diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..771f97f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,124 @@ + +# samples +samples/FallingBlocks/FallingBlocks.sdf +samples/FallingBlocks/FallingBlocks.sln.DotSettings +samples/FallingBlocks/FallingBlocks.suo +samples/FallingBlocks/FallingBlocks.v11.suo +samples/FallingBlocks/FallingBlocks.v12.suo +samples/FallingBlocks/FallingBlocks/Debug/ +samples/FallingBlocks/FallingBlocks/FallingBlocks.vcxproj.user +samples/HelloWorldDisplay/HelloWorldDisplay.sdf +samples/HelloWorldDisplay/HelloWorldDisplay.v12.suo +samples/HelloWorldDisplay/HelloWorldDisplay/HelloWorldDisplay.vcxproj.user +samples/HelloWorldDisplay/HelloWorldDisplay/Device-Debug/ +samples/HelloWorldDisplay/HelloWorldDisplay/Simulator-Debug/ + +# user configuration files +src_vs2010/BlackBerry.NativePlugin.opensdf +src_vs2010/BlackBerry.NativePlugin.sdf +src_vs2010/BlackBerry.NativePlugin.sln.DotSettings +src_vs2010/BlackBerry.NativePlugin.sln.DotSettings.user +src_vs2010/BlackBerry.NativePlugin.suo +src_vs2010/GDBParser/GDBParser.vcxproj.user +src_vs2010/BuildTasks/BlackBerry.BuildTasks.csproj.user +src_vs2010/DebugEngine/BlackBerry.DebugEngine.csproj.user +src_vs2010/DebugEngine/BlackBerry.DebugEngine.csproj.DotSettings +src_vs2010/GDBHost/BlackBerry.GDBHost.vcxproj.user +src_vs2010/NativeCore/BlackBerry.NativeCore.csproj.user +src_vs2010/Package/BlackBerry.Package.csproj.user +src_vs2010/Tasks/BlackBerry.Tasks.csproj.user +src_vs2010/UnitTests/UnitTests.csproj.user + +src_vs2012/BuildTasks/BlackBerry.BuildTasks.csproj.user +src_vs2012/BlackBerry.NativePlugin.sdf +src_vs2012/BlackBerry.NativePlugin.opensdf +src_vs2012/BlackBerry.NativePlugin.sln.DotSettings +src_vs2012/BlackBerry.NativePlugin.sln.DotSettings.user +src_vs2012/BlackBerry.NativePlugin.v11.suo +src_vs2012/GDBParser/GDBParser.vcxproj.user +src_vs2012/DebugEngine/BlackBerry.DebugEngine.csproj.user +src_vs2012/GDBHost/BlackBerry.GDBHost.vcxproj.user +src_vs2012/NativeCore/BlackBerry.NativeCore.csproj.user +src_vs2012/Package/BlackBerry.Package.csproj.user +src_vs2012/Package/BlackBerry.Package.csproj.DotSettings +src_vs2012/Tasks/BlackBerry.Tasks.csproj.user +src_vs2012/UnitTests/UnitTests.csproj.user + +src_vs2013/BuildTasks/BlackBerry.BuildTasks.csproj.user +src_vs2013/BlackBerry.NativePlugin.sdf +src_vs2013/BlackBerry.NativePlugin.opensdf +src_vs2013/BlackBerry.NativePlugin.sln.DotSettings +src_vs2013/BlackBerry.NativePlugin.sln.DotSettings.user +src_vs2013/BlackBerry.NativePlugin.v12.suo +src_vs2013/DebugEngine/BlackBerry.DebugEngine.csproj.user +src_vs2013/GDBHost/BlackBerry.GDBHost.vcxproj.user +src_vs2013/NativeCore/BlackBerry.NativeCore.csproj.user +src_vs2013/Package/BlackBerry.Package.csproj.user +src_vs2013/Tasks/BlackBerry.Tasks.csproj.user +src_vs2013/UnitTests/UnitTests.csproj.user + + +# build temp outputs +_BuildResults/ +BuildResults/ +src_vs2010/Debug/ +src_vs2010/Release/ +src_vs2010/GDBParser.UnitTests/bin/ +src_vs2010/GDBParser.UnitTests/obj/ +src_vs2010/GDBParser/Debug/ +src_vs2010/GDBParser/Release/ +src_vs2010/ipch/ +src_vs2010/BuildTasks/bin/ +src_vs2010/BuildTasks/obj/ +src_vs2010/DebugEngine/bin/ +src_vs2010/DebugEngine/obj/ +src_vs2010/GDBHost/Debug/ +src_vs2010/GDBHost/Release/ +src_vs2010/NativeCore/bin/ +src_vs2010/NativeCore/obj/ +src_vs2010/Package/bin/ +src_vs2010/Package/obj/ +src_vs2010/UnitTests/bin/ +src_vs2010/UnitTests/obj/ + +src_vs2012/Debug/ +src_vs2012/Release/ +src_vs2012/GDBParser/Debug/ +src_vs2012/GDBParser/Release/ +src_vs2012/GDBParser.UnitTests/bin/ +src_vs2012/GDBParser.UnitTests/obj/ +src_vs2012/ipch/ +src_vs2012/BuildTasks/bin/ +src_vs2012/BuildTasks/obj/ +src_vs2012/DebugEngine/bin/ +src_vs2012/DebugEngine/obj/ +src_vs2012/GDBHost/Debug/ +src_vs2012/GDBHost/Release/ +src_vs2012/NativeCore/bin/ +src_vs2012/NativeCore/obj/ +src_vs2012/Package/bin/ +src_vs2012/Package/obj/ +src_vs2012/UnitTests/bin/ +src_vs2012/UnitTests/obj/ + +src_vs2013/Debug/ +src_vs2013/Release/ +src_vs2013/GDBParser.UnitTests/bin/ +src_vs2013/GDBParser.UnitTests/obj/ +src_vs2013/GDBParser/Debug/ +src_vs2013/GDBParser/Release/ +src_vs2013/ipch/ +src_vs2013/BuildTasks/bin/ +src_vs2013/BuildTasks/obj/ +src_vs2013/DebugEngine/bin/ +src_vs2013/DebugEngine/obj/ +src_vs2013/GDBHost/Debug/ +src_vs2013/GDBHost/Release/ +src_vs2013/NativeCore/bin/ +src_vs2013/NativeCore/obj/ +src_vs2013/Package/bin/ +src_vs2013/Package/obj/ +src_vs2013/UnitTests/bin/ +src_vs2013/UnitTests/obj/ + + diff --git a/README.md b/README.md index 77982f0d..fe1c9266 100644 --- a/README.md +++ b/README.md @@ -6,24 +6,36 @@ All assets in this repository, unless otherwise stated through sub-directory LIC ##Build requirements Install -* [Microsoft Visual Studio Professional 2012 SDK] (http://www.microsoft.com/en-us/download/details.aspx?id=30668) - -or - * [Microsoft Visual Studio Professional 2013 SDK] (http://www.microsoft.com/en-us/download/details.aspx?id=40758) +Note: Currently, there is a bug in DIA SDK of Visual Studio 2013. +If Microsoft Visual Studio 2013 is installed on a machine where Microsoft Visual Studio 2012 was installed, the DIA SDK folder for Microsoft Visual Studio 2013 is installed in the DIA SDK folder for Microsoft Visual Studio 2012. +More info [here] (http://connect.microsoft.com/VisualStudio/feedback/details/814147/dia-sdk-installed-into-wrong-directory). + ##Build commands -1. VSNDKPluginBuild.bat – A batch file that builds the various components of the BlackBerry Native Plug-in to the ..\buildresults folder. -2. VSNDKPluginSetup.bat – A batch file that installs the newly built components of the BlackBerry Native Plug-in to the correct locations on your computer. +**build.bat** – A batch file that builds the various components of the BlackBerry Native Plug-in for Microsoft Visual Studio to the "_BuildResults" folder. + +**setup.bat** – A batch file that installs the newly built components of the BlackBerry Native Plug-in for Microsoft Visual Studio to the correct locations on your computer. + +Examples: + + **build.bat** - default, builds everything + **build.bat vs2010** - builds only for Microsoft Visual Studio 2010 + **build.bat vs2012 "/out:D:\Shared folder\\_BuildResults"** - builds only for Microsoft Visual Studio 2012 into the specified directory + + **setup.bat** - installs the plug-in for all Microsoft Visual Studio versions + **setup.bat vs2010** - installs the plug-in for only Microsoft Visual Studio 2010 + **setup.bat vs2012 /no-tools** - installs the plug-in for Microsoft Visual Studio 2012 without copying the bbndk_vs and qnxtools folders + **setup.bat vs2012 /msbuild-only** - updates only the local MSBuild for Microsoft Visual Studio 2012 and adds the 'BlackBerry' and 'BlackBerrySimulator' target platforms ##Contributing The BlackBerry Native Plug-in for Microsoft Visual Studio project currently contains the following code branches: -**Master Branch** - The master branch contains the latest production release of the source code. This code is considered stable and is fully tested by the Test team. You can [download the binaries] (http://developer.blackberry.com/native/downloads/) from the Downloads page on the BlackBerry developer website. +**Master Branch** - This branch contains the latest production release of the source code. This code is considered stable and is fully tested by the test team. You can [download the binaries] (http://developer.blackberry.com/native/downloads/) from the Downloads page on the BlackBerry developer website. -**Next Branch** - The next branch contains the latest beta release of the source code. This code may be unstable and is not fully tested because it has passed unit tests only. At some point, a full regression test cycle is performed on the next branch and the code is promoted to the master branch. +**Next Branch** - This branch contains the latest beta release of the source code. This code may be unstable and is not fully tested because it has passed unit tests only. At some point, a full regression test cycle is performed on the next branch and the code is promoted to the master branch. -**Feature Branch** - Feature branches contain the code changes required to implement specific features or issues being worked on for the next release. This code is considered unstable. These branches are denoted by the following naming scheme in the repository: next-### (where ### is the related issue number). When implementation is completed, the branch is unit and integration tested and then merged into the next branch. +**Feature Branch** - This branch contains the code changes required to implement specific features or issues being worked on for the next release. This code is considered unstable. These branches are denoted by the following naming scheme in the repository: next-### (where ### is the related issue number). When implementation is completed, the branch is unit and integration tested and then merged into the next branch. **To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).** @@ -42,5 +54,5 @@ The BlackBerry Native Plug-in for Microsoft Visual Studio project currently cont * [Gustavo Arnold](http://github.com/guarnold) ## Reference material -* [Using Microsoft Visual Studio] (https://developer.blackberry.com/native/documentation/core/vs_using_microsoft_visual_studio.html) -* Although Microsoft Visual Studio 2010 is no longer supported, you can still [download the plug-in and the docs] (http://developer.blackberry.com/native/downloads/) from the Downloads page. +* [Microsoft Visual Studio:] (http://developer.blackberry.com/native/documentation/dev/visual_studio/vs_using_microsoft_visual_studio.html) +* [GDB Commands] (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI.html) diff --git a/VSNDKPluginBuild.bat b/VSNDKPluginBuild.bat deleted file mode 100644 index 0c26eee5..00000000 --- a/VSNDKPluginBuild.bat +++ /dev/null @@ -1,60 +0,0 @@ -echo off - -REM ******************************************************************************************** -REM Declare Constants -REM ******************************************************************************************** -set thisDir=%~dp0 -set buildresults="%thisDir%\..\buildresults" -set dotNetFrameworkPath="C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MsBuild.exe" -set dotNetFrameworkPath2013="C:\Program Files (x86)\MSBuild\12.0\Bin\MsBuild.exe" -set solutionPath2010="%thisDir%\src\VSNDK.sln" -set AddIn2012="%thisDir%\src_vs2012\VSNDK.AddIn\VSNDK.AddIn.csproj" -set DebugEngine2012="%thisDir%\src_vs2012\VSNDK.DebugEngine\VSNDK.DebugEngine.csproj" -set GDWrapper2012="%thisDir%\src_vs2012\GDBWrapper\GDBWrapper.vcxproj" -set VSPackage2012="%thisDir%\src_vs2012\VSNDK.Package\VSNDK.Package.csproj" -set VSTasks2012="%thisDir%\src_vs2012\VSNDK.Tasks\VSNDK.Tasks.csproj" -set AddIn2013="%thisDir%\src_vs2013\VSNDK.AddIn\VSNDK.AddIn.csproj" -set DebugEngine2013="%thisDir%\src_vs2013\VSNDK.DebugEngine\VSNDK.DebugEngine.csproj" -set GDWrapper2013="%thisDir%\src_vs2013\GDBWrapper\GDBWrapper.vcxproj" -set VSPackage2013="%thisDir%\src_vs2013\VSNDK.Package\VSNDK.Package.csproj" -set VSTasks2013="%thisDir%\src_vs2013\VSNDK.Tasks\VSNDK.Tasks.csproj" - -REM ******************************************************************************************** -REM Clean up old bin folder -REM ******************************************************************************************** -echo Removing previous code -if not exist "%buildresults%" goto build - echo Remove Build Results - RMDIR /Q "%buildresults%" /S - MKDIR "%buildresults%" -:build - -REM ******************************************************************************************** -REM Build VS2010 -REM ******************************************************************************************** -REM echo Building Solution for VS2010 -REM %dotNetFrameworkPath% %solutionPath2010% /property:Configuration=Release /target:Clean;Build /p:OutputPath="%buildresults%\VS2010" > %buildresult%\VS2010_buildlog.txt -REM echo Build Success - -REM ******************************************************************************************** -REM Build VS2012 -REM ******************************************************************************************** -echo Building Solution for VS2012 -%dotNetFrameworkPath% %AddIn2012% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=11.0 /p:OutputPath="%buildresults%\VS2012" > %buildresult%\VS2012_buildlog_AddIn.txt -%dotNetFrameworkPath% %DebugEngine2012% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=11.0 /p:OutputPath="%buildresults%\VS2012" > %buildresult%\VS2012_buildlog_DBEngine.txt -%dotNetFrameworkPath% %GDWrapper2012% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=11.0 /p:OutputPath="%buildresults%\VS2012" > %buildresult%\VS2012_buildlog_GDBWrapper.txt -%dotNetFrameworkPath% %VSPackage2012% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=11.0 /p:OutputPath="%buildresults%\VS2012" > %buildresult%\VS2012_buildlog_Package.txt -%dotNetFrameworkPath% %VSTasks2012% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=11.0 /p:OutputPath="%buildresults%\VS2012" > %buildresult%\VS2012_buildlog_Tasks.txt -echo Build Success - -REM ******************************************************************************************** -REM Build VS2013 -REM ******************************************************************************************** -echo Building Solution for VS2013 -%dotNetFrameworkPath2013% %AddIn2013% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=12.0 /p:OutputPath="%buildresults%\VS2013" > %buildresults%\VS2013_buildlog_AddIn.txt -%dotNetFrameworkPath2013% %DebugEngine2013% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=12.0 /p:OutputPath="%buildresults%\VS2013" > %buildresults%\VS2013_buildlog_DBEngine.txt -%dotNetFrameworkPath2013% %GDWrapper2013% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=12.0 /p:OutputPath="%buildresults%\VS2013" > %buildresults%\VS2013_buildlog_GDBWrapper.txt -%dotNetFrameworkPath2013% %VSPackage2013% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=12.0 /p:OutputPath="%buildresults%\VS2013" > %buildresults%\VS2013_buildlog_Package.txt -%dotNetFrameworkPath2013% %VSTasks2013% /property:Configuration=Release /target:Clean;Build /p:VisualStudioVersion=12.0 /p:OutputPath="%buildresults%\VS2013" > %buildresults%\VS2013_buildlog_Tasks.txt -echo Build Success - diff --git a/VSNDKPluginSetup.bat b/VSNDKPluginSetup.bat deleted file mode 100644 index dcf95c0e..00000000 --- a/VSNDKPluginSetup.bat +++ /dev/null @@ -1,118 +0,0 @@ -echo off - -REM //******************************************************************************************** -REM // Batch Constants -REM // thisDir = working directory of current batch file. -REM // buildresults = Directory containing the build results. -REM ********************************************************************************************** -set thisDir=%~dp0 -set buildresults=%thisDir%..\buildresults\VS2010 -set ProgRoot=%ProgramFiles(x86)% -set AllUsers=%ALLUSERSPROFILE% -set AppData=%APPDATA% -set drive=%cd:~0,3% - -if "%ProgramFiles(x86)%XXX"=="XXX" ( -echo 32-bit -set ProgRoot=%ProgramFiles% -) -echo %ProgRoot% - -REM //******************************************************************************************** -REM // Copy AddIn Files -REM ********************************************************************************************** -echo Copy "%buildresults%\VSNDK.AddIn.AddIn" to "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -copy "%buildresults%\VSNDK.AddIn.AddIn" "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -echo Copy "%buildresults%\VSNDK.AddIn.dll" to "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" -copy "%buildresults%\VSNDK.AddIn.dll" "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" - -REM //******************************************************************************************** -REM // Copy GDBParser and DebugEngine Files -REM ********************************************************************************************** -echo Make Directory "%ProgRoot%\BlackBerry\VSPlugin-NDK" -md "%ProgRoot%\BlackBerry\VSPlugin-NDK" -echo Copy "%buildresults%\GDBParser.dll" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBParser.dll" -copy "%buildresults%\GDBParser.dll" "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBParser.dll" -echo Copy "%buildresults%\GDBWrapper.exe" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -copy "%buildresults%\GDBWrapper.exe" "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -echo Copy "%buildresults%\Instructions.txt" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -copy "%buildresults%\Instructions.txt" "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -echo Copy "%buildresults%\VSNDK.DebugEngine.dll" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" -copy "%buildresults%\VSNDK.DebugEngine.dll" "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" - -REM //******************************************************************************************** -REM // Copy Package Files -REM ********************************************************************************************** -echo Make Directory "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin" -md "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin" -echo "%buildresults%\extension.vsixmanifest" to "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\extension.vsixmanifest" -copy "%buildresults%\extension.vsixmanifest" "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\extension.vsixmanifest" -echo "%buildresults%\VSNDK.Package.dll" to "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -copy "%buildresults%\VSNDK.Package.dll" "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -echo "%buildresults%\VSNDK.Package.pkgdef" to "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" -copy "%buildresults%\VSNDK.Package.pkgdef" "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" - -REM //******************************************************************************************** -REM // Copy MSBuild Files -REM ********************************************************************************************** -echo Copy BlackBerry MSBuild directory -xcopy "%buildresults%\BlackBerry" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerry" /e /i /y -copy "%buildresults%\VSNDK.Tasks.dll" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerry\VSNDK.Tasks.dll" -echo Copy GDBWrapper.exe -echo Copy BlackBerrySimulator MSBuild directory -xcopy "%buildresults%\BlackBerrySimulator" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerrySimulator" /e /i /y -copy "%buildresults%\VSNDK.Tasks.dll" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerrySimulator\VSNDK.Tasks.dll" - -REM //******************************************************************************************** -REM // Copy Template Files -REM ********************************************************************************************** -echo Copy BlackBerry VCWizards directory -xcopy "%buildresults%\Templates\VCWizards" "%ProgRoot%\Microsoft Visual Studio 10.0\VC\VCWizards\CodeWiz" /e /i /y - -REM //******************************************************************************************** -REM // Copy SDK Command Line Tool Files -REM ********************************************************************************************** -echo xcopy "%thisDir%bbndk_vs" "%drive%bbndk_vs" /e /i /y -md "%drive%bbndk_vs" -xcopy "%thisDir%bbndk_vs" "%drive%bbndk_vs" /e /i /y - -REM //******************************************************************************************** -REM // Copy QNX Tools -REM ********************************************************************************************** -echo xcopy "%thisDir%qnxtools" "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" /e /i /y -md "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" -xcopy "%thisDir%qnxtools" "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" /e /i /y - -REM //******************************************************************************************** -REM // Register clases -REM ********************************************************************************************** -echo registering setup -REGEDIT.EXE /S "thisDir"VSNDKPluginSetup.reg - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/VSNDKPluginSetup.reg b/VSNDKPluginSetup.reg deleted file mode 100644 index 3f826dd5..00000000 --- a/VSNDKPluginSetup.reg +++ /dev/null @@ -1,102 +0,0 @@ -REGEDIT4 - -[HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin] -"device_password"="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA7fSRRS7m1Em+yoK0ioAYhwQAAAACAAAAAAADZgAAwAAAABAAAAAb9QNNQPNG1qB5uDOFabBjAAAAAASAAACgAAAAEAAAAOu49T6nbn0mHnBMoGvre5cIAAAA2NG7RxOCGYgUAAAAi84MGQ9ELFYdXZ5pOhVSayDK2V4=" -"device_IP"="169.254.0.1" -"simulator_password"="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA7fSRRS7m1Em+yoK0ioAYhwQAAAACAAAAAAADZgAAwAAAABAAAAAb9QNNQPNG1qB5uDOFabBjAAAAAASAAACgAAAAEAAAAOu49T6nbn0mHnBMoGvre5cIAAAA2NG7RxOCGYgUAAAAi84MGQ9ELFYdXZ5pOhVSayDK2V4=" -"simulator_IP"="" -"NDKHostPath"="" -"NDKTargetPath"="" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"AddressBP"=dword:00000000 -"AutoSelectPriority"=dword:00000004 -"CallstackBP"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"Attach"=dword:00000001 -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -"AlwaysLoadLocal"="1" -"PortSupplier"="{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}" -"Name"="VSNDK Debug Engine" -@="guidDebuggingSampleEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7ProgramProvider" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7Engine" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}] -@="BlackBerrySupplier" -"Assembly"="VSNDK.DebugEngine" -"Class"="VSNDK.DebugEngine.AD7PortSupplier" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"ThreadingModel"="Free" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\AD7Metrics\PortSupplier\{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}] -"Name"="BlackBerry" -"DisallowUserEnteredPorts"=dword:00000000 -"CLSID"="{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}" -@="Visual Studio Plug-in for BlackBerry" -"PortPickerCLSID"="{3FAA02D6-72D8-4F69-A1E6-BB05ECB4E37A}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"AlwaysLoadLocal"="1" -"PortSupplier"="{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}" -"Name"="VSNDK Debug Engine" -"CallstackBP"=dword:00000001 -"AutoSelectPriority"=dword:00000004 -"AddressBP"=dword:00000000 -"Attach"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -@="guidDebuggingSampleEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7ProgramProvider" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"Assembly"="VSNDK.DebugEngine" -"Class"="VSNDK.DebugEngine.AD7Engine" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"Attach"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -@="guidDebuggingSampleEngine" -"AlwaysLoadLocal"="1" -"AutoSelectPriority"=dword:00000004 -"PortSupplier"="{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}" -"Name"="VSNDK Debug Engine" -"CallstackBP"=dword:00000001 -"AddressBP"=dword:00000000 - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" \ No newline at end of file diff --git a/VSNDKPluginSetupVS2012.bat b/VSNDKPluginSetupVS2012.bat deleted file mode 100644 index 579ee868..00000000 --- a/VSNDKPluginSetupVS2012.bat +++ /dev/null @@ -1,118 +0,0 @@ -echo off - -REM //******************************************************************************************** -REM // Batch Constants -REM // thisDir = working directory of current batch file. -REM // buildresults = Directory containing the build results. -REM ********************************************************************************************** -set thisDir=%~dp0 -set buildresults=%thisDir%..\buildresults\VS2012 -set ProgRoot=%ProgramFiles(x86)% -set AllUsers=%ALLUSERSPROFILE% -set AppData=%APPDATA% -set drive=%cd:~0,3% - -if "%ProgramFiles(x86)%XXX"=="XXX" ( -echo 32-bit -set ProgRoot=%ProgramFiles% -) -echo %ProgRoot% - -REM //******************************************************************************************** -REM // Copy AddIn Files -REM ********************************************************************************************** -echo Copy "%buildresults%\VSNDK.AddIn.AddIn" to "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -copy "%buildresults%\VSNDK.AddIn.AddIn" "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -echo Copy "%buildresults%\VSNDK.AddIn.dll" to "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" -copy "%buildresults%\VSNDK.AddIn.dll" "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" - -REM //******************************************************************************************** -REM // Copy GDBParser and DebugEngine Files -REM ********************************************************************************************** -echo Make Directory "%ProgRoot%\BlackBerry\VSPlugin-NDK" -md "%ProgRoot%\BlackBerry\VSPlugin-NDK" -echo "%buildresults%\GDBParser.dll" to "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\GDBParser.dll" -copy "%buildresults%\GDBParser.dll" "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\GDBParser.dll" -echo Copy "%buildresults%\GDBWrapper.exe" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -copy "%buildresults%\GDBWrapper.exe" "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -echo Copy "%buildresults%\Instructions.txt" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -copy "%buildresults%\Instructions.txt" "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -echo Copy "%buildresults%\VSNDK.DebugEngine.dll" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" -copy "%buildresults%\VSNDK.DebugEngine.dll" "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" - -REM //******************************************************************************************** -REM // Copy Package Files -REM ********************************************************************************************** -echo Make Directory "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin" -md "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin" -echo "%buildresults%\extension.vsixmanifest" to "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\extension.vsixmanifest" -copy "%buildresults%\extension.vsixmanifest" "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\extension.vsixmanifest" -echo "%buildresults%\VSNDK.Package.dll" to "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -copy "%buildresults%\VSNDK.Package.dll" "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -echo "%buildresults%\VSNDK.Package.pkgdef" to "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" -copy "%buildresults%\VSNDK.Package.pkgdef" "%ProgRoot%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" - -REM //******************************************************************************************** -REM // Copy MSBuild Files -REM ********************************************************************************************** -echo Copy BlackBerry MSBuild directory -xcopy "%buildresults%\BlackBerry" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerry" /e /i /y -copy "%buildresults%\VSNDK.Tasks.dll" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerry\VSNDK.Tasks.dll" -echo Copy GDBWrapper.exe -echo Copy BlackBerrySimulator MSBuild directory -xcopy "%buildresults%\BlackBerrySimulator" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerrySimulator" /e /i /y -copy "%buildresults%\VSNDK.Tasks.dll" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerrySimulator\VSNDK.Tasks.dll" - -REM //******************************************************************************************** -REM // Copy Template Files -REM ********************************************************************************************** -echo Copy BlackBerry VCWizards directory -xcopy "%buildresults%\Templates\VCWizards" "%ProgRoot%\Microsoft Visual Studio 11.0\VC\VCWizards\CodeWiz" /e /i /y - -REM //******************************************************************************************** -REM // Copy SDK Command Line Tool Files -REM ********************************************************************************************** -echo xcopy "%thisDir%bbndk_vs" "%drive%bbndk_vs" /e /i /y -md "%drive%bbndk_vs" -xcopy "%thisDir%bbndk_vs" "%drive%bbndk_vs" /e /i /y - -REM //******************************************************************************************** -REM // Copy QNX Tools -REM ********************************************************************************************** -echo xcopy "%thisDir%qnxtools" "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" /e /i /y -md "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" -xcopy "%thisDir%qnxtools" "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" /e /i /y - -REM //******************************************************************************************** -REM // Register clases -REM ********************************************************************************************** -echo registering setup -REGEDIT.EXE /S "thisDir"VSNDKPluginSetup2012.reg - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/VSNDKPluginSetupVS2012.reg b/VSNDKPluginSetupVS2012.reg deleted file mode 100644 index 5245ef89..00000000 --- a/VSNDKPluginSetupVS2012.reg +++ /dev/null @@ -1,103 +0,0 @@ -REGEDIT4 - -[HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin] -"device_password"="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA7fSRRS7m1Em+yoK0ioAYhwQAAAACAAAAAAADZgAAwAAAABAAAAAb9QNNQPNG1qB5uDOFabBjAAAAAASAAACgAAAAEAAAAOu49T6nbn0mHnBMoGvre5cIAAAA2NG7RxOCGYgUAAAAi84MGQ9ELFYdXZ5pOhVSayDK2V4=" -"device_IP"="169.254.0.1" -"simulator_password"="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA7fSRRS7m1Em+yoK0ioAYhwQAAAACAAAAAAADZgAAwAAAABAAAAAb9QNNQPNG1qB5uDOFabBjAAAAAASAAACgAAAAEAAAAOu49T6nbn0mHnBMoGvre5cIAAAA2NG7RxOCGYgUAAAAi84MGQ9ELFYdXZ5pOhVSayDK2V4=" -"simulator_IP"="" -"NDKHostPath"="" -"NDKTargetPath"="" -"NDKRemotePath"="" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"AddressBP"=dword:00000000 -"AutoSelectPriority"=dword:00000004 -"CallstackBP"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"Attach"=dword:00000001 -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -"AlwaysLoadLocal"="1" -"PortSupplier"="{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}" -"Name"="VSNDK Debug Engine" -@="guidDebuggingSampleEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7ProgramProvider" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7Engine" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\CLSID\{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}] -@="BlackBerrySupplier" -"Assembly"="VSNDK.DebugEngine" -"Class"="VSNDK.DebugEngine.AD7PortSupplier" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"ThreadingModel"="Free" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\AD7Metrics\PortSupplier\{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}] -"Name"="BlackBerry" -"DisallowUserEnteredPorts"=dword:00000000 -"CLSID"="{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}" -@="Visual Studio Plug-in for BlackBerry" -"PortPickerCLSID"="{3FAA02D6-72D8-4F69-A1E6-BB05ECB4E37A}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"AlwaysLoadLocal"="1" -"PortSupplier"="{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}" -"Name"="VSNDK Debug Engine" -"CallstackBP"=dword:00000001 -"AutoSelectPriority"=dword:00000004 -"AddressBP"=dword:00000000 -"Attach"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -@="guidDebuggingSampleEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7ProgramProvider" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"Assembly"="VSNDK.DebugEngine" -"Class"="VSNDK.DebugEngine.AD7Engine" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"Attach"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -@="guidDebuggingSampleEngine" -"AlwaysLoadLocal"="1" -"AutoSelectPriority"=dword:00000004 -"PortSupplier"="{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}" -"Name"="VSNDK Debug Engine" -"CallstackBP"=dword:00000001 -"AddressBP"=dword:00000000 - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" \ No newline at end of file diff --git a/VSNDKPluginSetupVS2013.bat b/VSNDKPluginSetupVS2013.bat deleted file mode 100644 index af05df1f..00000000 --- a/VSNDKPluginSetupVS2013.bat +++ /dev/null @@ -1,118 +0,0 @@ -echo off - -REM //******************************************************************************************** -REM // Batch Constants -REM // thisDir = working directory of current batch file. -REM // buildresults = Directory containing the build results. -REM ********************************************************************************************** -set thisDir=%~dp0 -set buildresults=%thisDir%..\buildresults\VS2013 -set ProgRoot=%ProgramFiles(x86)% -set AllUsers=%ALLUSERSPROFILE% -set AppData=%APPDATA% -set drive=%cd:~0,3% - -if "%ProgramFiles(x86)%XXX"=="XXX" ( -echo 32-bit -set ProgRoot=%ProgramFiles% -) -echo %ProgRoot% - -REM //******************************************************************************************** -REM // Copy AddIn Files -REM ********************************************************************************************** -echo Copy "%buildresults%\VSNDK.AddIn.AddIn" to "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -copy "%buildresults%\VSNDK.AddIn.AddIn" "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -echo Copy "%buildresults%\VSNDK.AddIn.dll" to "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" -copy "%buildresults%\VSNDK.AddIn.dll" "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" - -REM //******************************************************************************************** -REM // Copy GDBParser and DebugEngine Files -REM ********************************************************************************************** -echo Make Directory "%ProgRoot%\BlackBerry\VSPlugin-NDK" -md "%ProgRoot%\BlackBerry\VSPlugin-NDK" -echo "%buildresults%\GDBParser.dll" to "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\GDBParser.dll" -copy "%buildresults%\GDBParser.dll" "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\GDBParser.dll" -echo Copy "%buildresults%\GDBWrapper.exe" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -copy "%buildresults%\GDBWrapper.exe" "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -echo Copy "%buildresults%\Instructions.txt" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -copy "%buildresults%\Instructions.txt" "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -echo Copy "%buildresults%\VSNDK.DebugEngine.dll" to "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" -copy "%buildresults%\VSNDK.DebugEngine.dll" "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" - -REM //******************************************************************************************** -REM // Copy Package Files -REM ********************************************************************************************** -echo Make Directory "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin" -md "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin" -echo "%buildresults%\extension.vsixmanifest" to "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\extension.vsixmanifest" -copy "%buildresults%\extension.vsixmanifest" "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\extension.vsixmanifest" -echo "%buildresults%\VSNDK.Package.dll" to "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -copy "%buildresults%\VSNDK.Package.dll" "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -echo "%buildresults%\VSNDK.Package.pkgdef" to "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" -copy "%buildresults%\VSNDK.Package.pkgdef" "%ProgRoot%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" - -REM //******************************************************************************************** -REM // Copy MSBuild Files -REM ********************************************************************************************** -echo Copy BlackBerry MSBuild directory -xcopy "%buildresults%\BlackBerry" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\BlackBerry" /e /i /y -copy "%buildresults%\VSNDK.Tasks.dll" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\BlackBerry\VSNDK.Tasks.dll" -echo Copy GDBWrapper.exe -echo Copy BlackBerrySimulator MSBuild directory -xcopy "%buildresults%\BlackBerrySimulator" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\BlackBerrySimulator" /e /i /y -copy "%buildresults%\VSNDK.Tasks.dll" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\BlackBerrySimulator\VSNDK.Tasks.dll" - -REM //******************************************************************************************** -REM // Copy Template Files -REM ********************************************************************************************** -echo Copy BlackBerry VCWizards directory -xcopy "%buildresults%\Templates\VCWizards" "%ProgRoot%\Microsoft Visual Studio 12.0\VC\VCWizards\CodeWiz" /e /i /y - -REM //******************************************************************************************** -REM // Copy SDK Command Line Tool Files -REM ********************************************************************************************** -echo xcopy "%thisDir%bbndk_vs" "%drive%bbndk_vs" /e /i /y -md "%drive%bbndk_vs" -xcopy "%thisDir%bbndk_vs" "%drive%bbndk_vs" /e /i /y - -REM //******************************************************************************************** -REM // Copy QNX Tools -REM ********************************************************************************************** -echo xcopy "%thisDir%qnxtools" "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" /e /i /y -md "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" -xcopy "%thisDir%qnxtools" "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" /e /i /y - -REM //******************************************************************************************** -REM // Register clases -REM ********************************************************************************************** -echo registering setup -REGEDIT.EXE /S "thisDir"VSNDKPluginSetup2013.reg - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/VSNDKPluginSetupVS2013.reg b/VSNDKPluginSetupVS2013.reg deleted file mode 100644 index 3061b5ed..00000000 --- a/VSNDKPluginSetupVS2013.reg +++ /dev/null @@ -1,103 +0,0 @@ -REGEDIT4 - -[HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin] -"device_password"="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA7fSRRS7m1Em+yoK0ioAYhwQAAAACAAAAAAADZgAAwAAAABAAAAAb9QNNQPNG1qB5uDOFabBjAAAAAASAAACgAAAAEAAAAOu49T6nbn0mHnBMoGvre5cIAAAA2NG7RxOCGYgUAAAAi84MGQ9ELFYdXZ5pOhVSayDK2V4=" -"device_IP"="169.254.0.1" -"simulator_password"="AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA7fSRRS7m1Em+yoK0ioAYhwQAAAACAAAAAAADZgAAwAAAABAAAAAb9QNNQPNG1qB5uDOFabBjAAAAAASAAACgAAAAEAAAAOu49T6nbn0mHnBMoGvre5cIAAAA2NG7RxOCGYgUAAAAi84MGQ9ELFYdXZ5pOhVSayDK2V4=" -"simulator_IP"="" -"NDKHostPath"="" -"NDKTargetPath"="" -"NDKRemotePath"="" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"AddressBP"=dword:00000000 -"AutoSelectPriority"=dword:00000004 -"CallstackBP"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"Attach"=dword:00000001 -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -"AlwaysLoadLocal"="1" -"PortSupplier"="{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}" -"Name"="VSNDK Debug Engine" -@="guidDebuggingSampleEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7ProgramProvider" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7Engine" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\CLSID\{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}] -@="BlackBerrySupplier" -"Assembly"="VSNDK.DebugEngine" -"Class"="VSNDK.DebugEngine.AD7PortSupplier" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"ThreadingModel"="Free" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\AD7Metrics\PortSupplier\{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}] -"Name"="BlackBerry" -"DisallowUserEnteredPorts"=dword:00000000 -"CLSID"="{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}" -@="Visual Studio Plug-in for BlackBerry" -"PortPickerCLSID"="{3FAA02D6-72D8-4F69-A1E6-BB05ECB4E37A}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"AlwaysLoadLocal"="1" -"PortSupplier"="{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}" -"Name"="VSNDK Debug Engine" -"CallstackBP"=dword:00000001 -"AutoSelectPriority"=dword:00000004 -"AddressBP"=dword:00000000 -"Attach"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -@="guidDebuggingSampleEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" -"Class"="VSNDK.DebugEngine.AD7ProgramProvider" -"Assembly"="VSNDK.DebugEngine" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] -"CodeBase"="C:\\Program Files (x86)\\BlackBerry\\VSPlugin-NDK\\VSNDK.DebugEngine.dll" -"Assembly"="VSNDK.DebugEngine" -"Class"="VSNDK.DebugEngine.AD7Engine" -"InprocServer32"="c:\\windows\\system32\\mscoree.dll" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] -"Attach"=dword:00000001 -"ProgramProvider"="{AD06FD46-C790-4D5C-A274-8815DF9511B8}" -"CLSID"="{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}" -@="guidDebuggingSampleEngine" -"AlwaysLoadLocal"="1" -"AutoSelectPriority"=dword:00000004 -"PortSupplier"="{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}" -"Name"="VSNDK Debug Engine" -"CallstackBP"=dword:00000001 -"AddressBP"=dword:00000000 - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] -"guidNativeOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidCOMPlusOnlyEng"="{449EC4CC-30D2-4032-9256-EE18EB41B62B}" -"guidScriptEng"="{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}" -"guidCOMPlusNativeEng"="{92EF0900-2251-11D2-B72E-0000F87572EF}" \ No newline at end of file diff --git a/VSNDKPluginUninstall.bat b/VSNDKPluginUninstall.bat deleted file mode 100644 index 7f03daf6..00000000 --- a/VSNDKPluginUninstall.bat +++ /dev/null @@ -1,105 +0,0 @@ -echo off - -REM //******************************************************************************************** -REM // Batch Constants -REM // thisDir = working directory of current batch file. -REM // buildresults = Directory containing the build results. -REM ********************************************************************************************** -set thisDir=%~dp0 -set buildresults=%thisDir%..\buildresults -set ProgRoot=%ProgramFiles(x86)% -set AllUsers=%ALLUSERSPROFILE% -set AppData=%APPDATA% -set drive=%cd:~0,3% - -if "%ProgramFiles(x86)%XXX"=="XXX" ( -echo 32-bit -set ProgRoot=%ProgramFiles% -) -echo %ProgRoot% - -REM //******************************************************************************************** -REM // Remove AddIn Files -REM ********************************************************************************************** -echo Deleting "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -del "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.AddIn" -echo Deleting "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" -del "%AllUsers%\Microsoft\MSEnvShared\Addins\VSNDK.AddIn.dll" - -REM //******************************************************************************************** -REM // Remove GDBParser and DebugEngine Files -REM ********************************************************************************************** -echo Deleting "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBParser.dll" -del "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBParser.dll" -echo Deleting "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -del "%ProgRoot%\BlackBerry\VSPlugin-NDK\GDBWrapper.exe" -echo Deleting "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -del "%ProgRoot%\BlackBerry\VSPlugin-NDK\Instructions.txt" -echo Deleting "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" -del "%ProgRoot%\BlackBerry\VSPlugin-NDK\VSNDK.DebugEngine.dll" -echo Remove Directory "%ProgRoot%\BlackBerry\VSPlugin-NDK" -rd "%ProgRoot%\BlackBerry\VSPlugin-NDK" - -REM //******************************************************************************************** -REM // Remove Package Files -REM ********************************************************************************************** -echo Deleting "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\extension.vsixmanifest" -del "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\extension.manifest" -echo Deleting "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -del "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.dll" -echo Deleting "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" -del "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin\VSNDK.Package.pkgdef" -echo Remove Directory "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin" -rd "%ProgRoot%\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\NDK Plugin" - - -REM //******************************************************************************************** -REM // Remove MSBuild Files -REM ********************************************************************************************** -echo Delete BlackBerry MSBuild directory -rd "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerry" /s /q -echo Delete BlackBerrySimulator MSBuild directory -rd "%buildresults%\BlackBerrySimulator" "%ProgRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms\BlackBerrySimulator" /s /q - -REM //******************************************************************************************** -REM // Remove Template Files -REM ********************************************************************************************** -echo Delete BlackBerry VCWizards directory -rd "%ProgRoot%\Microsoft Visual Studio 10.0\VC\VCWizards\CodeWiz\BlackBerry" /s /q - -REM //******************************************************************************************** -REM // Remove command line tools -REM ********************************************************************************************** -echo Delete %drive%bbndk_vs directory -rd "%drive%bbndk_vs" /s /q - -REM //******************************************************************************************** -REM // Remove qnx tools -REM ********************************************************************************************** -echo Delete "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" directory -rd "%ProgRoot%\BlackBerry\VSPlugin-NDK\qnxtools" /s /q - -REM //******************************************************************************************** -REM // Register clases -REM ********************************************************************************************** -echo Unregistering - %thisDir%VSNDKPluginUninstall.reg -REGEDIT.EXE -S %thisDir%VSNDKPluginUninstall.reg - - - - - - - - - - - - - - - - - - - diff --git a/VSNDKPluginUninstall.reg b/VSNDKPluginUninstall.reg deleted file mode 100644 index 634e9486..00000000 --- a/VSNDKPluginUninstall.reg +++ /dev/null @@ -1,27 +0,0 @@ -REGEDIT4 - -[-HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\AD7Metrics\PortSupplier\{92A2B753-00BD-40FF-9964-6AB64A1D6C9F}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\CLSID\{AD06FD46-C790-4D5C-A274-8815DF9511B8}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\CLSID\{904AA6E0-942C-4D11-9094-7BAAEB3EE4B9}] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}\IncompatibleList] - -[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\AD7Metrics\Engine\{E5A37609-2F43-4830-AA85-D94CFA035DD2}] \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 00000000..f17bd5ba --- /dev/null +++ b/build.bat @@ -0,0 +1,211 @@ +@echo off +echo Starting... +setlocal EnableExtensions + +REM ******************************************************************************************** +REM Allow selective build +REM ******************************************************************************************** + +:: Process parameters, to limit the solutions to build +if "%~1" == "" ( + set ActionClean=1 + set ActionBuildPackage=0 + set ActionBuildVS2010=1 + set ActionBuildVS2012=1 + set ActionBuildVS2013=1 + set PackageVersion= +) else ( + set ActionClean=1 + set ActionBuildPackage=0 + set ActionBuildVS2010=0 + set ActionBuildVS2012=0 + set ActionBuildVS2013=0 + set PackageVersion= +) + +:args_parsing +set arg=%~1 +if "%arg%" == "" (goto args_parsing_done) +if /i "%arg%" == "/all" set ActionBuildVS2010=1 && set ActionBuildVS2012=1 && set ActionBuildVS2013=1 +if /i "%arg%" == "/noclean" set ActionClean=0 +if /i "%arg%" == "/no-clean" set ActionClean=0 +if /i "%arg%" == "vs2010" set ActionBuildVS2010=1 +if /i "%arg%" == "vs2012" set ActionBuildVS2012=1 +if /i "%arg%" == "vs2013" set ActionBuildVS2013=1 +if /i "%arg:~0,5%" == "/out:" set CustomOutputDir=%arg:~5% +if /i "%arg:~0,8%" == "/package" set ActionClean=1 && set ActionBuildPackage=1 +if /i "%arg:~0,9%" == "/package:" set PackageVersion=%arg:~9% + +shift /1 +goto args_parsing + +:args_parsing_done +set arg= + +REM ******************************************************************************************** +REM Declare Constants +REM ******************************************************************************************** +set /A actionNo=1 +set thisDir=%~dp0 +set thisDir=%thisDir:~0,-1% + +REM Make sure version of the release package is set +if "%PackageVersion%" == "" set PackageVersion=1.0.0-alpha +if "%PackageVersion:~0,1%" == "v" set PackageVersion=%PackageVersion:~1% +if "%PackageVersion:~0,1%" == "V" set PackageVersion=%PackageVersion:~1% + +REM Allow to override the BuildReults path, in case someone dislikes the default one +set BuildResults=%thisDir%\_BuildResults +if "%CustomOutputDir%" == "" goto skip_buildoutput_override + set BuildResults=%CustomOutputDir% + if "%BuildResults:~-1%" == "\" set BuildResults=%BuildResults:~0,-1% +:skip_buildoutput_override + +set ProgFilesRoot=%ProgramFiles(x86)% +if "%ProgFilesRoot%" == "" set ProgFilesRoot=%ProgramFiles% +set QnxToolsDir=%thisDir%\qnxtools + +set ZipTool=%thisDir%\ext\7zip\7z.exe +set MsBuild="C:\Windows\Microsoft.NET\Framework\v4.0.30319\MsBuild.exe" +set MsBuild2013="%ProgFilesRoot%\MSBuild\12.0\Bin\MsBuild.exe" +set MsBuildCmd=%MsBuild% /property:Configuration=Release /target:Rebuild +set MsBuild2013Cmd=%MsBuild2013% /property:Configuration=Release /target:Rebuild + +set SolutionPath2010="%thisDir%\src_vs2010\BlackBerry.NativePlugin.sln" +set SolutionPath2012="%thisDir%\src_vs2012\BlackBerry.NativePlugin.sln" +set SolutionPath2013="%thisDir%\src_vs2013\BlackBerry.NativePlugin.sln" + +set PackageResults=%BuildResults%\Package +set PackageNamePrefix=BBNDK- + +echo Current folder: "%thisDir%" +echo Output folder: "%BuildResults%" + +REM ******************************************************************************************** +REM Clean up old bin folder +REM ******************************************************************************************** +if %ActionClean% equ 0 (goto skip_clean) + +echo %actionNo%: Removing previous code... +if not exist "%BuildResults%" ( + mkdir "%BuildResults%" + echo %actionNo%: Created empty folder - DONE + +) else ( + rmdir /Q "%BuildResults%" /S + if errorlevel 1 ( exit /b %errorlevel% ) + + mkdir "%BuildResults%" + if errorlevel 1 ( exit /b %errorlevel% ) + echo %actionNo%: Cleanup - DONE +) +set /a actionNo += 1 + +:skip_clean + +REM ******************************************************************************************** +REM Build VS2010 +REM ******************************************************************************************** +if %ActionBuildVS2010% equ 0 (goto skip_vs2010) + +echo %actionNo%: Building Solution for Visual Studio 2010 +%MsBuildCmd% %SolutionPath2010% /p:OutputPath="%BuildResults%\VS2010" > "%BuildResults%\VS2010_buildlog.txt" +if errorlevel 1 ( exit /b %errorlevel% ) +echo %actionNo%: Build - DONE +set /a actionNo += 1 + +:skip_vs2010 + +REM ******************************************************************************************** +REM Build VS2012 +REM ******************************************************************************************** +if %ActionBuildVS2012% equ 0 (goto skip_vs2012) + +echo %actionNo%: Building Solution for Visual Studio 2012 +%MsBuildCmd% %SolutionPath2012% /p:OutputPath="%BuildResults%\VS2012" /p:VisualStudioVersion=11.0 > "%BuildResults%\VS2012_buildlog.txt" +if errorlevel 1 ( exit /b %errorlevel% ) +echo %actionNo%: Build - DONE +set /a actionNo += 1 + +:skip_vs2012 + +REM ******************************************************************************************** +REM Build VS2013 +REM ******************************************************************************************** +if %ActionBuildVS2013% equ 0 (goto skip_vs2013) + +echo %actionNo%: Building Solution for Visual Studio 2013 +%MsBuild2013Cmd% %SolutionPath2013% /p:OutputPath="%BuildResults%\VS2013" /p:VisualStudioVersion=12.0 > "%BuildResults%\VS2013_buildlog.txt" +if errorlevel 1 ( exit /b %errorlevel% ) +echo %actionNo%: Build - DONE +set /a actionNo += 1 + +:skip_vs2013 + +REM ******************************************************************************************** +REM Release Package ZIP files creation +REM ******************************************************************************************** +if %ActionBuildPackage% equ 0 (goto skip_package) + +if exist "%PackageResults%" rmdir /Q "%PackageResults%" /S +mkdir "%PackageResults%" + +echo %actionNo%: Creating release package version: v%PackageVersion% (MSBuild platforms part) +if exist "%PackageResults%\BlackBerry" rmdir /Q "%PackageResults%\BlackBerry" /S +if exist "%PackageResults%\Microsoft.Cpp" rmdir /Q "%PackageResults%\Microsoft.Cpp" /S + +echo Creating folder structure compatible with MSBuild v4.0 +xcopy "%QnxToolsDir%" "%PackageResults%\BlackBerry\QnxTools" /e /i /y /q +if exist "%BuildResults%\VS2010\BlackBerry" ( + xcopy "%BuildResults%\VS2010\BlackBerry" "%PackageResults%\Microsoft.Cpp\v4.0\Platforms\BlackBerry\" /e /i /y /q + copy "%BuildResults%\VS2010\BlackBerry.BuildTasks.dll" "%PackageResults%\Microsoft.Cpp\v4.0\Platforms\BlackBerry\BlackBerry.BuildTasks.dll" +) +if exist "%BuildResults%\VS2012\BlackBerry" ( + xcopy "%BuildResults%\VS2012\BlackBerry" "%PackageResults%\Microsoft.Cpp\v4.0\V110\Platforms\BlackBerry\" /e /i /y /q + copy "%BuildResults%\VS2012\BlackBerry.BuildTasks.dll" "%PackageResults%\Microsoft.Cpp\v4.0\V110\Platforms\BlackBerry\BlackBerry.BuildTasks.dll" +) +if exist "%BuildResults%\VS2013\BlackBerry" ( + xcopy "%BuildResults%\VS2013\BlackBerry" "%PackageResults%\Microsoft.Cpp\v4.0\V120\Platforms\BlackBerry\" /e /i /y /q + copy "%BuildResults%\VS2013\BlackBerry.BuildTasks.dll" "%PackageResults%\Microsoft.Cpp\v4.0\V120\Platforms\BlackBerry\BlackBerry.BuildTasks.dll" +) + +echo Compressing... +%ZipTool% a -tzip -mx9 "%PackageResults%\MSBuild_Platforms_v%PackageVersion%.zip" "%PackageResults%\BlackBerry" "%PackageResults%\Microsoft.Cpp" > nul +if errorlevel 1 ( exit /b %errorlevel% ) +echo Created ZIP archive + +if exist "%PackageResults%\BlackBerry" rmdir /Q "%PackageResults%\BlackBerry" /S +if exist "%PackageResults%\Microsoft.Cpp" rmdir /Q "%PackageResults%\Microsoft.Cpp" /S +echo %actionNo%: Package - MSBuild - DONE +set /a actionNo += 1 + +echo %actionNo%: Copying VSIX packages... + +REM Copy VSIX packages: +if exist "%BuildResults%\VS2010\BlackBerry.Package.vsix" ( + copy /B "%BuildResults%\VS2010\BlackBerry.Package.vsix" "%PackageResults%\%PackageNamePrefix%plugin_vs2010_v%PackageVersion%.vsix" + if errorlevel 1 ( exit /b %errorlevel% ) +) +if exist "%BuildResults%\VS2012\BlackBerry.Package.vsix" ( + copy /B "%BuildResults%\VS2012\BlackBerry.Package.vsix" "%PackageResults%\%PackageNamePrefix%plugin_vs2012_v%PackageVersion%.vsix" + if errorlevel 1 ( exit /b %errorlevel% ) +) +if exist "%BuildResults%\VS2013\BlackBerry.Package.vsix" ( + copy /B "%BuildResults%\VS2013\BlackBerry.Package.vsix" "%PackageResults%\%PackageNamePrefix%plugin_vs2013_v%PackageVersion%.vsix" + if errorlevel 1 ( exit /b %errorlevel% ) +) + +echo %actionNo%: VSIX - DONE +set /a actionNo += 1 + +:skip_package + +goto EOF + +REM ******************************************************************************************** +REM DONE +REM ******************************************************************************************** + +:EOF +endlocal +echo [ALL DONE] diff --git a/CleanFiles.bat b/clean.bat similarity index 100% rename from CleanFiles.bat rename to clean.bat diff --git a/ext/7zip/7z.exe b/ext/7zip/7z.exe new file mode 100644 index 00000000..101884c3 Binary files /dev/null and b/ext/7zip/7z.exe differ diff --git a/ext/7zip/License.txt b/ext/7zip/License.txt new file mode 100644 index 00000000..e25910a6 --- /dev/null +++ b/ext/7zip/License.txt @@ -0,0 +1,56 @@ + 7-Zip + ~~~~~ + License for use and distribution + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + 7-Zip Copyright (C) 1999-2010 Igor Pavlov. + + Licenses for files are: + + 1) 7z.dll: GNU LGPL + unRAR restriction + 2) All other files: GNU LGPL + + The GNU LGPL + unRAR restriction means that you must follow both + GNU LGPL rules and unRAR restriction rules. + + + Note: + You can use 7-Zip on any computer, including a computer in a commercial + organization. You don't need to register or pay for 7-Zip. + + + GNU LGPL information + -------------------- + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You can receive a copy of the GNU Lesser General Public License from + http://www.gnu.org/ + + + unRAR restriction + ----------------- + + The decompression engine for RAR archives was developed using source + code of unRAR program. + All copyrights to original unRAR code are owned by Alexander Roshal. + + The license for original unRAR code has the following restriction: + + The unRAR sources cannot be used to re-create the RAR compression algorithm, + which is proprietary. Distribution of modified unRAR sources in separate form + or as a part of other software is permitted, provided that it is clearly + stated in the documentation and source comments that the code may + not be used to develop a RAR (WinRAR) compatible archiver. + + + -- + Igor Pavlov diff --git a/ext/NUnit/license.txt b/ext/NUnit/license.txt new file mode 100644 index 00000000..b12903af --- /dev/null +++ b/ext/NUnit/license.txt @@ -0,0 +1,15 @@ +Copyright 2002-2013 Charlie Poole +Copyright 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov +Copyright 2000-2002 Philip A. Craig + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. + +Portions Copyright 2002-2013 Charlie Poole or Copyright 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright 2000-2002 Philip A. Craig + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/ext/NUnit/nunit.framework.dll b/ext/NUnit/nunit.framework.dll new file mode 100644 index 00000000..780727f2 Binary files /dev/null and b/ext/NUnit/nunit.framework.dll differ diff --git a/ext/NUnit/nunit.framework.xml b/ext/NUnit/nunit.framework.xml new file mode 100644 index 00000000..4c8c26e8 --- /dev/null +++ b/ext/NUnit/nunit.framework.xml @@ -0,0 +1,10960 @@ + + + + nunit.framework + + + + + The different targets a test action attribute can be applied to + + + + + Default target, which is determined by where the action attribute is attached + + + + + Target a individual test case + + + + + Target a suite of test cases + + + + + Delegate used by tests that execute code and + capture any thrown exception. + + + + + The Assert class contains a collection of static methods that + implement the most common assertions used in NUnit. + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + + + + Throws an with the message and arguments + that are passed in. This is used by the other Assert functions. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This is used by the other Assert functions. + + The message to initialize the with. + + + + Throws an . + This is used by the other Assert functions. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as ignored. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as Inconclusive. + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + + This method is provided for use by VB developers needing to test + the value of properties with private setters. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate does not throw an exception + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not null or empty + + The string to be tested + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + + + + Helper for Assert.AreEqual(double expected, double actual, ...) + allowing code generation to work consistently. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Gets the number of assertions executed so far and + resets the counter to zero. + + + + + AssertionHelper is an optional base class for user tests, + allowing the use of shorter names for constraints and + asserts and avoiding conflict with the definition of + , from which it inherits much of its + behavior, in certain mock object frameworks. + + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + Arguments to use in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Returns a ListMapper based on a collection. + + The original collection + + + + + Provides static methods to express the assumptions + that must be met for a test to give a meaningful + result. If an assumption is not met, the test + should produce an inconclusive result. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the + method throws an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Waits for pending asynchronous operations to complete, if appropriate, + and returns a proper result of the invocation by unwrapping task results + + The raw result of the method invocation + The unwrapped result, if necessary + + + + A set of Assert methods operationg on one or more collections + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + The message that will be displayed on failure + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Summary description for DirectoryAssert + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Summary description for FileAssert. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if objects are not equal + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the two Stream are the same. + Arguments to be used in formatting the message + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the Streams are the same. + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + GlobalSettings is a place for setting default values used + by the framework in performing asserts. + + + + + Default tolerance for floating point equality + + + + + Class used to guard against unexpected argument values + by throwing an appropriate exception. + + + + + Throws an exception if an argument is null + + The value to be tested + The name of the argument + + + + Throws an exception if a string argument is null or empty + + The value to be tested + The name of the argument + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Interface implemented by a user fixture in order to + validate any expected exceptions. It is only called + for test methods marked with the ExpectedException + attribute. + + + + + Method to handle an expected exception + + The exception to be handled + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + The ITestCaseData interface is implemented by a class + that is able to return complete testcases for use by + a parameterized test method. + + NOTE: This interface is used in both the framework + and the core, even though that results in two different + types. However, sharing the source code guarantees that + the various implementations will be compatible and that + the core is able to reflect successfully over the + framework implementations of ITestCaseData. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Indicates whether a result has been specified. + This is necessary because the result may be + null, so it's value cannot be checked. + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + The Iz class is a synonym for Is intended for use in VB, + which regards Is as a keyword. + + + + + The List class is a helper class with properties and methods + that supply a number of constraints used with lists and collections. + + + + + List.Map returns a ListMapper, which can be used to map + the original collection to another collection. + + + + + + + ListMapper is used to transform a collection used as an actual argument + producing another collection to be used in the assertion. + + + + + Construct a ListMapper based on a collection + + The collection to be transformed + + + + Produces a collection containing all the values of a property + + The collection of property values + + + + + Randomizer returns a set of random values in a repeatable + way, to allow re-running of tests if necessary. + + + + + Get a randomizer for a particular member, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Get a randomizer for a particular parameter, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Construct a randomizer using a random seed + + + + + Construct a randomizer using a specified seed + + + + + Return an array of random doubles between 0.0 and 1.0. + + + + + + + Return an array of random doubles with values in a specified range. + + + + + Return an array of random ints with values in a specified range. + + + + + Get a random seed for use in creating a randomizer. + + + + + The SpecialValue enum is used to represent TestCase arguments + that cannot be used as arguments to an Attribute. + + + + + Null represents a null value, which cannot be used as an + argument to an attribute under .NET 1.x + + + + + Basic Asserts on strings. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string is not found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are Notequal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + + + + The TestCaseData class represents a set of arguments + and other parameter info to be used for a parameterized + test case. It provides a number of instance modifiers + for use in initializing the test case. + + Note: Instance modifiers are getters that return + the same instance after modifying it's state. + + + + + The argument list to be provided to the test + + + + + The expected result to be returned + + + + + Set to true if this has an expected result + + + + + The expected exception Type + + + + + The FullName of the expected exception + + + + + The name to be used for the test + + + + + The description of the test + + + + + A dictionary of properties, used to add information + to tests without requiring the class to change. + + + + + If true, indicates that the test case is to be ignored + + + + + If true, indicates that the test case is marked explicit + + + + + The reason for ignoring a test case + + + + + Initializes a new instance of the class. + + The arguments. + + + + Initializes a new instance of the class. + + The argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + The third argument. + + + + Sets the expected result for the test + + The expected result + A modified TestCaseData + + + + Sets the expected exception type for the test + + Type of the expected exception. + The modified TestCaseData instance + + + + Sets the expected exception type for the test + + FullName of the expected exception. + The modified TestCaseData instance + + + + Sets the name of the test case + + The modified TestCaseData instance + + + + Sets the description for the test case + being constructed. + + The description. + The modified TestCaseData instance. + + + + Applies a category to the test + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Ignores this TestCase. + + + + + + Ignores this TestCase, specifying the reason. + + The reason. + + + + + Marks this TestCase as Explicit + + + + + + Marks this TestCase as Explicit, specifying the reason. + + The reason. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Returns true if the result has been set + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + Gets a list of categories associated with this test. + + + + + Gets the property dictionary for this test + + + + + Provide the context information of the current test + + + + + Constructs a TestContext using the provided context dictionary + + A context dictionary + + + + Get the current test context. This is created + as needed. The user may save the context for + use within a test, but it should not be used + outside the test for which it is created. + + + + + Gets a TestAdapter representing the currently executing test in this context. + + + + + Gets a ResultAdapter representing the current result for the test + executing in this context. + + + + + Gets the directory containing the current test assembly. + + + + + Gets the directory to be used for outputing files created + by this test run. + + + + + TestAdapter adapts a Test for consumption by + the user test code. + + + + + Constructs a TestAdapter for this context + + The context dictionary + + + + The name of the test. + + + + + The FullName of the test + + + + + The properties of the test. + + + + + ResultAdapter adapts a TestResult for consumption by + the user test code. + + + + + Construct a ResultAdapter for a context + + The context holding the result + + + + The TestState of current test. This maps to the ResultState + used in nunit.core and is subject to change in the future. + + + + + The TestStatus of current test. This enum will be used + in future versions of NUnit and so is to be preferred + to the TestState value. + + + + + Provides details about a test + + + + + Creates an instance of TestDetails + + The fixture that the test is a member of, if available. + The method that implements the test, if available. + The full name of the test. + A string representing the type of test, e.g. "Test Case". + Indicates if the test represents a suite of tests. + + + + The fixture that the test is a member of, if available. + + + + + The method that implements the test, if available. + + + + + The full name of the test. + + + + + A string representing the type of test, e.g. "Test Case". + + + + + Indicates if the test represents a suite of tests. + + + + + The ResultState enum indicates the result of running a test + + + + + The result is inconclusive + + + + + The test was not runnable. + + + + + The test has been skipped. + + + + + The test has been ignored. + + + + + The test succeeded + + + + + The test failed + + + + + The test encountered an unexpected exception + + + + + The test was cancelled by the user + + + + + The TestStatus enum indicates the result of running a test + + + + + The test was inconclusive + + + + + The test has skipped + + + + + The test succeeded + + + + + The test failed + + + + + Helper class with static methods used to supply constraints + that operate on strings. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the Regex pattern supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + TextMessageWriter writes constraint descriptions and messages + in displayable form as a text stream. It tailors the display + of individual message components to form the standard message + format of NUnit assertion failure messages. + + + + + MessageWriter is the abstract base for classes that write + constraint descriptions and messages in some form. The + class has separate methods for writing various components + of a message, allowing implementations to tailor the + presentation as needed. + + + + + Construct a MessageWriter given a culture + + + + + Method to write single line message with optional args, usually + written to precede the general failure message. + + The message to be written + Any arguments used in formatting the message + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the Expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in locating the point where the strings differ + If true, the strings should be clipped to fit the line + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for a modifier + + The modifier. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Abstract method to get the max line length + + + + + Prefix used for the expected value line of a message + + + + + Prefix used for the actual value line of a message + + + + + Length of a message prefix + + + + + Construct a TextMessageWriter + + + + + Construct a TextMessageWriter, specifying a user message + and optional formatting arguments. + + + + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in string comparisons + If true, clip the strings to fit the max line length + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Write the text for a modifier. + + The modifier. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Write the generic 'Expected' line for a constraint + + The constraint that failed + + + + Write the generic 'Expected' line for a given value + + The expected value + + + + Write the generic 'Expected' line for a given value + and tolerance. + + The expected value + The tolerance within which the test was made + + + + Write the generic 'Actual' line for a constraint + + The constraint for which the actual value is to be written + + + + Write the generic 'Actual' line for a given value + + The actual value causing a failure + + + + Gets or sets the maximum line length for this writer + + + + + Helper class with properties and methods that supply + constraints that operate on exceptions. + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying an expected exception + + + + + Creates a constraint specifying an exception with a given InnerException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying that no exception is thrown + + + + + Attribute used to apply a category to a test + + + + + The name of the category + + + + + Construct attribute for a given category based on + a name. The name may not contain the characters ',', + '+', '-' or '!'. However, this is not checked in the + constructor since it would cause an error to arise at + as the test was loaded without giving a clear indication + of where the problem is located. The error is handled + in NUnitFramework.cs by marking the test as not + runnable. + + The name of the category + + + + Protected constructor uses the Type name as the name + of the category. + + + + + The name of the category + + + + + Used to mark a field for use as a datapoint when executing a theory + within the same fixture that requires an argument of the field's Type. + + + + + Used to mark an array as containing a set of datapoints to be used + executing a theory within the same fixture that requires an argument + of the Type of the array elements. + + + + + Attribute used to provide descriptive text about a + test case or fixture. + + + + + Construct the attribute + + Text describing the test + + + + Gets the test description + + + + + Enumeration indicating how the expected message parameter is to be used + + + + Expect an exact match + + + Expect a message containing the parameter string + + + Match the regular expression provided as a parameter + + + Expect a message that starts with the parameter string + + + + ExpectedExceptionAttribute + + + + + + Constructor for a non-specific exception + + + + + Constructor for a given type of exception + + The type of the expected exception + + + + Constructor for a given exception name + + The full name of the expected exception + + + + Gets or sets the expected exception type + + + + + Gets or sets the full Type name of the expected exception + + + + + Gets or sets the expected message text + + + + + Gets or sets the user message displayed in case of failure + + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets the name of a method to be used as an exception handler + + + + + ExplicitAttribute marks a test or test fixture so that it will + only be run if explicitly executed from the gui or command line + or if it is included by use of a filter. The test will not be + run simply because an enclosing suite is run. + + + + + Default constructor + + + + + Constructor with a reason + + The reason test is marked explicit + + + + The reason test is marked explicit + + + + + Attribute used to mark a test that is to be ignored. + Ignored tests result in a warning message when the + tests are run. + + + + + Constructs the attribute without giving a reason + for ignoring the test. + + + + + Constructs the attribute giving a reason for ignoring the test + + The reason for ignoring the test + + + + The reason for ignoring a test + + + + + Abstract base for Attributes that are used to include tests + in the test run based on environmental settings. + + + + + Constructor with no included items specified, for use + with named property syntax. + + + + + Constructor taking one or more included items + + Comma-delimited list of included items + + + + Name of the item that is needed in order for + a test to run. Multiple itemss may be given, + separated by a comma. + + + + + Name of the item to be excluded. Multiple items + may be given, separated by a comma. + + + + + The reason for including or excluding the test + + + + + PlatformAttribute is used to mark a test fixture or an + individual method as applying to a particular platform only. + + + + + Constructor with no platforms specified, for use + with named property syntax. + + + + + Constructor taking one or more platforms + + Comma-deliminted list of platforms + + + + CultureAttribute is used to mark a test fixture or an + individual method as applying to a particular Culture only. + + + + + Constructor with no cultures specified, for use + with named property syntax. + + + + + Constructor taking one or more cultures + + Comma-deliminted list of cultures + + + + Marks a test to use a combinatorial join of any argument data + provided. NUnit will create a test case for every combination of + the arguments provided. This can result in a large number of test + cases and so should be used judiciously. This is the default join + type, so the attribute need not be used except as documentation. + + + + + PropertyAttribute is used to attach information to a test as a name/value pair.. + + + + + Construct a PropertyAttribute with a name and string value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and int value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and double value + + The name of the property + The property value + + + + Constructor for derived classes that set the + property dictionary directly. + + + + + Constructor for use by derived classes that use the + name of the type as the property name. Derived classes + must ensure that the Type of the property value is + a standard type supported by the BCL. Any custom + types will cause a serialization Exception when + in the client. + + + + + Gets the property dictionary for this attribute + + + + + Default constructor + + + + + Marks a test to use pairwise join of any argument data provided. + NUnit will attempt too excercise every pair of argument values at + least once, using as small a number of test cases as it can. With + only two arguments, this is the same as a combinatorial join. + + + + + Default constructor + + + + + Marks a test to use a sequential join of any argument data + provided. NUnit will use arguements for each parameter in + sequence, generating test cases up to the largest number + of argument values provided and using null for any arguments + for which it runs out of values. Normally, this should be + used with the same number of arguments for each parameter. + + + + + Default constructor + + + + + Summary description for MaxTimeAttribute. + + + + + Construct a MaxTimeAttribute, given a time in milliseconds. + + The maximum elapsed time in milliseconds + + + + RandomAttribute is used to supply a set of random values + to a single parameter of a parameterized test. + + + + + ValuesAttribute is used to provide literal arguments for + an individual parameter of a test. + + + + + Abstract base class for attributes that apply to parameters + and supply data for the parameter. + + + + + Gets the data to be provided to the specified parameter + + + + + The collection of data to be returned. Must + be set by any derived attribute classes. + We use an object[] so that the individual + elements may have their type changed in GetData + if necessary. + + + + + Construct with one argument + + + + + + Construct with two arguments + + + + + + + Construct with three arguments + + + + + + + + Construct with an array of arguments + + + + + + Get the collection of values to be used as arguments + + + + + Construct a set of doubles from 0.0 to 1.0, + specifying only the count. + + + + + + Construct a set of doubles from min to max + + + + + + + + Construct a set of ints from min to max + + + + + + + + Get the collection of values to be used as arguments + + + + + RangeAttribute is used to supply a range of values to an + individual parameter of a parameterized test. + + + + + Construct a range of ints using default step of 1 + + + + + + + Construct a range of ints specifying the step size + + + + + + + + Construct a range of longs + + + + + + + + Construct a range of doubles + + + + + + + + Construct a range of floats + + + + + + + + RepeatAttribute may be applied to test case in order + to run it multiple times. + + + + + Construct a RepeatAttribute + + The number of times to run the test + + + + RequiredAddinAttribute may be used to indicate the names of any addins + that must be present in order to run some or all of the tests in an + assembly. If the addin is not loaded, the entire assembly is marked + as NotRunnable. + + + + + Initializes a new instance of the class. + + The required addin. + + + + Gets the name of required addin. + + The required addin name. + + + + Summary description for SetCultureAttribute. + + + + + Construct given the name of a culture + + + + + + Summary description for SetUICultureAttribute. + + + + + Construct given the name of a culture + + + + + + SetUpAttribute is used in a TestFixture to identify a method + that is called immediately before each test is run. It is + also used in a SetUpFixture to identify the method that is + called once, before any of the subordinate tests are run. + + + + + Attribute used to mark a class that contains one-time SetUp + and/or TearDown methods that apply to all the tests in a + namespace or an assembly. + + + + + Attribute used to mark a static (shared in VB) property + that returns a list of tests. + + + + + Attribute used in a TestFixture to identify a method that is + called immediately after each test is run. It is also used + in a SetUpFixture to identify the method that is called once, + after all subordinate tests have run. In either case, the method + is guaranteed to be called, even if an exception is thrown. + + + + + Provide actions to execute before and after tests. + + + + + When implemented by an attribute, this interface implemented to provide actions to execute before and after tests. + + + + + Executed before each test is run + + Provides details about the test that is going to be run. + + + + Executed after each test is run + + Provides details about the test that has just been run. + + + + Provides the target for the action attribute + + The target for the action attribute + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Descriptive text for this test + + + + + TestCaseAttribute is used to mark parameterized test cases + and provide them with their arguments. + + + + + Construct a TestCaseAttribute with a list of arguments. + This constructor is not CLS-Compliant + + + + + + Construct a TestCaseAttribute with a single argument + + + + + + Construct a TestCaseAttribute with a two arguments + + + + + + + Construct a TestCaseAttribute with a three arguments + + + + + + + + Gets the list of arguments to a test case + + + + + Gets or sets the expected result. Use + ExpectedResult by preference. + + The result. + + + + Gets or sets the expected result. + + The result. + + + + Gets a flag indicating whether an expected + result has been set. + + + + + Gets a list of categories associated with this test; + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + Gets or sets the expected exception. + + The expected exception. + + + + Gets or sets the name the expected exception. + + The expected name of the exception. + + + + Gets or sets the expected message of the expected exception + + The expected message of the exception. + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets or sets the description. + + The description. + + + + Gets or sets the name of the test. + + The name of the test. + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the explicit status of the test + + + + + Gets or sets the reason for not running the test + + + + + Gets or sets the reason for not running the test. + Set has the side effect of marking the test as ignored. + + The ignore reason. + + + + FactoryAttribute indicates the source to be used to + provide test cases for a test method. + + + + + Construct with the name of the data source, which must + be a property, field or method of the test class itself. + + An array of the names of the factories that will provide data + + + + Construct with a Type, which must implement IEnumerable + + The Type that will provide data + + + + Construct with a Type and name. + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + [TestFixture] + public class ExampleClass + {} + + + + + Default constructor + + + + + Construct with a object[] representing a set of arguments. + In .NET 2.0, the arguments may later be separated into + type arguments and constructor arguments. + + + + + + Descriptive text for this fixture + + + + + Gets and sets the category for this fixture. + May be a comma-separated list of categories. + + + + + Gets a list of categories for this fixture + + + + + The arguments originally provided to the attribute + + + + + Gets or sets a value indicating whether this should be ignored. + + true if ignore; otherwise, false. + + + + Gets or sets the ignore reason. May set Ignored as a side effect. + + The ignore reason. + + + + Get or set the type arguments. If not set + explicitly, any leading arguments that are + Types are taken as type arguments. + + + + + Attribute used to identify a method that is + called before any tests in a fixture are run. + + + + + Attribute used to identify a method that is called after + all the tests in a fixture have run. The method is + guaranteed to be called, even if an exception is thrown. + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Used on a method, marks the test with a timeout value in milliseconds. + The test will be run in a separate thread and is cancelled if the timeout + is exceeded. Used on a method or assembly, sets the default timeout + for all contained test methods. + + + + + Construct a TimeoutAttribute given a time in milliseconds + + The timeout value in milliseconds + + + + Marks a test that must run in the STA, causing it + to run in a separate thread if necessary. + + On methods, you may also use STAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresSTAAttribute + + + + + Marks a test that must run in the MTA, causing it + to run in a separate thread if necessary. + + On methods, you may also use MTAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresMTAAttribute + + + + + Marks a test that must run on a separate thread. + + + + + Construct a RequiresThreadAttribute + + + + + Construct a RequiresThreadAttribute, specifying the apartment + + + + + ValueSourceAttribute indicates the source to be used to + provide data for one parameter of a test method. + + + + + Construct with the name of the factory - for use with languages + that don't support params arrays. + + The name of the data source to be used + + + + Construct with a Type and name - for use with languages + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + AllItemsConstraint applies another constraint to each + item in a collection, succeeding if they all succeed. + + + + + Abstract base class used for prefixes + + + + + The Constraint class is the base of all built-in constraints + within NUnit. It provides the operator overloads used to combine + constraints. + + + + + The IConstraintExpression interface is implemented by all + complete and resolvable constraints and expressions. + + + + + Return the top-level constraint for this expression + + + + + + Static UnsetObject used to detect derived constraints + failing to set the actual value. + + + + + The actual value being tested against a constraint + + + + + The display name of this Constraint for use by ToString() + + + + + Argument fields used by ToString(); + + + + + The builder holding this constraint + + + + + Construct a constraint with no arguments + + + + + Construct a constraint with one argument + + + + + Construct a constraint with two arguments + + + + + Sets the ConstraintBuilder holding this constraint + + + + + Write the failure message to the MessageWriter provided + as an argument. The default implementation simply passes + the constraint and the actual value to the writer, which + then displays the constraint description and the value. + + Constraints that need to provide additional details, + such as where the error occured can override this. + + The MessageWriter on which to display the message + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by an + ActualValueDelegate that returns the value to be tested. + The default implementation simply evaluates the delegate + but derived classes may override it to provide for delayed + processing. + + An + True for success, false for failure + + + + Test whether the constraint is satisfied by a given reference. + The default implementation simply dereferences the value but + derived classes may override it to provide for delayed processing. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Default override of ToString returns the constraint DisplayName + followed by any arguments within angle brackets. + + + + + + Returns the string representation of this constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Returns a DelayedConstraint with the specified delay time. + + The delay in milliseconds. + + + + + Returns a DelayedConstraint with the specified delay time + and polling interval. + + The delay in milliseconds. + The interval at which to test the constraint. + + + + + The display name of this Constraint for use by ToString(). + The default value is the name of the constraint with + trailing "Constraint" removed. Derived classes may set + this to another name in their constructors. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending Or + to the current constraint. + + + + + Class used to detect any derived constraints + that fail to set the actual value in their + Matches override. + + + + + The base constraint + + + + + Construct given a base constraint + + + + + + Construct an AllItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + AndConstraint succeeds only if both members succeed. + + + + + BinaryConstraint is the abstract base of all constraints + that combine two other constraints in some fashion. + + + + + The first constraint being combined + + + + + The second constraint being combined + + + + + Construct a BinaryConstraint from two other constraints + + The first constraint + The second constraint + + + + Create an AndConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply both member constraints to an actual value, succeeding + succeeding only if both of them succeed. + + The actual value + True if the constraints both succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + AssignableFromConstraint is used to test that an object + can be assigned from a given Type. + + + + + TypeConstraint is the abstract base for constraints + that take a Type as their expected value. + + + + + The expected Type used by the constraint + + + + + Construct a TypeConstraint for a given Type + + + + + + Write the actual value for a failing constraint test to a + MessageWriter. TypeConstraints override this method to write + the name of the type. + + The writer on which the actual value is displayed + + + + Construct an AssignableFromConstraint for the type provided + + + + + + Test whether an object can be assigned from the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AssignableToConstraint is used to test that an object + can be assigned to a given Type. + + + + + Construct an AssignableToConstraint for the type provided + + + + + + Test whether an object can be assigned to the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AttributeConstraint tests that a specified attribute is present + on a Type or other provider and that the value of the attribute + satisfies some other constraint. + + + + + Constructs an AttributeConstraint for a specified attriute + Type and base constraint. + + + + + + + Determines whether the Type or other provider has the + expected attribute and if its value matches the + additional constraint specified. + + + + + Writes a description of the attribute to the specified writer. + + + + + Writes the actual value supplied to the specified writer. + + + + + Returns a string representation of the constraint. + + + + + AttributeExistsConstraint tests for the presence of a + specified attribute on a Type. + + + + + Constructs an AttributeExistsConstraint for a specific attribute Type + + + + + + Tests whether the object provides the expected attribute. + + A Type, MethodInfo, or other ICustomAttributeProvider + True if the expected attribute is present, otherwise false + + + + Writes the description of the constraint to the specified writer + + + + + BasicConstraint is the abstract base for constraints that + perform a simple comparison to a constant value. + + + + + Initializes a new instance of the class. + + The expected. + The description. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + BinarySerializableConstraint tests whether + an object is serializable in binary format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation + + + + + CollectionConstraint is the abstract base class for + constraints that operate on collections. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Determines whether the specified enumerable is empty. + + The enumerable. + + true if the specified enumerable is empty; otherwise, false. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Protected method to be implemented by derived classes + + + + + + + CollectionContainsConstraint is used to test whether a collection + contains an expected object as a member. + + + + + CollectionItemsEqualConstraint is the abstract base class for all + collection constraints that apply some notion of item equality + as a part of their operation. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Flag the constraint to use the supplied EqualityAdapter. + NOTE: For internal use only. + + The EqualityAdapter to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Compares two collection members for equality + + + + + Return a new CollectionTally for use in making tests + + The collection to be included in the tally + + + + Flag the constraint to ignore case and return self. + + + + + Construct a CollectionContainsConstraint + + + + + + Test whether the expected item is contained in the collection + + + + + + + Write a descripton of the constraint to a MessageWriter + + + + + + CollectionEquivalentCOnstraint is used to determine whether two + collections are equivalent. + + + + + Construct a CollectionEquivalentConstraint + + + + + + Test whether two collections are equivalent + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionOrderedConstraint is used to test whether a collection is ordered. + + + + + Construct a CollectionOrderedConstraint + + + + + Modifies the constraint to use an IComparer and returns self. + + + + + Modifies the constraint to use an IComparer<T> and returns self. + + + + + Modifies the constraint to use a Comparison<T> and returns self. + + + + + Modifies the constraint to test ordering by the value of + a specified property and returns self. + + + + + Test whether the collection is ordered + + + + + + + Write a description of the constraint to a MessageWriter + + + + + + Returns the string representation of the constraint. + + + + + + If used performs a reverse comparison + + + + + CollectionSubsetConstraint is used to determine whether + one collection is a subset of another + + + + + Construct a CollectionSubsetConstraint + + The collection that the actual value is expected to be a subset of + + + + Test whether the actual collection is a subset of + the expected collection provided. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionTally counts (tallies) the number of + occurences of each object in one or more enumerations. + + + + + Construct a CollectionTally object from a comparer and a collection + + + + + Try to remove an object from the tally + + The object to remove + True if successful, false if the object was not found + + + + Try to remove a set of objects from the tally + + The objects to remove + True if successful, false if any object was not found + + + + The number of objects remaining in the tally + + + + + ComparisonAdapter class centralizes all comparisons of + values in NUnit, adapting to the use of any provided + IComparer, IComparer<T> or Comparison<T> + + + + + Returns a ComparisonAdapter that wraps an IComparer + + + + + Returns a ComparisonAdapter that wraps an IComparer<T> + + + + + Returns a ComparisonAdapter that wraps a Comparison<T> + + + + + Compares two objects + + + + + Gets the default ComparisonAdapter, which wraps an + NUnitComparer object. + + + + + Construct a ComparisonAdapter for an IComparer + + + + + Compares two objects + + + + + + + + Construct a default ComparisonAdapter + + + + + ComparisonAdapter<T> extends ComparisonAdapter and + allows use of an IComparer<T> or Comparison<T> + to actually perform the comparison. + + + + + Construct a ComparisonAdapter for an IComparer<T> + + + + + Compare a Type T to an object + + + + + Construct a ComparisonAdapter for a Comparison<T> + + + + + Compare a Type T to an object + + + + + Abstract base class for constraints that compare values to + determine if one is greater than, equal to or less than + the other. This class supplies the Using modifiers. + + + + + ComparisonAdapter to be used in making the comparison + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Modifies the constraint to use an IComparer and returns self + + + + + Modifies the constraint to use an IComparer<T> and returns self + + + + + Modifies the constraint to use a Comparison<T> and returns self + + + + + Delegate used to delay evaluation of the actual value + to be used in evaluating a constraint + + + + + ConstraintBuilder maintains the stacks that are used in + processing a ConstraintExpression. An OperatorStack + is used to hold operators that are waiting for their + operands to be reognized. a ConstraintStack holds + input constraints as well as the results of each + operator applied. + + + + + Initializes a new instance of the class. + + + + + Appends the specified operator to the expression by first + reducing the operator stack and then pushing the new + operator on the stack. + + The operator to push. + + + + Appends the specified constraint to the expresson by pushing + it on the constraint stack. + + The constraint to push. + + + + Sets the top operator right context. + + The right context. + + + + Reduces the operator stack until the topmost item + precedence is greater than or equal to the target precedence. + + The target precedence. + + + + Resolves this instance, returning a Constraint. If the builder + is not currently in a resolvable state, an exception is thrown. + + The resolved constraint + + + + Gets a value indicating whether this instance is resolvable. + + + true if this instance is resolvable; otherwise, false. + + + + + OperatorStack is a type-safe stack for holding ConstraintOperators + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified operator onto the stack. + + The op. + + + + Pops the topmost operator from the stack. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost operator without modifying the stack. + + The top. + + + + ConstraintStack is a type-safe stack for holding Constraints + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified constraint. As a side effect, + the constraint's builder field is set to the + ConstraintBuilder owning this stack. + + The constraint. + + + + Pops this topmost constrait from the stack. + As a side effect, the constraint's builder + field is set to null. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost constraint without modifying the stack. + + The topmost constraint + + + + ConstraintExpression represents a compound constraint in the + process of being constructed from a series of syntactic elements. + + Individual elements are appended to the expression as they are + reognized. Once an actual Constraint is appended, the expression + returns a resolvable Constraint. + + + + + ConstraintExpressionBase is the abstract base class for the + ConstraintExpression class, which represents a + compound constraint in the process of being constructed + from a series of syntactic elements. + + NOTE: ConstraintExpressionBase is separate because the + ConstraintExpression class was generated in earlier + versions of NUnit. The two classes may be combined + in a future version. + + + + + The ConstraintBuilder holding the elements recognized so far + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a string representation of the expression as it + currently stands. This should only be used for testing, + since it has the side-effect of resolving the expression. + + + + + + Appends an operator to the expression and returns the + resulting expression itself. + + + + + Appends a self-resolving operator to the expression and + returns a new ResolvableConstraintExpression. + + + + + Appends a constraint to the expression and returns that + constraint, which is associated with the current state + of the expression being built. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + With is currently a NOP - reserved for future use. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + ContainsConstraint tests a whether a string contains a substring + or a collection contains an object. It postpones the decision of + which test to use until the type of the actual argument is known. + This allows testing whether a string is contained in a collection + or as a substring of another string using the same syntax. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to ignore case and return self. + + + + + Applies a delay to the match so that a match can be evaluated in the future. + + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + If the value of is less than 0 + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + The time interval used for polling + If the value of is less than 0 + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a delegate + + The delegate whose value is to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a given reference. + Overridden to wait for the specified delay period before + calling the base constraint with the dereferenced value. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + EmptyCollectionConstraint tests whether a collection is empty. + + + + + Check that the collection is empty + + + + + + + Write the constraint description to a MessageWriter + + + + + + EmptyConstraint tests a whether a string or collection is empty, + postponing the decision about which test is applied until the + type of the actual argument is known. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EmptyDirectoryConstraint is used to test that a directory is empty + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + EmptyStringConstraint tests whether a string is empty. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EndsWithConstraint can test whether a string ends + with an expected substring. + + + + + StringConstraint is the abstract base for constraints + that operate on strings. It supports the IgnoreCase + modifier for string operations. + + + + + The expected value + + + + + Indicates whether tests should be case-insensitive + + + + + Constructs a StringConstraint given an expected value + + The expected value + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by a given string + + The string to be tested + True for success, false for failure + + + + Modify the constraint to ignore case in matching. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EqualConstraint is able to compare an actual value with the + expected value provided in its constructor. Two objects are + considered equal if both are null, or if both have the same + value. NUnit has special semantics for some object types. + + + + + If true, strings in error messages will be clipped + + + + + NUnitEqualityComparer used to test equality. + + + + + Initializes a new instance of the class. + + The expected value. + + + + Flag the constraint to use a tolerance when determining equality. + + Tolerance value to be used + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write a failure message. Overridden to provide custom + failure messages for EqualConstraint. + + The MessageWriter to write to + + + + Write description of this constraint + + The MessageWriter to write to + + + + Display the failure information for two collections that did not match. + + The MessageWriter on which to display + The expected collection. + The actual collection + The depth of this failure in a set of nested collections + + + + Displays a single line showing the types and sizes of the expected + and actual enumerations, collections or arrays. If both are identical, + the value is only shown once. + + The MessageWriter on which to display + The expected collection or array + The actual collection or array + The indentation level for the message line + + + + Displays a single line showing the point in the expected and actual + arrays at which the comparison failed. If the arrays have different + structures or dimensions, both values are shown. + + The MessageWriter on which to display + The expected array + The actual array + Index of the failure point in the underlying collections + The indentation level for the message line + + + + Display the failure information for two IEnumerables that did not match. + + The MessageWriter on which to display + The expected enumeration. + The actual enumeration + The depth of this failure in a set of nested collections + + + + Flag the constraint to ignore case and return self. + + + + + Flag the constraint to suppress string clipping + and return self. + + + + + Flag the constraint to compare arrays as collections + and return self. + + + + + Switches the .Within() modifier to interpret its tolerance as + a distance in representable values (see remarks). + + Self. + + Ulp stands for "unit in the last place" and describes the minimum + amount a given value can change. For any integers, an ulp is 1 whole + digit. For floating point values, the accuracy of which is better + for smaller numbers and worse for larger numbers, an ulp depends + on the size of the number. Using ulps for comparison of floating + point results instead of fixed tolerances is safer because it will + automatically compensate for the added inaccuracy of larger numbers. + + + + + Switches the .Within() modifier to interpret its tolerance as + a percentage that the actual values is allowed to deviate from + the expected value. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in days. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in hours. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in minutes. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in seconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in milliseconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in clock ticks. + + Self + + + + EqualityAdapter class handles all equality comparisons + that use an IEqualityComparer, IEqualityComparer<T> + or a ComparisonAdapter. + + + + + Compares two objects, returning true if they are equal + + + + + Returns true if the two objects can be compared by this adapter. + The base adapter cannot handle IEnumerables except for strings. + + + + + Returns an EqualityAdapter that wraps an IComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer<T>. + + + + + Returns an EqualityAdapter that wraps an IComparer<T>. + + + + + Returns an EqualityAdapter that wraps a Comparison<T>. + + + + + EqualityAdapter that wraps an IComparer. + + + + + Returns true if the two objects can be compared by this adapter. + Generic adapter requires objects of the specified type. + + + + + EqualityAdapter that wraps an IComparer. + + + + + EqualityAdapterList represents a list of EqualityAdapters + in a common class across platforms. + + + + + ExactCountConstraint applies another constraint to each + item in a collection, succeeding only if a specified + number of items succeed. + + + + + Construct an ExactCountConstraint on top of an existing constraint + + + + + + + Apply the item constraint to each item in the collection, + succeeding only if the expected number of items pass. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + ExactTypeConstraint is used to test that an object + is of the exact type provided in the constructor + + + + + Construct an ExactTypeConstraint for a given Type + + The expected Type. + + + + Test that an object is of the exact type specified + + The actual value. + True if the tested object is of the exact type provided, otherwise false. + + + + Write the description of this constraint to a MessageWriter + + The MessageWriter to use + + + + ExceptionTypeConstraint is a special version of ExactTypeConstraint + used to provided detailed info about the exception thrown in + an error message. + + + + + Constructs an ExceptionTypeConstraint + + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overriden to write additional information + in the case of an Exception. + + The MessageWriter to use + + + + FailurePoint class represents one point of failure + in an equality test. + + + + + The location of the failure + + + + + The expected value + + + + + The actual value + + + + + Indicates whether the expected value is valid + + + + + Indicates whether the actual value is valid + + + + + FailurePointList represents a set of FailurePoints + in a cross-platform way. + + + + + FalseConstraint tests that the actual value is false + + + + + Initializes a new instance of the class. + + + + Helper routines for working with floating point numbers + + + The floating point comparison code is based on this excellent article: + http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm + + + "ULP" means Unit in the Last Place and in the context of this library refers to + the distance between two adjacent floating point numbers. IEEE floating point + numbers can only represent a finite subset of natural numbers, with greater + accuracy for smaller numbers and lower accuracy for very large numbers. + + + If a comparison is allowed "2 ulps" of deviation, that means the values are + allowed to deviate by up to 2 adjacent floating point values, which might be + as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. + + + + + Compares two floating point values for equality + First floating point value to be compared + Second floating point value t be compared + + Maximum number of representable floating point values that are allowed to + be between the left and the right floating point values + + True if both numbers are equal or close to being equal + + + Floating point values can only represent a finite subset of natural numbers. + For example, the values 2.00000000 and 2.00000024 can be stored in a float, + but nothing inbetween them. + + + This comparison will count how many possible floating point values are between + the left and the right number. If the number of possible values between both + numbers is less than or equal to maxUlps, then the numbers are considered as + being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + Compares two double precision floating point values for equality + First double precision floating point value to be compared + Second double precision floating point value t be compared + + Maximum number of representable double precision floating point values that are + allowed to be between the left and the right double precision floating point values + + True if both numbers are equal or close to being equal + + + Double precision floating point values can only represent a limited series of + natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 + can be stored in a double, but nothing inbetween them. + + + This comparison will count how many possible double precision floating point + values are between the left and the right number. If the number of possible + values between both numbers is less than or equal to maxUlps, then the numbers + are considered as being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + + Reinterprets the memory contents of a floating point value as an integer value + + + Floating point value whose memory contents to reinterpret + + + The memory contents of the floating point value interpreted as an integer + + + + + Reinterprets the memory contents of a double precision floating point + value as an integer value + + + Double precision floating point value whose memory contents to reinterpret + + + The memory contents of the double precision floating point value + interpreted as an integer + + + + + Reinterprets the memory contents of an integer as a floating point value + + Integer value whose memory contents to reinterpret + + The memory contents of the integer value interpreted as a floating point value + + + + + Reinterprets the memory contents of an integer value as a double precision + floating point value + + Integer whose memory contents to reinterpret + + The memory contents of the integer interpreted as a double precision + floating point value + + + + Union of a floating point variable and an integer + + + The union's value as a floating point variable + + + The union's value as an integer + + + The union's value as an unsigned integer + + + Union of a double precision floating point variable and a long + + + The union's value as a double precision floating point variable + + + The union's value as a long + + + The union's value as an unsigned long + + + + Tests whether a value is greater than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is greater than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + InstanceOfTypeConstraint is used to test that an object + is of the same type provided or derived from it. + + + + + Construct an InstanceOfTypeConstraint for the type provided + + The expected Type + + + + Test whether an object is of the specified type or a derived type + + The object to be tested + True if the object is of the provided type or derives from it, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + Tests whether a value is less than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is less than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Static methods used in creating messages + + + + + Static string used when strings are clipped + + + + + Returns the representation of a type as used in NUnitLite. + This is the same as Type.ToString() except for arrays, + which are displayed with their declared sizes. + + + + + + + Converts any control characters in a string + to their escaped representation. + + The string to be converted + The converted string + + + + Return the a string representation for a set of indices into an array + + Array of indices for which a string is needed + + + + Get an array of indices representing the point in a enumerable, + collection or array corresponding to a single int index into the + collection. + + The collection to which the indices apply + Index in the collection + Array of indices + + + + Clip a string to a given length, starting at a particular offset, returning the clipped + string with ellipses representing the removed parts + + The string to be clipped + The maximum permitted length of the result string + The point at which to start clipping + The clipped string + + + + Clip the expected and actual strings in a coordinated fashion, + so that they may be displayed together. + + + + + + + + + Shows the position two strings start to differ. Comparison + starts at the start index. + + The expected string + The actual string + The index in the strings at which comparison should start + Boolean indicating whether case should be ignored + -1 if no mismatch found, or the index where mismatch found + + + + NaNConstraint tests that the actual value is a double or float NaN + + + + + Test that the actual value is an NaN + + + + + + + Write the constraint description to a specified writer + + + + + + NoItemConstraint applies another constraint to each + item in a collection, failing if any of them succeeds. + + + + + Construct a NoItemConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + NotConstraint negates the effect of some other constraint + + + + + Initializes a new instance of the class. + + The base constraint to be negated. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + NullConstraint tests that the actual value is null + + + + + Initializes a new instance of the class. + + + + + NullEmptyStringConstraint tests whether a string is either null or empty. + + + + + Constructs a new NullOrEmptyStringConstraint + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + The Numerics class contains common operations on numeric values. + + + + + Checks the type of the object, returning true if + the object is a numeric type. + + The object to check + true if the object is a numeric type + + + + Checks the type of the object, returning true if + the object is a floating point numeric type. + + The object to check + true if the object is a floating point numeric type + + + + Checks the type of the object, returning true if + the object is a fixed point numeric type. + + The object to check + true if the object is a fixed point numeric type + + + + Test two numeric values for equality, performing the usual numeric + conversions and using a provided or default tolerance. If the tolerance + provided is Empty, this method may set it to a default tolerance. + + The expected value + The actual value + A reference to the tolerance in effect + True if the values are equal + + + + Compare two numeric values, performing the usual numeric conversions. + + The expected value + The actual value + The relationship of the values to each other + + + + NUnitComparer encapsulates NUnit's default behavior + in comparing two objects. + + + + + Compares two objects + + + + + + + + Returns the default NUnitComparer. + + + + + Generic version of NUnitComparer + + + + + + Compare two objects of the same type + + + + + NUnitEqualityComparer encapsulates NUnit's handling of + equality tests between objects. + + + + + + + + + + Compares two objects for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + + If true, all string comparisons will ignore case + + + + + If true, arrays will be treated as collections, allowing + those of different dimensions to be compared + + + + + Comparison objects used in comparisons for some constraints. + + + + + List of points at which a failure occured. + + + + + RecursionDetector used to check for recursion when + evaluating self-referencing enumerables. + + + + + Compares two objects for equality within a tolerance, setting + the tolerance to the actual tolerance used if an empty + tolerance is supplied. + + + + + Helper method to compare two arrays + + + + + Method to compare two DirectoryInfo objects + + first directory to compare + second directory to compare + true if equivalent, false if not + + + + Returns the default NUnitEqualityComparer + + + + + Gets and sets a flag indicating whether case should + be ignored in determining equality. + + + + + Gets and sets a flag indicating that arrays should be + compared as collections, without regard to their shape. + + + + + Gets the list of external comparers to be used to + test for equality. They are applied to members of + collections, in place of NUnit's own logic. + + + + + Gets the list of failure points for the last Match performed. + The list consists of objects to be interpreted by the caller. + This generally means that the caller may only make use of + objects it has placed on the list at a particular depthy. + + + + + RecursionDetector detects when a comparison + between two enumerables has reached a point + where the same objects that were previously + compared are again being compared. This allows + the caller to stop the comparison if desired. + + + + + Check whether two objects have previously + been compared, returning true if they have. + The two objects are remembered, so that a + second call will always return true. + + + + + OrConstraint succeeds if either member succeeds + + + + + Create an OrConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply the member constraints to an actual value, succeeding + succeeding as soon as one of them succeeds. + + The actual value + True if either constraint succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + PathConstraint serves as the abstract base of constraints + that operate on paths and provides several helper methods. + + + + + The expected path used in the constraint + + + + + Flag indicating whether a caseInsensitive comparison should be made + + + + + Construct a PathConstraint for a give expected path + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Returns true if the expected path and actual path match + + + + + Returns the string representation of this constraint + + + + + Transform the provided path to its canonical form so that it + may be more easily be compared with other paths. + + The original path + The path in canonical form + + + + Test whether one path in canonical form is under another. + + The first path - supposed to be the parent path + The second path - supposed to be the child path + Indicates whether case should be ignored + + + + + Modifies the current instance to be case-insensitve + and returns it. + + + + + Modifies the current instance to be case-sensitve + and returns it. + + + + + Predicate constraint wraps a Predicate in a constraint, + returning success if the predicate is true. + + + + + Construct a PredicateConstraint from a predicate + + + + + Determines whether the predicate succeeds when applied + to the actual value. + + + + + Writes the description to a MessageWriter + + + + + PropertyConstraint extracts a named property and uses + its value as the actual value for a chained constraint. + + + + + Initializes a new instance of the class. + + The name. + The constraint to apply to the property. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + PropertyExistsConstraint tests that a named property + exists on the object provided through Match. + + Originally, PropertyConstraint provided this feature + in addition to making optional tests on the vaue + of the property. The two constraints are now separate. + + + + + Initializes a new instance of the class. + + The name of the property. + + + + Test whether the property exists for a given object + + The object to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + RangeConstraint tests whether two values are within a + specified range. + + + + + Initializes a new instance of the class. + + From. + To. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + RegexConstraint can test whether a string matches + the pattern provided. + + + + + Initializes a new instance of the class. + + The pattern. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ResolvableConstraintExpression is used to represent a compound + constraint being constructed at a point where the last operator + may either terminate the expression or may have additional + qualifying constraints added to it. + + It is used, for example, for a Property element or for + an Exception element, either of which may be optionally + followed by constraints that apply to the property or + exception. + + + + + Create a new instance of ResolvableConstraintExpression + + + + + Create a new instance of ResolvableConstraintExpression, + passing in a pre-populated ConstraintBuilder. + + + + + Resolve the current expression to a Constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Appends an And Operator to the expression + + + + + Appends an Or operator to the expression. + + + + + ReusableConstraint wraps a constraint expression after + resolving it so that it can be reused consistently. + + + + + Construct a ReusableConstraint from a constraint expression + + The expression to be resolved and reused + + + + Converts a constraint to a ReusableConstraint + + The constraint to be converted + A ReusableConstraint + + + + Returns the string representation of the constraint. + + A string representing the constraint + + + + Resolves the ReusableConstraint by returning the constraint + that it originally wrapped. + + A resolved constraint + + + + SameAsConstraint tests whether an object is identical to + the object passed to its constructor + + + + + Initializes a new instance of the class. + + The expected object. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Summary description for SamePathConstraint. + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SamePathOrUnderConstraint tests that one path is under another + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SomeItemsConstraint applies another constraint to each + item in a collection, succeeding if any of them succeeds. + + + + + Construct a SomeItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + succeeding if any item succeeds. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + StartsWithConstraint can test whether a string starts + with an expected substring. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubPathConstraint tests that the actual path is under the expected path + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubstringConstraint can test whether a string contains + the expected substring. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ThrowsConstraint is used to test the exception thrown by + a delegate by applying a constraint to it. + + + + + Initializes a new instance of the class, + using a constraint to be applied to the exception. + + A constraint to apply to the caught exception. + + + + Executes the code of the delegate and captures any exception. + If a non-null base constraint was provided, it applies that + constraint to the exception. + + A delegate representing the code to be tested + True if an exception is thrown and the constraint succeeds, otherwise false + + + + Converts an ActualValueDelegate to a TestDelegate + before calling the primary overload. + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Get the actual exception thrown - used by Assert.Throws. + + + + + ThrowsNothingConstraint tests that a delegate does not + throw an exception. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True if no exception is thrown, otherwise false + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overridden in ThrowsNothingConstraint to write + information about the exception that was actually caught. + + The writer on which the actual value is displayed + + + + The Tolerance class generalizes the notion of a tolerance + within which an equality test succeeds. Normally, it is + used with numeric types, but it can be used with any + type that supports taking a difference between two + objects and comparing that difference to a value. + + + + + Constructs a linear tolerance of a specdified amount + + + + + Constructs a tolerance given an amount and ToleranceMode + + + + + Tests that the current Tolerance is linear with a + numeric value, throwing an exception if it is not. + + + + + Returns an empty Tolerance object, equivalent to + specifying no tolerance. In most cases, it results + in an exact match but for floats and doubles a + default tolerance may be used. + + + + + Returns a zero Tolerance object, equivalent to + specifying an exact match. + + + + + Gets the ToleranceMode for the current Tolerance + + + + + Gets the value of the current Tolerance instance. + + + + + Returns a new tolerance, using the current amount as a percentage. + + + + + Returns a new tolerance, using the current amount in Ulps. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of days. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of hours. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of minutes. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of seconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of milliseconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of clock ticks. + + + + + Returns true if the current tolerance is empty. + + + + + Modes in which the tolerance value for a comparison can be interpreted. + + + + + The tolerance was created with a value, without specifying + how the value would be used. This is used to prevent setting + the mode more than once and is generally changed to Linear + upon execution of the test. + + + + + The tolerance is used as a numeric range within which + two compared values are considered to be equal. + + + + + Interprets the tolerance as the percentage by which + the two compared values my deviate from each other. + + + + + Compares two values based in their distance in + representable numbers. + + + + + TrueConstraint tests that the actual value is true + + + + + Initializes a new instance of the class. + + + + + UniqueItemsConstraint tests whether all the items in a + collection are unique. + + + + + Check that all items are unique. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + XmlSerializableConstraint tests whether + an object is serializable in XML format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Represents a constraint that succeeds if all the + members of a collection match a base constraint. + + + + + Abstract base for operators that indicate how to + apply a constraint to items in a collection. + + + + + PrefixOperator takes a single constraint and modifies + it's action in some way. + + + + + The ConstraintOperator class is used internally by a + ConstraintBuilder to represent an operator that + modifies or combines constraints. + + Constraint operators use left and right precedence + values to determine whether the top operator on the + stack should be reduced before pushing a new operator. + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + The syntax element preceding this operator + + + + + The syntax element folowing this operator + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Returns the constraint created by applying this + prefix to another constraint. + + + + + + + Constructs a CollectionOperator + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + they all succeed. + + + + + Operator that requires both it's arguments to succeed + + + + + Abstract base class for all binary operators + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Abstract method that produces a constraint by applying + the operator to its left and right constraint arguments. + + + + + Gets the left precedence of the operator + + + + + Gets the right precedence of the operator + + + + + Construct an AndOperator + + + + + Apply the operator to produce an AndConstraint + + + + + Operator that tests for the presence of a particular attribute + on a type and optionally applies further tests to the attribute. + + + + + Abstract base class for operators that are able to reduce to a + constraint whether or not another syntactic element follows. + + + + + Construct an AttributeOperator for a particular Type + + The Type of attribute tested + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that succeeds if the specified + count of members of a collection match a base constraint. + + + + + Construct an ExactCountOperator for a specified count + + The expected count + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Represents a constraint that succeeds if none of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Negates the test of the constraint it wraps. + + + + + Constructs a new NotOperator + + + + + Returns a NotConstraint applied to its argument. + + + + + Operator that requires at least one of it's arguments to succeed + + + + + Construct an OrOperator + + + + + Apply the operator to produce an OrConstraint + + + + + Operator used to test for the presence of a named Property + on an object and optionally apply further tests to the + value of that property. + + + + + Constructs a PropOperator for a particular named property + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Gets the name of the property to which the operator applies + + + + + Represents a constraint that succeeds if any of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + any of them succeed. + + + + + Operator that tests that an exception is thrown and + optionally applies further tests to the exception. + + + + + Construct a ThrowsOperator + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that simply wraps the + constraint provided as an argument, without any + further functionality, but which modifes the + order of evaluation because of its precedence. + + + + + Constructor for the WithOperator + + + + + Returns a constraint that wraps its argument + + + + + Thrown when an assertion failed. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when a test executes inconclusively. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + + + + + + + Compares two objects of a given Type for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + diff --git a/ext/NUnit/nunit.mocks.dll b/ext/NUnit/nunit.mocks.dll new file mode 100644 index 00000000..50393b3f Binary files /dev/null and b/ext/NUnit/nunit.mocks.dll differ diff --git a/prune.bat b/prune.bat new file mode 100644 index 00000000..f1be3899 --- /dev/null +++ b/prune.bat @@ -0,0 +1,35 @@ +@echo off + +SETLOCAL + +REM ###################################### +REM # Make sure git tools are accessible +REM # (assume default installation dir) +REM # + +set ProgFilesRoot=%ProgramFiles(x86)% +if "%ProgFilesRoot%" == "" set ProgFilesRoot=%ProgramFiles% +set PATH=%PATH%;%ProgFilesRoot%\Git\bin; + +echo Repository cleanup script +echo. + +REM ###################################### +REM # Reading names from: +REM # - 'prune.tags.txt' +REM # and +REM # removing all unnecessary tags +REM # + +echo Removing tags... +FOR /F "eol=; delims==" %%i in (prune.tags.txt) do ( + echo Removing tag '%%i'... + git tag -d "%%i" +) + +echo [DONE] + +REM # +REM ###################################### + +ENDLOCAL diff --git a/prune.tags.txt b/prune.tags.txt new file mode 100644 index 00000000..62a5d52f --- /dev/null +++ b/prune.tags.txt @@ -0,0 +1,22 @@ +; +; Put extra tag names here +; +v +vv1.01.0036 +vv1.01.0041-2 +vv1.01.0042 +vv1.01.0043 +vv1.01.0045 +vv1.2.0001-4 +vv2.0.0001 +vv2.0.0002 +vv2.0.0002-1 +vv2.0.0003 +vv2.0.0004 +vv2.0.0005 +vv2.0.0005-2 +vv2.0.0005-3 +vv2.0.0006 +vv3.0.0.15 +vv3.0.0003 +vv3.0.0002 diff --git a/samples/FallingBlocks/FallingBlocks.sln b/samples/FallingBlocks/FallingBlocks.sln index 9e6120b3..a2d27f9b 100644 --- a/samples/FallingBlocks/FallingBlocks.sln +++ b/samples/FallingBlocks/FallingBlocks.sln @@ -1,6 +1,6 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FallingBlocks", "FallingBlocks\FallingBlocks.vcxproj", "{90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}" EndProject Global @@ -16,26 +16,16 @@ Global Simulator-Debug|Win32 = Simulator-Debug|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerry.Build.0 = Debug|BlackBerry - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator + {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerry.ActiveCfg = Debug|Win32 + {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|BlackBerrySimulator.ActiveCfg = Debug|Win32 {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|Win32.ActiveCfg = Debug|Win32 {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Debug|Win32.Build.0 = Debug|Win32 - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|BlackBerry.ActiveCfg = Release|BlackBerry - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|BlackBerry.Build.0 = Release|BlackBerry - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator + {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|BlackBerry.ActiveCfg = Release|Win32 + {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|BlackBerrySimulator.ActiveCfg = Release|Win32 {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|Win32.ActiveCfg = Release|Win32 {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Release|Win32.Build.0 = Release|Win32 - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|BlackBerry.ActiveCfg = Simulator-Debug|BlackBerry - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|BlackBerry.Build.0 = Simulator-Debug|BlackBerry - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|BlackBerrySimulator.ActiveCfg = Simulator-Debug|BlackBerrySimulator - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|BlackBerrySimulator.Build.0 = Simulator-Debug|BlackBerrySimulator - {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|BlackBerrySimulator.Deploy.0 = Simulator-Debug|BlackBerrySimulator + {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|BlackBerry.ActiveCfg = Simulator-Debug|Win32 + {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|BlackBerrySimulator.ActiveCfg = Simulator-Debug|Win32 {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|Win32.ActiveCfg = Simulator-Debug|Win32 {90124CDE-5D40-4B1B-ADCD-4DCF309A4FC8}.Simulator-Debug|Win32.Build.0 = Simulator-Debug|Win32 EndGlobalSection diff --git a/samples/FallingBlocks/FallingBlocks/FallingBlocks.vcxproj.user b/samples/FallingBlocks/FallingBlocks/FallingBlocks.vcxproj.user deleted file mode 100644 index 695b5c78..00000000 --- a/samples/FallingBlocks/FallingBlocks/FallingBlocks.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/samples/HelloWorldDisplay/HelloWorldDisplay.sln b/samples/HelloWorldDisplay/HelloWorldDisplay.sln index fadfcf17..b64fe081 100644 --- a/samples/HelloWorldDisplay/HelloWorldDisplay.sln +++ b/samples/HelloWorldDisplay/HelloWorldDisplay.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +# Visual Studio 2013 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloWorldDisplay", "HelloWorldDisplay\HelloWorldDisplay.vcxproj", "{92A45A6C-CC44-42BF-895E-93C1FD0F1842}" EndProject Global diff --git a/samples/HelloWorldDisplay/HelloWorldDisplay/HelloWorldDisplay.vcxproj.user b/samples/HelloWorldDisplay/HelloWorldDisplay/HelloWorldDisplay.vcxproj.user deleted file mode 100644 index 695b5c78..00000000 --- a/samples/HelloWorldDisplay/HelloWorldDisplay/HelloWorldDisplay.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/samples/HelloWorldDisplay/HelloWorldDisplay/bbutil.c b/samples/HelloWorldDisplay/HelloWorldDisplay/bbutil.c index 830d2c85..35ec1fd2 100644 --- a/samples/HelloWorldDisplay/HelloWorldDisplay/bbutil.c +++ b/samples/HelloWorldDisplay/HelloWorldDisplay/bbutil.c @@ -24,7 +24,7 @@ #include #include "bbutil.h" -#define USING_GL11; +#define USING_GL11 //#include //#include diff --git a/setup.bat b/setup.bat new file mode 100644 index 00000000..f1cec20b --- /dev/null +++ b/setup.bat @@ -0,0 +1,289 @@ +@echo off +setlocal EnableExtensions + +REM ******************************************************************************************** +REM Allow selective installation/uninstallation +REM ******************************************************************************************** + +:: Process parameters, to limit setup activities or directions +if "%~1" == "" ( + set ActionVS2010=1 + set ActionVS2012=1 + set ActionVS2013=1 + set ActionUninstall=0 + set ActionSkipTools=0 + set ActionMSBuildOnly=0 +) else ( + set ActionVS2010=0 + set ActionVS2012=0 + set ActionVS2013=0 + set ActionUninstall=0 + set ActionSkipTools=0 + set ActionMSBuildOnly=0 + for %%a in (%*) do ( + if /i "%%a" == "/all" set ActionVS2010=1 && set ActionVS2012=1 && set ActionVS2013=1 + if /i "%%a" == "/uninstall" set ActionUninstall=1 + if /i "%%a" == "/u" set ActionUninstall=1 + if /i "%%a" == "/delete" set ActionUninstall=1 + if /i "%%a" == "/del" set ActionUninstall=1 + if /i "%%a" == "/skip-tools" set ActionSkipTools=1 + if /i "%%a" == "/no-tools" set ActionSkipTools=1 + if /i "%%a" == "/notools" set ActionSkipTools=1 + if /i "%%a" == "/msbuild" set ActionMSBuildOnly=1 + if /i "%%a" == "/msbuild-only" set ActionMSBuildOnly=1 + if /i "%%a" == "/msbuildonly" set ActionMSBuildOnly=1 + if /i "%%a" == "/only-msbuild" set ActionMSBuildOnly=1 + if /i "%%a" == "/onlymsbuild" set ActionMSBuildOnly=1 + if /i "%%a" == "vs2010" set ActionVS2010=1 + if /i "%%a" == "vs2012" set ActionVS2012=1 + if /i "%%a" == "vs2013" set ActionVS2013=1 + ) +) + +REM ******************************************************************************************** +REM Declare Constants +REM ******************************************************************************************** +set /A actionNo=1 +set thisDir=%~dp0 +set thisDir=%thisDir:~0,-1% +set BuildResults=%thisDir%\_BuildResults + +set ProgFilesRoot=%ProgramFiles(x86)% +set SystemArch=x64 +if "%ProgFilesRoot%" == "" set "ProgFilesRoot=%ProgramFiles%" && set SystemArch=x86 + +set AllUsersRoot=%ALLUSERSPROFILE% +set PluginRoot=%ProgFilesRoot%\BlackBerry\VSPlugin-NDK + +if %ActionUninstall% neq 0 (echo Performing REMOVAL action...) else (echo Performing INSTALLATION action...) + +REM ******************************************************************************************** +REM Visual Studio 2010 +REM ******************************************************************************************** +if %ActionVS2010% equ 0 (goto skip_vs2010) + +echo %actionNo%: Processing Setup for Visual Studio 2010 +call :processSetup 2010 10.0 +if errorlevel 1 ( exit /b %errorlevel% ) +if %ActionUninstall% neq 0 (echo %actionNo%: Removal - DONE) else (echo %actionNo%: Installation - DONE) +set /a actionNo += 1 + +:skip_vs2010 + +REM ******************************************************************************************** +REM Visual Studio 2012 +REM ******************************************************************************************** +if %ActionVS2012% equ 0 (goto skip_vs2012) + +echo %actionNo%: Processing Setup for Visual Studio 2012 +call :processSetup 2012 11.0 V110 +if errorlevel 1 ( exit /b %errorlevel% ) +if %ActionUninstall% neq 0 (echo %actionNo%: Removal - DONE) else (echo %actionNo%: Installation - DONE) +set /a actionNo += 1 + +:skip_vs2012 + +REM ******************************************************************************************** +REM Visual Studio 2013 +REM ******************************************************************************************** +if %ActionVS2013% equ 0 (goto skip_vs2013) + +echo %actionNo%: Processing Setup for Visual Studio 2013 +call :processSetup 2013 12.0 V120 +if errorlevel 1 ( exit /b %errorlevel% ) +if %ActionUninstall% neq 0 (echo %actionNo%: Removal - DONE) else (echo %actionNo%: Installation - DONE) +set /a actionNo += 1 + +:skip_vs2013 + +REM ******************************************************************************************** +REM Helper functions +REM ******************************************************************************************** +goto EOF + +REM ******************************************************************************************** +REM Aggregate function to perform all actions needed to correctly deploy plugin +REM $1 - Visual Studio number (2012) +REM $2 - Visual Studio version (12.0) +REM $3 - Visual Studio selector (V120) # optional +:processSetup +setlocal EnableDelayedExpansion + +set VSYear=%1 +set VSVersion=%~2 +set VSSelector=%~3 +set BuildPath=%BuildResults%\VS%VSYear% +set VSPluginPath=%ProgFilesRoot%\Microsoft Visual Studio %VSVersion%\Common7\IDE\Extensions\NDK Plugin + +set MSBuildTargetPath=%ProgFilesRoot%\MSBuild\Microsoft.Cpp\v4.0\Platforms +if not "%VSSelector%" == "" set MSBuildTargetPath=%ProgFilesRoot%\MSBuild\Microsoft.Cpp\v4.0\%VSSelector%\Platforms + +set /a actionNo += 1 + +REM Skip tools&plugin, if only upgrading MSBuild (in case of debugger development) +if %ActionMSBuildOnly% neq 0 goto msbuild_only + +REM Skip installation of custom tools (in case upgrading only plugin during development) +if %ActionSkipTools% neq 0 goto skip_tools +call :processTools "%thisDir%" "%PluginRoot%" "%SystemDrive%" +set /a actionNo += 1 +:skip_tools + +call :processPlugin "%BuildPath%" "%PluginRoot%" "%VSPluginPath%" +set /a actionNo += 1 + +:msbuild_only +call :processMSBuild "%BuildPath%" "%MSBuildTargetPath%" +set /a actionNo += 1 +if %ActionMSBuildOnly% neq 0 goto processSetup_End + +:processSetup_End +endlocal +exit /b + +REM ******************************************************************************************** +REM MSBuild system upgrade +REM ******************************************************************************************** +REM $1 - from +REM $2 - MSBuild Targets path +:processMSBuild +setlocal + +set InputPath=%~1 +set OutputMsBuildTargetsPath=%~2 + +if %ActionUninstall% neq 0 (goto uninstall_MSBuild) + +REM MSBuild Files +echo %actionNo%: Installing build targets +echo Copy BlackBerry MSBuild directory [%OutputMsBuildTargetsPath%] +if exist "%OutputMsBuildTargetsPath%\BlackBerry" ( rd "%OutputMsBuildTargetsPath%\BlackBerry" /s /q ) +xcopy "%InputPath%\BlackBerry" "%OutputMsBuildTargetsPath%\BlackBerry" /e /i /y +copy "%InputPath%\BlackBerry.BuildTasks.dll" "%OutputMsBuildTargetsPath%\BlackBerry\BlackBerry.BuildTasks.dll" + +goto processMSBuild_End + +:uninstall_MSBuild + +REM Remove MSBuild Files +echo %actionNo%: Removing build targets +echo Delete BlackBerry MSBuild directory +rd "%OutputMsBuildTargetsPath%\BlackBerry" /s /q + +:processMSBuild_End +endlocal +exit /b + +REM ******************************************************************************************** +REM Copy GDBParser and DebugEngine Files +REM ******************************************************************************************** +REM $1 - from +REM $2 - to (plugin path) +REM $3 - to (Visual Studio path) +:processPlugin +setlocal EnableDelayedExpansion + +set InputPath=%~1 +set OutputPluginPath=%~2 +set OutputVsPath=%~3 + +if %ActionUninstall% neq 0 (goto uninstall_Plugin) + +REM Create folders +echo %actionNo%: Installing plugin binaries +echo Make Directory "%OutputPluginPath%" +md "%OutputPluginPath%" +echo Make Directory "%OutputVsPath%" +md "%OutputVsPath%" + +REM Install Package Files +echo "%InputPath%\extension.vsixmanifest" to "%OutputVsPath%\extension.vsixmanifest" +copy "%InputPath%\extension.vsixmanifest" "%OutputVsPath%\extension.vsixmanifest" +echo "%InputPath%\BlackBerry.GDBHost.exe" to "%OutputVsPath%\BlackBerry.GDBHost.exe" +copy "%InputPath%\BlackBerry.GDBHost.exe" "%OutputVsPath%\BlackBerry.GDBHost.exe" +echo "%InputPath%\BlackBerry.NativeCore.dll" to "%OutputVsPath%\BlackBerry.NativeCore.dll" +copy "%InputPath%\BlackBerry.NativeCore.dll" "%OutputVsPath%\BlackBerry.NativeCore.dll" +echo "%InputPath%\BlackBerry.Package.dll" to "%OutputVsPath%\BlackBerry.Package.dll" +copy "%InputPath%\BlackBerry.Package.dll" "%OutputVsPath%\BlackBerry.Package.dll" +echo "%InputPath%\BlackBerry.Package.pkgdef" to "%OutputVsPath%\BlackBerry.Package.pkgdef" +copy "%InputPath%\BlackBerry.Package.pkgdef" "%OutputVsPath%\BlackBerry.Package.pkgdef" +echo "%InputPath%\BlackBerry.DebugEngine.dll" to "%OutputVsPath%\BlackBerry.DebugEngine.dll" +copy "%InputPath%\BlackBerry.DebugEngine.dll" "%OutputVsPath%\BlackBerry.DebugEngine.dll" + +goto processPlugin_End + +:uninstall_Plugin + +echo %actionNo%: Removing plugin binaries + +REM Uninstall Package Files + +echo Deleting "%OutputVsPath%\extension.vsixmanifest" +del "%OutputVsPath%\extension.vsixmanifest" +echo Deleting "%OutputVsPath%\BlackBerry.GDBHost.exe" +del "%OutputVsPath%\BlackBerry.GDBHost.exe" +echo Deleting "%OutputVsPath%\BlackBerry.NativeCore.dll" +del "%OutputVsPath%\BlackBerry.NativeCore.dll" +echo Deleting "%OutputVsPath%\BlackBerry.Package.dll" +del "%OutputVsPath%\BlackBerry.Package.dll" +echo Deleting "%OutputVsPath%\BlackBerry.Package.pkgdef" +del "%OutputVsPath%\BlackBerry.Package.pkgdef" +echo Deleting "%OutputVsPath%\BlackBerry.DebugEngine.dll" +del "%OutputVsPath%\BlackBerry.DebugEngine.dll" + +REM Remove folders +echo Remove Directory "%OutputPluginPath%" +rd "%OutputPluginPath%" +echo Remove Directory "%OutputVsPath%" +rd "%OutputVsPath%" + +:processPlugin_End +endlocal +exit /b + +REM ******************************************************************************************** +REM NDK & QNX toolset +REM ******************************************************************************************** +REM $1 - from +REM $2 - to (plugin path) +REM $3 - NDK path +:processTools +setlocal EnableDelayedExpansion + +set InputPath=%~1 +set OutputPath=%~2 +set OutputNdkPath=%~3 + +if %ActionUninstall% neq 0 (goto uninstall_Tools) + +REM Install +echo %actionNo%: Installing toolset +echo xcopy "%InputPath%\bbndk_vs" "%OutputNdkPath%\bbndk_vs" /e /i /y +md "%OutputNdkPath%\bbndk_vs" +xcopy "%InputPath%\bbndk_vs" "%OutputNdkPath%\bbndk_vs" /e /i /y + +echo xcopy "%InputPath%\qnxtools" "%OutputPath%\qnxtools" /e /i /y +md "%OutputPath%\qnxtools" +xcopy "%InputPath%\qnxtools" "%OutputPath%\qnxtools" /e /i /y +goto processTools_End + +:uninstall_Tools + +REM Remove +echo %actionNo%: Removing toolset +echo Delete "%OutputNdkPath%\bbndk_vs" directory +rd "%OutputNdkPath%\bbndk_vs" /s /q +echo Delete "%OutputPath%\qnxtools" directory +rd "%OutputPath%\qnxtools" /s /q + +:processTools_End +endlocal +exit /b + +REM ******************************************************************************************** +REM END +REM ******************************************************************************************** + +:EOF +endlocal +echo [ALL DONE] diff --git a/src/GDBParser.UnitTests/GDBParser_UnitTests.csproj b/src/GDBParser.UnitTests/GDBParser_UnitTests.csproj deleted file mode 100644 index e5408b1d..00000000 --- a/src/GDBParser.UnitTests/GDBParser_UnitTests.csproj +++ /dev/null @@ -1,64 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {6451DFCD-1CCD-4796-A832-A45FB95D994F} - Library - Properties - GDBParser.UnitTests - GDBParser.UnitTests - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - {CC7B28E0-CB31-44F7-A380-E7072F670F38} - GDBParser - - - - - \ No newline at end of file diff --git a/src/GDBParser.UnitTests/Properties/AssemblyInfo.cs b/src/GDBParser.UnitTests/Properties/AssemblyInfo.cs deleted file mode 100644 index 7dfe25ba..00000000 --- a/src/GDBParser.UnitTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GDBParser.UnitTests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("GDBParser.UnitTests")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("80f98dd4-ce03-42f3-b852-346148df4493")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/GDBParser.UnitTests/UnitTest.cs b/src/GDBParser.UnitTests/UnitTest.cs deleted file mode 100644 index 42cc7323..00000000 --- a/src/GDBParser.UnitTests/UnitTest.cs +++ /dev/null @@ -1,381 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using VSNDK.Parser; -using NUnit.Framework; - -namespace GDBParser_UnitTests -{ - public class UnitTests - { - [Test] - public void GetNextChar() - { - Assert.AreEqual(0, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('a'), "abcdefghij", 0), "Error: char 'a', string 'abcdefghij', int '0'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('a'), "abcdefghij", 1), "Error: char 'a', string 'abcdefghij', int '1'"); - Assert.AreEqual(3, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "abcdefghij", 0), "Error: char 'd', string 'abcdefghij', int '0'"); - Assert.AreEqual(3, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "abcdefghij", 1), "Error: char 'd', string 'abcdefghij', int '1'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('z'), "abcdefghij", 1), "Error: char 'z', string 'abcdefghij', int '1'"); - Assert.AreEqual(0, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "", 1), "Error: char 'd', string '', int '1'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "abcdefghij", 12), "Error: char 'd', string 'abcdefghij', int '12'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte(null), "abcdefghij", 1), "Error: char NULL, string 'abcdefghij', int '1'"); - } - - [Test] - public void findClosing() - { - Assert.AreEqual(1, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "()cdefghij", 0), "Error: char '(', char '), string '()cdefghij', int '0'"); - Assert.AreEqual(10, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(bcdefghij", 2), "Error: char '(', char '), string '(bcdefghij', int '2'"); - Assert.AreEqual(10, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(bcdefghij", 0), "Error: char '(', char '), string '(bcdefghij', int '0'"); - Assert.AreEqual(5, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()())ghij", 0), "Error: char '(', char '), string '(()())ghij', int '0'"); - Assert.AreEqual(7, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((\\()())hij", 0), "Error: char '(', char '), string '((\\()())hij', int '0'"); - Assert.AreEqual(2, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()())ghij", 1), "Error: char '(', char '), string '(()())ghij', int '1'"); - Assert.AreEqual(4, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((\\()())hij", 1), "Error: char '(', char '), string '((\\()())hij', int '1'"); - Assert.AreEqual(4, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()())ghij", 3), "Error: char '(', char '), string '(()())ghij', int '3'"); - Assert.AreEqual(6, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()(())hij", 3), "Error: char '(', char '), string '(()(())hij', int '3'"); - Assert.AreEqual(1, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "()())fghij", 0), "Error: char '(', char '), string '()())fghij', int '0'"); - Assert.AreEqual(3, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "()())fghij", 2), "Error: char '(', char '), string '()())fghij', int '2'"); - Assert.AreEqual(10, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((())fghij", 0), "Error: char '(', char '), string '(()())ghij', int '0'"); - Assert.AreEqual(4, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((())fghij", 1), "Error: char '(', char '), string '((())fghij', int '1'"); - } - - [Test] - public void searchResponse() - { - // Add the values you want to test. - Assert.AreEqual(3, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 1, true, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '1', bool 'TRUE', char '?'"); - Assert.AreEqual(1, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 1, true, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '1', bool 'TRUE', char '@'"); - Assert.AreEqual(14, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 3, true, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '3', bool 'TRUE', char '?'"); - Assert.AreEqual(12, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 3, true, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '3', bool 'TRUE', char '@'"); - Assert.AreEqual(19, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 10, 3, true, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '10', int '3', bool 'TRUE', char '?'"); - Assert.AreEqual(17, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 10, 3, true, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '10', int '3', bool 'TRUE', char '@'"); - Assert.AreEqual(24, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 1, false, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '1', bool 'TRUE', char '?'"); - Assert.AreEqual(24, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 1, false, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '1', bool 'TRUE', char '@'"); - Assert.AreEqual(19, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 3, false, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '3', bool 'TRUE', char '?'"); - Assert.AreEqual(19, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 3, false, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '3', bool 'TRUE', char '@'"); - } - - [Test] - public void substituteVariables() - { - string[] v = new string[10]; - v[0] = "The"; - v[1] = "text"; - v[2] = ""; - v[3] = ""; - v[4] = ""; - v[5] = "the"; - v[6] = ""; - v[7] = ""; - v[8] = ""; - v[9] = "number"; - // Add the values you want to test. - StringAssert.AreEqualIgnoringCase("The number of the words in the following text is smaller than the number of the letters in the same text\r\n", GDBParserUnitTests.substitute_Variables("$0$ $9$ of $5$ words in $5$ following $1$ is smaller $3$than $5$ $9$ of $5$ letters in $5$ same $1$$EOL$", v), "Error: string '', Variables array not printed."); - } - - [Test] - public void insertingCommandCodes() - { - string[,] map = new string[48, 2]; // The value for the first column of this array corresponds to the value of NumberOfInstructions constant, in gdb-connect.h. - string[] v = new string[48]; // The size of this array corresponds to the value of NumberOfInstructions constant, in gdb-connect.h. - bool result = GDBParserUnitTests.inserting_Command_Codes(map, v); - Assert.AreEqual(true, result); - Assert.IsNotEmpty(map, "Hash table could not be empty!"); - Assert.IsNotEmpty(v, "Parsing instructions array could not be empty!"); - } - - [Test] - public void getInstructionCode() - { - // The instruction code returned from get_Instruction_Code() function depends on the position the associated parsing instruction - // was stored in the respective data structure. That's why the following unit tests just compares the instruction code with -1 - // (-1 means that the instruction was not found). - string param = ""; - // Add the values you want to test. - Assert.AreEqual(-1, GDBParserUnitTests.get_Instruction_Code("", out param), "Error: string '', string ''"); - StringAssert.AreEqualIgnoringCase("", param, "Param should be empty."); - - param = ""; - Assert.AreNotEqual(-1, GDBParserUnitTests.get_Instruction_Code("-exec-continue --thread-group i1", out param), "Error: string '-exec-continue --thread-group i1', string ''"); - StringAssert.AreEqualIgnoringCase("", param, "Param should be empty for command '-exec-continue --thread-group i1'."); - - param = ""; - Assert.AreNotEqual(-1, GDBParserUnitTests.get_Instruction_Code("-break-delete 3", out param), "Error: string '-break-delete 3', string ''"); - StringAssert.AreEqualIgnoringCase(";3", param, "Param should not be empty for command '-break-delete 3'."); - - param = ""; - Assert.AreNotEqual(-1, GDBParserUnitTests.get_Instruction_Code("-break-after 4 10", out param), "Error: string '-break-after 4 10', string ''"); - StringAssert.AreEqualIgnoringCase(";4;10", param, "Param should not be empty for command '-break-after 4 10'."); - } - - [Test] - public void get_SeqID() - { - // Add the values you want to test. - Assert.AreEqual(211, GDBParserUnitTests.get_Seq_ID("211^done,value=\"1\""), "Error: string '211^done,value=\"1\"'"); - Assert.AreEqual(111, GDBParserUnitTests.get_Seq_ID("111^running"), "Error: string '111^running'"); - Assert.AreEqual(-3, GDBParserUnitTests.get_Seq_ID("=breakpoint-modified,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0xf7fd8502\",func=\"pendfunc1\",file=\"gdb/testsuite/gdb.mi/pendshr1.c\",fullname=\"/unsafegdb/testsuite/gdb.mi/pendshr1.c\",line=\"21\",times=\"0\",original-location=\"pendfunc1\"}"), "Error: string '=breakpoint-modified,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0xf7fd8502\",func=\"pendfunc1\",file=\"gdb/testsuite/gdb.mi/pendshr1.c\",fullname=\"/unsafegdb/testsuite/gdb.mi/pendshr1.c\",line=\"21\",times=\"0\",original-location=\"pendfunc1\"}'"); - Assert.AreEqual(-2, GDBParserUnitTests.get_Seq_ID("*stopped,reason=\"breakpoint-hit\",disp=\"keep\",bkptno=\"2\",frame={func=\"foo\",args=[],file=\"hello.c\",fullname=\"/home/foo/bar/hello.c\",line=\"13\"}"), "Error: string '*stopped,reason=\"breakpoint-hit\",disp=\"keep\",bkptno=\"2\",frame={func=\"foo\",args=[],file=\"hello.c\",fullname=\"/home/foo/bar/hello.c\",line=\"13\"}'"); - Assert.AreEqual(-2, GDBParserUnitTests.get_Seq_ID("111*stopped,signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={addr=\"0x00010140\",func=\"foo\",args=[],file=\"try.c\",line=\"13\"}"), "Error: string '111*stopped,signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={addr=\"0x00010140\",func=\"foo\",args=[],file=\"try.c\",line=\"13\"}'"); - Assert.AreEqual(-1, GDBParserUnitTests.get_Seq_ID("abcde"), "Error: string 'abcde'"); - Assert.AreEqual(-1, GDBParserUnitTests.get_Seq_ID(""), "Error: string ''"); - } - - [Test] - public void parseGDB1() - { - string asyncInst = "??=thread-exited,id;{#51\\;;??\";@@\";#$EOL$;};??thread-created,id;{#40\\;;??\";@@\";#\\;;??pid ;@@ ;#$EOL$;};0;??*running;{#41\\;;??thread-id=\"all;{#0;}{??thread-id=\";@@\";};#$EOL$;};0;??*stopped;{??breakpoint-hit;{#27\\;;??bkptno=\";@@\";#\\;;??file=\";@@\";#\\;;??line=\";@@\";}{??end-stepping-range;{#45;??file=\";{#\\;;@@\";0;#\\;;??line=\";@@\";};}{??function-finished;{#46;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};}{??exited-normally;{#42;}{??exit-code;{#43\\;;??\";@@\";}{??signal-received;{??signal-meaning=\"Killed\";{#47;}{??signal-meaning=\"Segmentation fault\";{#54\\;;??addr=\";@@\";#\\;;??func=\";@@\";0;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};}{#44\\;;??addr=\";@@\";#\\;;??func=\";@@\";0;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};};};}{??exited-signalled;{#55\\;??signal-name=\";@@\";#\\;;??signal-meaning=\";@@\";}{#44\\;;??addr=\";@@\";#\\;;??func=\";@@\";0;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};};};};};};};};#\\;;??thread-id=;{??\";@@\";};#$EOL$;};0;??=breakpoint-modified,bkpt=\\{number=\";{0;($EOR$;$1=?HResult = hr; - } - - property HRESULT HResult - { - HRESULT get() - { - return Exception::HResult; - } - } -}; - -END_NAMESPACE diff --git a/src/GDBParser/Constants.cpp b/src/GDBParser/Constants.cpp deleted file mode 100644 index c21d40d8..00000000 --- a/src/GDBParser/Constants.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#include "stdafx.h" - -#pragma managed(on) - -BEGIN_NAMESPACE - -public ref class Constants -{ -public: - #undef S_OK - static const int S_OK = 0; - - #undef S_FALSE - static const int S_FALSE = 1; - - #define __E_NOTIMPL E_NOTIMPL - #undef E_NOTIMPL - static const int E_NOTIMPL = __E_NOTIMPL; - - #define __E_FAIL E_FAIL - #undef E_FAIL - static const int E_FAIL = __E_FAIL; - - static const int E_WIN32_INVALID_NAME = HRESULT_FROM_WIN32(ERROR_INVALID_NAME); - - static const int E_WIN32_ALREADY_INITIALIZED = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED); - - #define __RPC_E_SERVERFAULT RPC_E_SERVERFAULT - #undef RPC_E_SERVERFAULT - static const int RPC_E_SERVERFAULT = __RPC_E_SERVERFAULT; -}; - -END_NAMESPACE \ No newline at end of file diff --git a/src/GDBParser/GDBParser.def b/src/GDBParser/GDBParser.def deleted file mode 100644 index dae61e7a..00000000 --- a/src/GDBParser/GDBParser.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY "GDBParser" - -EXPORTS -DllRegisterServer PRIVATE -DllUnregisterServer PRIVATE \ No newline at end of file diff --git a/src/GDBParser/GDBParser.rc b/src/GDBParser/GDBParser.rc deleted file mode 100644 index 66dfd246..00000000 --- a/src/GDBParser/GDBParser.rc +++ /dev/null @@ -1,67 +0,0 @@ -// 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 - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#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 ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -IDR_GDBPARSER REGISTRY "GDBParser.rgs" - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - -IDR_GDBPARSER REGISTRY "GDBParser.rgs" - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/GDBParser/GDBParser.rgs b/src/GDBParser/GDBParser.rgs deleted file mode 100644 index aa6344f9..00000000 --- a/src/GDBParser/GDBParser.rgs +++ /dev/null @@ -1,59 +0,0 @@ -HKLM -{ - NoRemove SOFTWARE - { - NoRemove Microsoft - { - NoRemove VisualStudio - { - NoRemove 10.0 - { - NoRemove AD7Metrics - { - NoRemove Engine - { - '{D951924A-4999-42a0-9217-1EB5233D1D5A}' = s 'guidDebuggingSampleEngine' - { - val 'CLSID' = s '{8355452D-6D2F-41b0-89B8-BB2AA2529E94}' - val 'ProgramProvider' = s '{FF3E23A2-DA7E-4fa7-AF47-6EDEDE4E922E}' - val 'Attach' = d '1' - val 'AddressBP' = d '0' - val 'AutoSelectPriority' = d '4' - val 'CallstackBP' = d '1' - val 'Name' = s 'Sample Debug Engine' - val 'PortSupplier' = s '{708C1ECA-FF48-11D2-904F-00C04FA302A1}' - - 'IncompatibleList' - { - val 'guidCOMPlusNativeEng' = s '{92EF0900-2251-11D2-B72E-0000F87572EF}' - val 'guidCOMPlusOnlyEng' = s '{449EC4CC-30D2-4032-9256-EE18EB41B62B}' - val 'guidNativeOnlyEng' = s '{449EC4CC-30D2-4032-9256-EE18EB41B62B}' - val 'guidScriptEng' = s '{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}' - } - } - } - } - - NoRemove CLSID - { - '{8355452D-6D2F-41b0-89B8-BB2AA2529E94}' - { - val 'Assembly' = s 'Microsoft.VisualStudio.Debugger.SampleEngine' - val 'Class' = s 'Microsoft.VisualStudio.Debugger.SampleEngine.AD7Engine' - val 'InprocServer32' = s 'c:\windows\system32\mscoree.dll' - val 'CodeBase' = s '%GDBPARSERPATH%\Microsoft.VisualStudio.Debugger.SampleEngine.dll' - } - - '{FF3E23A2-DA7E-4fa7-AF47-6EDEDE4E922E}' - { - val 'Assembly' = s 'Microsoft.VisualStudio.Debugger.SampleEngine' - val 'Class' = s 'Microsoft.VisualStudio.Debugger.SampleEngine.AD7ProgramProvider' - val 'InprocServer32' = s 'c:\windows\system32\mscoree.dll' - val 'CodeBase' = s '%GDBPARSERPATH%\Microsoft.VisualStudio.Debugger.SampleEngine.dll' - } - } - } - } - } - } -} \ No newline at end of file diff --git a/src/GDBParser/GDBParser.vcxproj b/src/GDBParser/GDBParser.vcxproj deleted file mode 100644 index 6a577dc1..00000000 --- a/src/GDBParser/GDBParser.vcxproj +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {CC7B28E0-CB31-44F7-A380-E7072F670F38} - GDBParser - Win32Proj - GDBParser - - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30305.0 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - C:\Users\guarnold.RIMNET\vsplugin-ndk\src\gdb-connect;$(SourcePath) - C:\Users\guarnold.RIMNET\vsplugin-ndk\src\gdb-connect;$(IncludePath) - $(ReferencePath) - $(LibraryPath) - - - - Disabled - C:\VSPlugin-Git\vsplugin-ndk\src\gdb-connect;$(ProgramFiles)\Microsoft Visual Studio 10.0\DIA SDK\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;DEBUG;%(PreprocessorDefinitions) - false - Default - MultiThreadedDebugDLL - Use - Level3 - ProgramDatabase - - - $(IntDir);%(AdditionalIncludeDirectories) - $(IntDir)GDBParser.res - - - true - psapi.lib;$(ProgramFiles)\Microsoft Visual Studio 10.0\DIA SDK\lib\diaguids.lib;%(AdditionalDependencies) - GDBParser.def - true - true - Windows - false - - - MachineX86 - - - - - - - - - $(VSInstallDir)\DIA SDK\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - MultiThreadedDLL - Use - Level3 - ProgramDatabase - - - true - psapi.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;%(AdditionalDependencies) - GDBParser.def - true - Windows - true - true - false - - - MachineX86 - - - xcopy "$(ProjectDir)Instructions.txt" "$(OutputPath)" /d /y - Copying Instructions.txt to output directory. - - - - - true - true - - - - - - - - false - - - false - - - - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/GDBParser/GDBParser.vcxproj.filters b/src/GDBParser/GDBParser.vcxproj.filters deleted file mode 100644 index 5c165339..00000000 --- a/src/GDBParser/GDBParser.vcxproj.filters +++ /dev/null @@ -1,74 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - {3bb6314f-66c5-4c9f-b290-dfa7cf75aeea} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - Resource Files - - - - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Source Files\GDBParser API Header files - - - - - Resource Files - - - \ No newline at end of file diff --git a/src/GDBParser/GDBParser.vcxproj.user b/src/GDBParser/GDBParser.vcxproj.user deleted file mode 100644 index ace9a86a..00000000 --- a/src/GDBParser/GDBParser.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/GDBParser/GDBParserAPI.cpp b/src/GDBParser/GDBParserAPI.cpp deleted file mode 100644 index eca44cd4..00000000 --- a/src/GDBParser/GDBParserAPI.cpp +++ /dev/null @@ -1,854 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#include "stdafx.h" - -#pragma managed(on) - -#include -#include < stdio.h > -#include < stdlib.h > -#include < vcclr.h > -using namespace System; -using namespace System::Text::RegularExpressions; -using namespace Microsoft::Win32; - -#include "ProjInclude.h" - -// GDBParser API header files (in alphabetical order) -#include "GDBParserAPI.h" - -#include "gdb-connect.h" - -using namespace std; - - -/// -/// Set an auto pointer given a String^. -/// -/// String. -/// Auto pointer. -CAutoPtr convertToAutoPtrFromString(String^ str) { - CAutoPtr ap; - - pin_ptr pkwc = PtrToStringChars(str); - char* pc = new char[(wcslen(pkwc) + 1) * sizeof(char)]; - ap.Attach(pc); - - // Convert wchar_t* to a char* - size_t origsize = wcslen(pkwc) + 1; - size_t convertedChars = 0; - wcstombs_s(&convertedChars, ap, origsize, pkwc, _TRUNCATE); - - return ap; -} - - -/// -/// Gets a parsed asynchronous GDB response from Output Buffer. Also can get a parsed GDB response for a non-synchronous GDB -/// COMMAND from Output buffer. This method is called by the Event Dispather of the Debug Engine. -/// -/// Parsed GDB response. -String^ GDBParser::removeGDBResponse() -{ - char output[ParsedMessageSize] = ""; - removeFromOutputBuffer(output); - String ^systemstring = gcnew String(output); - return systemstring; -} - - -/// -/// Sends a non-synchronous GDB command by adding it into the Input Buffer. This method is called by the Debug Engine whenever -/// it needs to send a GDB command without having to wait for the respective GDB response. -/// -/// Command to be sent to GDB. -/// True. -bool GDBParser::addGDBCommand(String^ GDBCommand) -{ - CAutoPtr apCmd = convertToAutoPtrFromString(GDBCommand); - while (!addIntoInputBuffer(apCmd)); // Keep trying until it is added into Input buffer - return(true); -} - - -/// -/// Exits GDB. This method is called to end the debug session by Event Dispatcher (Debug Engine) or directly by the debug engine -/// when it fails to launch a new debug session. -/// -void GDBParser::exitGDB() -{ - // Sends the command that exits GDB immediately. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html) - addGDBCommand("-gdb-exit"); - GDBConsole::shutdown(); - s_running = false; - if (m_BBConnectProcess) - TerminateProcess(m_BBConnectProcess, 0); -} - - -/// -/// Verify if Input buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool GDBParser::is_Input_Buffer_Empty() -{ - return(isInputBufferEmpty()); -} - - -/// -/// Sends a synchronous GDB command by adding it into the Input Buffer and waiting for the respective GDB response. This -/// method is called by the Debug Engine whenever it needs a GDB response for a given GDB command. -/// -/// Command to be sent to GDB. -/// Instruction ID. -/// Parsed GDB response. -String^ GDBParser::parseCommand(String^ GDBCommand, int ID) -{ - char output[ParsedMessageSize] = ""; - CAutoPtr apCmd; - if (ID < 10) - apCmd = convertToAutoPtrFromString("0" + ID + GDBCommand); - else - apCmd = convertToAutoPtrFromString(ID + GDBCommand); - - while (!addIntoInputBuffer(apCmd) && s_running) - Sleep(0); // keep trying to add into buffer - - while (strcmp(output,"") == 0 && s_running) - removeSyncFromOutputBuffer(output, ID); - if (strcmp(output,"$#@EMPTY@#$") == 0) // This string means that both GDB and the parser worked well and returned an empty string. - strcpy(output,""); - - String ^systemstring = gcnew String(output); - return systemstring; -} - - -/// -/// Sets the NDK variables. -/// -/// Boolean value that indicates which of the simulator/device is being used: -/// True -> simulator; -/// False -> Device. -void GDBParser::setNDKVars(bool isSimulator) { - String^ keyPath = "HKEY_CURRENT_USER\\Software\\BlackBerry\\BlackBerryVSPlugin"; - String^ ndkHostPath = (String^)Registry::GetValue(keyPath, "NDKHostPath", ""); - String^ ndkTargetPath = (String^)Registry::GetValue(keyPath, "NDKTargetPath", ""); - m_remotePath = (String^)Registry::GetValue(keyPath, "NDKRemotePath", ""); - - if (isSimulator) { - m_pcGDBCmd = ndkHostPath + "\\usr\\bin\\ntox86-gdb.exe --interpreter=mi2"; - m_libPaths[0] = ndkTargetPath + "\\x86\\lib"; - m_libPaths[1] = ndkTargetPath + "\\x86\\usr\\lib"; - } else { - m_pcGDBCmd = ndkHostPath + "\\usr\\bin\\ntoarm-gdb.exe --interpreter=mi2"; - m_libPaths[0] = ndkTargetPath + "\\armle-v7\\lib"; - m_libPaths[1] = ndkTargetPath + "\\armle-v7\\usr\\lib"; - } - - // Escape backslashes for strings that will be sent to GDB - String^ pattern = "\\\\"; // one backslash - String^ replacement = "\\\\\\\\"; // two backslashes - Regex^ r = gcnew Regex(pattern); - - String^ regexResult; - for (int i = 0; i < NUM_LIB_PATHS; i++) { - regexResult = r->Replace(m_libPaths[i], replacement); - m_libPaths[i] = regexResult; - } -} - - -/// -/// Run BlackBerryConnect to stablish a connection with the device/simulator. -/// -/// Device/Simulator IP. -/// NDK full path. -/// Public key full path. -/// Device/simulator password. -void GDBParser::BlackBerryConnect(String^ IPAddrStr, String^ toolsPath, String^ publicKeyPath, String^ password) -{ - CAutoPtr apDevice = convertToAutoPtrFromString(IPAddrStr); - CAutoPtr apTools = convertToAutoPtrFromString(toolsPath); - CAutoPtr apKey = convertToAutoPtrFromString(publicKeyPath); - - CAutoPtr apPass; - if (!String::IsNullOrEmpty(password)) - apPass = convertToAutoPtrFromString(password); - - LPCTSTR lpApplicationName = NULL; - PROCESS_INFORMATION pi; - STARTUPINFOA si; - DWORD flags = 0; - - memset(&pi, 0, sizeof(pi)); - - // Set up the start up info struct. - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); -#if !defined (SHOW_BB_CONNECT_WINDOW) - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; -#endif - - char args[256]; - if (!String::IsNullOrEmpty(password)) - sprintf(args, "java.exe -Xmx512M -jar \"%s\\..\\lib\\Connect.jar\" %s -password %s -sshPublicKey \"%s\"", apTools, apDevice, apPass, apKey); - else - sprintf(args, "java.exe -Xmx512M -jar \"%s\\..\\lib\\Connect.jar\" %s -sshPublicKey \"%s\"", apTools, apDevice, apKey); - - // Launch the process - if (!CreateProcessA(NULL, args, NULL, NULL, TRUE, - flags, NULL, NULL, &si, &pi)) - ErrorExit(_T("CreateProcess: BlackBerry-Connect")); - - m_BBConnectProcess = pi.hProcess; -} - - -/// -/// Execute GDB only to get the list of running processes in the Device/Simulator -/// -/// Device/Simulator IP. -/// Device/simulator password. -/// TRUE when using the Simulator, FALSE when using the Device. -/// NDK full path. -/// Public key full path. -/// How many seconds to wait for connecting to the device. -/// A string with the list of running processes. -String^ GDBParser::GetPIDsThroughGDB(String^ IP, String^ password, bool isSimulator, String^ toolsPath, String^ publicKeyPath, int timeout) -{ - string response; - string parsed; - m_BBConnectProcess = NULL; - char pcCmd[256]; - - // Run BlackBerryConnect - BlackBerryConnect(IP, toolsPath, publicKeyPath, password); - - // Get device (IP address) - CAutoPtr ip = convertToAutoPtrFromString(IP); - - // Set NDK Variables - setNDKVars(isSimulator); - - // Convert GDB command to wchar_t* since GDBWrapper.exe requires a Unicode argument - pin_ptr pkwcGDBCmd = PtrToStringChars(m_pcGDBCmd); - const size_t newsizew = (wcslen(pkwcGDBCmd) + 1) * sizeof(wchar_t); - wchar_t* pwcGDBCmd = new wchar_t[newsizew]; - wcscpy_s(pwcGDBCmd, newsizew, pkwcGDBCmd); - CAutoPtr apGDBCmd; - apGDBCmd.Attach(pwcGDBCmd); - - // Get GDB Console - GDBConsole::setGDBPath(apGDBCmd); - GDBConsole* console = GDBConsole::getInstance(); - - // Convert library paths - CAutoPtr libPaths[NUM_LIB_PATHS]; - for (int i = 0; i < NUM_LIB_PATHS; i++) { - libPaths[i] = convertToAutoPtrFromString(m_libPaths[i]); - } - - /// Send intialization commands to GDB - response = console->waitForPrompt(true); - if ((response == "") || (response[0] == '!')) //found an error - { - // ??? load output console window with the parsed message. - response = ""; - } - - if (response != "") - { -// sprintf(pcCmd, "set debug nto-debug 2\r\n"); -// console->sendCommand(pcCmd); -// response = console->waitForPrompt(true); - - sprintf(pcCmd, "1-target-select qnx %s:8000\r\n", ip); - console->sendCommand(pcCmd); - response = console->waitForPromptWithTimeout(timeout); - if ((response == "") || (response[0] == '!')) //found an error - { - // ??? load output console window with the parsed message. - response = ""; - } - - if ((response != "") && (response != "TIMEOUT!") && (response.find("1^error,msg=",0) == -1)) //there is no error from previous response - { - sprintf(pcCmd, "info pidlist\r\n"); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - if ((response == "") || (response[0] == '!')) //found an error - { - // ??? load output console window with the parsed message. - response = ""; - } - } - } - exitGDB(); - String ^systemString = gcnew String(response.c_str()); - return systemString; -} - - -/// -/// Launch the GDB Debug Process. -/// -/// ID of the running process to be debugged. -/// Full path of the executable file. -/// Device/Simulator IP. -/// TRUE when using the Simulator, FALSE when using the Device. -/// NDK full path. -/// Public key full path. -/// Device/simulator password. -/// True -> succeeded; -/// False -> failed. -bool GDBParser::LaunchProcess(String^ pidStr, String^ exeStr, String^ IPAddrStr, bool isSimulator, String^ toolsPath, String^ publicKeyPath, String^ password) -{ - string response; - string parsed; - s_running = true; - m_BBConnectProcess = NULL; - char pcCmd[256]; - - // Run BlackBerryConnect - BlackBerryConnect(IPAddrStr, toolsPath, publicKeyPath, password); - - // Get PID - CAutoPtr apPid = convertToAutoPtrFromString(pidStr); - long int pid = strtol(apPid, NULL, 10); - if (pid == 0) { - return false; - } - - // Get device (IP address) - CAutoPtr apDevice = convertToAutoPtrFromString(IPAddrStr); - - // Get binary file path - CAutoPtr apBinaryFile; - if (exeStr == "CannotAttachToRunningProcess") - apBinaryFile = convertToAutoPtrFromString(""); - else - apBinaryFile = convertToAutoPtrFromString(exeStr); - - // Set NDK Variables - setNDKVars(isSimulator); - - // Convert GDB command to wchar_t* since GDBWrapper.exe requires a Unicode argument - pin_ptr pkwcGDBCmd = PtrToStringChars(m_pcGDBCmd); - const size_t newsizew = (wcslen(pkwcGDBCmd) + 1) * sizeof(wchar_t); - wchar_t* pwcGDBCmd = new wchar_t[newsizew]; - wcscpy_s(pwcGDBCmd, newsizew, pkwcGDBCmd); - CAutoPtr apGDBCmd; - apGDBCmd.Attach(pwcGDBCmd); - - // Get GDB Console - GDBConsole::setGDBPath(apGDBCmd); - GDBConsole* console = GDBConsole::getInstance(); - - // Convert library paths - CAutoPtr libPaths[NUM_LIB_PATHS]; - for (int i = 0; i < NUM_LIB_PATHS; i++) { - libPaths[i] = convertToAutoPtrFromString(m_libPaths[i]); - } - - // initializing the parsing data structures, buffers and thread - HANDLE sendingThread; - unsigned threadID; - unordered_map commandCodesMap; - string parsingInstructions[NumberOfInstructions]; - - cleanBuffers(); - if(!insertingCommandCodes(&commandCodesMap, parsingInstructions)) - { - printf("Error initializing parsing data structures"); - return false; - } - - /// Send intialization commands to GDB - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[2]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - -// sprintf(pcCmd, "set debug nto-debug 2\r\n"); -// console->sendCommand(pcCmd); -// response = console->waitForPrompt(true); - - sprintf(pcCmd, "1-gdb-set breakpoint pending on\r\n"); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[8]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - - sprintf(pcCmd, "4-target-select qnx %s:8000\r\n", apDevice); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[3]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - - sprintf(pcCmd, "5-file-exec-and-symbols %s\r\n", apBinaryFile); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[7]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - - if (m_remotePath != "") - { - m_remotePath = m_remotePath + "\\lib;" + m_remotePath + "\\usr\\lib;" + m_remotePath + "\\usr\\lib\\qt4"; - CAutoPtr apPath = convertToAutoPtrFromString(m_remotePath); - sprintf(pcCmd, "6set solib-search-path %s\r\n", apPath ); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[8]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - } - - sprintf(pcCmd, "7-target-attach %d\r\n", pid); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[6]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - -// start thread responsible for reading InputBuffer and sending commands to GDB. -// Thread must start after initializing GDB with the previous instructions because: -// - this thread will start another one (listening GDB) that will start consuming GDB responses. So, the above waitForPrompt would -// never get a result and this method would freeze. -// - the previous commands don't use the GDB Buffer, so the results wouldn't be parsed correctly. - sendingThread = (HANDLE)_beginthreadex( NULL, 0, &sendingCommands2GDB, (void *)console, 0, &threadID); - - return true; -} - - - - -// From this point on it is implemented the interface that allows creating unit tests for gdb-connect functions. Don't use these methods -// for something else because they need some resources that are allocated correctly when launching GDB the right way, i.e., by using the -// above GDBParser::LaunchProcess method. To be able to run the unit tests, it is needed to create mock resources or call -// GDBParser::LaunchProcess method first, because it will allocate the needed resources and will start GDB. - - -/// -/// Get the associated instruction ID from the command that would be sent to GDB. -/// -/// Command that would be sent to GDB. -/// When the instruction code stored in "map" is negative, it means that the commands parameters should be saved to -/// be used by the listeningGDB thread. When that happens, update and return variable "param". -/// Returns the instruction code for the command that would be sent to GDB or -1 in case of an error. It can also return the -/// command parameters, as it was described above. -int GDBParserUnitTests::get_Instruction_Code(String^ command, [Runtime::InteropServices::Out] String^ %param) -{ - CAutoPtr apCmd = convertToAutoPtrFromString(command); - string c = apCmd; - string p = ""; - - unordered_map map; - string v[NumberOfInstructions]; - - // First create the hash table map. - bool result = insertingCommandCodes(&map, v); - - int code = -2; - - if (result == 1) - { - code = getInstructionCode(c, map, &p); - param = gcnew String(p.c_str()); - } - return code; -} - - -/// -/// Get the sequential ID of the supposed response. -/// -/// The supposed GDB response. -/// If the supposed response is synchronous, this ID corresponds to the sequential ID of the command that should be sent to GDB -/// that generated such supposed response. If the supposed response is asynchronous, there is no sequential ID, so it returns: -/// -3 - when it shows that a supposed breakpoint was modified; -/// -2 - for any other supposed asynchronous response -/// -1 - when the supposed response is not completed or in case of an error. -int GDBParserUnitTests::get_Seq_ID(String^ response) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - return getSeqID(r); -} - - -/// -/// Initialize the hash map data structure "map" in which each entry contains a GDB command that is currently recognized by -/// the parser with its respective instruction ID. It loads these information from Instructions.txt file, in where each line has the -/// following format: -/// {$}gdb-command:->:parsing-instruction; -/// It must have the $ sign in front of the GDB command when it is needed to store the command parameters to be used later by the -/// listeningGDB thread. This usually happens whenever the GDB response for a given command does not contains enough information, like -/// only "^done" for example, when the parser needs something else. The ":->:" separates the GDB command from the parsing Instruction. -/// -/// Array that contains all the data from the Hash map created by insertingCommandCodes() function, that are the GDB -/// commands recognized by the parser and their respectives instructions IDs. -/// A string array with all of the currently recognized parsing instructions. The index position -/// correponds to the instruction ID used in "map" for the respective GDB command. -/// 1 in case of sucess; 0 if there is an error when opening the Instructions.txt file. -bool GDBParserUnitTests::inserting_Command_Codes(array^ map, array^ parsingInstructions) -{ - unordered_map m; - string v[NumberOfInstructions]; - - bool result = insertingCommandCodes(&m, v); - - for (int i = 0; i < NumberOfInstructions; i++) - { - parsingInstructions[i] = gcnew String(v[i].c_str()); - } - - int i = 0; - for (unordered_map::iterator it = m.begin(); it != m.end(); ++it) - { - map[i,0] = gcnew String(it->first.c_str()); - map[i,1] = Convert::ToString(it->second); - i++; - } - - return result; -} - - -/// -/// Function used to call the parser that will parse a supposed GDB response according to the supposed parsing instruction, returning -/// this parsed response. This function is called when starting GDB (this one doesn't use the OutputBuffer because it returns the supposed -/// parsed response). -/// -/// Supposed GDB response. -/// Instruction used to parse the supposed GDB response. -/// Returns the parsed GDB response. -String^ GDBParserUnitTests::parse_GDB(String^ response, String^ parsingInstruction) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - string output = parseGDB(r, p); - String ^systemstring = gcnew String(output.c_str()); - return systemstring; -} - - -/// -/// Function used to call the parser that will parse a supposed GDB response according to the supposed parsing instruction, storing -/// the parsed response in the respective position in the Output Buffer. Must be used together with the functions that create and handle -/// the Output Buffer. DON'T CALL THIS METHOD PASSING A POSITION OF OUTPUT BUFFER THAT IS ALREADY FILLED! parseGDB(string, string, int) is -/// used in an environment that has a different thread consuming items from Output Buffer. In this initial unit tests environment only -/// the current thread is running, which means that, if you try to add data to a non-empty position, this method will be busy-waiting till -/// that entry is empty, causing, in this scenario, a DEADLOCK. -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Position in the Output Buffer in which the parsed response will be stored. -void GDBParserUnitTests::parse_GDB(String^ response, String^ parsingInstruction, int position) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - parseGDB(r, p, position); -} - - -/// -/// Reponsible for parsing a supposed GDB response. Depending on the parsing instruction, the parser can get the first occurrence -/// from the supposed GDB response or get all of them that satisfies this parsing instruction. -/// -/// Supposed GDB response. -/// Instruction used to parse the supposed GDB response. -/// Current character to be read in the supposed GDB response. -/// If the parsing instruction specifies that it has to get all occurences from the supposed GDB response, this -/// value must be true. -/// A variable stores a string parsed from the supposed GDB response and can be used as many times as needed to -/// created the parsed response. Up to 10 variables can be created for a given parsing instruction. -/// If the parsing instruction allows the parser to get all occurrences from the supposed GDB response, this -/// separator will be used at the end of each occurence. The default one is '#' but it can be specified in the parsing instruction. -/// Returns the parsed GDB response. -String^ GDBParserUnitTests::parse_GDB(String^ response, String^ parsingInstruction, int respBegin, bool repeat, array^ variables, String^ separator) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - CAutoPtr apSep = convertToAutoPtrFromString(separator); - string s = apSep; - - char v[10][128]; - for (int i = 0; i< 10; i++) - { - CAutoPtr apAux = convertToAutoPtrFromString(variables[i]); - string aux = apAux; - - if (aux.length() > 128) - aux[127] = '\0'; - strcpy(v[i], aux.c_str()); - } - - string output = parseGDB(&r, p, respBegin, repeat, v, s); - String ^systemstring = gcnew String(output.c_str()); - return systemstring; -} - - -/// -/// Find the position of the associated closing bracket/parenthesis. -/// -/// The associated opening character ("(", "{" or "["). -/// The associated closing character (")", "}" or "]"). -/// The string where the search will be made. -/// Start position in the parsingInstruction string. This position normally corresponds to the position of the opening -/// character, but it could be smaller than that (never bigger!). However, if it is smaller, it cannot have the same character between -/// the 'ini' position and the corresponding one for the opening one. If need to have another one, precede it by the character '\'. -/// Returns the position of the associated closing bracket/parenthesis. If it is not found, returns the length of the string. -int GDBParserUnitTests::find_Closing(char opening, char closing, String^ parsingInstruction, int ini) -{ - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - return findClosing(opening, closing, p, ini); -} - - -/// -/// Get the next position of a given character (token) in a string message (txt), starting from a given position (pos). -/// -/// Character to search for. -/// String message in which it will search for the given character. -/// Starting position in the string message. -/// An integer that corresponds to the next position of the character in the string. If the character is not found, returns -/// the length of the string. -int GDBParserUnitTests::get_Next_Char(char token, String^ txt, int pos) -{ - CAutoPtr apTxt = convertToAutoPtrFromString(txt); - string t = apTxt; - return getNextChar(token, t, pos); -} - - -/// -/// Get the position of a given string (txt) in the string "response", starting from a given position (begin). -/// -/// String response where the search will be performed. -/// String to search for in the response. -/// Starting position in the string response. -/// Search for that string "times" times. Ex: I want to find the third occurrence of word "qaqa" in the -/// response. -/// Direction: if true, search forwards; if not, search backwards -/// The kind of parsing instruction that called this method. '?', '@', or '~'. If searching forward and '?', the -/// function will return the next position after the found string. If not, will return the first position of the found string. -/// An integer that corresponds to the next position of the string txt in the response. -1 in case of an error. -int GDBParserUnitTests::search_Response(String^ response, String^ txt, int begin, int times, bool forward, char instruction) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apTxt = convertToAutoPtrFromString(txt); - string t = apTxt; - return searchResponse(r, t, begin, times, forward, instruction); -} - - -/// -/// Substitute the existing variables in the string "txt" by their values, stored in the "variables" array. Each variable name -/// has this format: $9$, where $ characters are used to identify the variable while the number corresponds to the variable ID, that also -/// corresponds to the array index. There is a special variable "$EOL$" that is substituted by "\r\n". -/// -/// String to search for variables. -/// Array with the variable values. -/// Returns the new modified string. -String^ GDBParserUnitTests::substitute_Variables(String^ txt, array^ variables) -{ - CAutoPtr apTxt = convertToAutoPtrFromString(txt); - string t = apTxt; - char v[10][128]; - for (int i = 0; i< 10; i++) - { - CAutoPtr apAux = convertToAutoPtrFromString(variables[i]); - string aux = apAux; - - if (aux.length() > 128) - aux[127] = '\0'; - strcpy(v[i], aux.c_str()); - } - string output = substituteVariables(t, v); - String ^systemstring = gcnew String(output.c_str()); - return systemstring; -} - - -/// -/// This method stores a command that should be sent to GDB. Input buffer is a circular one. -/// -/// Command that should be sent to GDB. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool GDBParserUnitTests::add_Into_Input_Buffer(String^ command) -{ - CAutoPtr apCmd = convertToAutoPtrFromString(command); - char GDBCommand[GDBCommandSize]; - strcpy(GDBCommand, apCmd); - return addIntoInputBuffer(GDBCommand); -} - - -/// -/// Gets the next command that would be sent to GDB. Input buffer is a circular one. -/// -/// Returns the next command that would be sent to GDB. -String^ GDBParserUnitTests::remove_From_Input_Buffer() -{ - char command[GDBCommandSize] = ""; - removeFromInputBuffer(command); - string basicstring(command); - return(gcnew String(basicstring.c_str())); -} - - -/// -/// Verify if Input buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -//bool GDBParserUnitTests::is_Input_Buffer_Empty() -//{ -// return isInputBufferEmpty(); -//} - - -/// -/// For every command that should be to GDB, the following parameters should be added into GDBBuffer. -/// -/// Sequential ID of the command that would be sent to GDB. It is used to identify, when evaluating supposed GDB -/// responses, which command generated that given response. This ID is also used to specify the location in which this entry will be -/// stored in this buffer. -/// Each command that should be sent to GDB has an associated instruction code, that corresponds to the -/// parsing instruction that will be used to parse the supposed GDB response. -/// Used to store the GDB command parameters, so they could be used during the parsing task. There are some GDB -/// commands, like -break-delete for example, that results in a simple "^done" GDB response. The parser can identify which command -/// caused that response but cannot know what was affected by it (considering the -break-delete command, the parser will know that some -/// breakpoint was successfully deleted but won't know which of them was deleted). Using "param" helps the parser letting it knows -/// which parameters were sent together with a given GDB command. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool GDBParserUnitTests::add_Into_GDB_Buffer(int seq_id, int instructionCode, String^ param) -{ - CAutoPtr apParam = convertToAutoPtrFromString(param); - string p = apParam; - return addIntoGDBBuffer(seq_id, instructionCode, p); -} - - -/// -/// This method is called to find the right parsing instruction for the supposed GDB response. -/// -/// Sequential ID of the GDB response. -/// Returns the parameters sent together with the GDB command that generated this response, if there are some. -/// Returns the instruction code associated to the sequential id (seq). -int GDBParserUnitTests::remove_From_GDB_Buffer(int seq, [Runtime::InteropServices::Out] String^ %param) -{ - string p = ""; - int code = removeFromGDBBuffer(seq, &p); - param = gcnew String(p.c_str()); - return code; -} - - -/// -/// Verify if GDB buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool GDBParserUnitTests::is_GDB_Buffer_Empty() -{ - return isGDBBufferEmpty(); -} - - -/// -/// Store the supposed parsed GDB response in the "seq_stamp" position of the Output buffer. -/// -/// Position in the Output buffer to store the supposed parsed GDB response. -/// Supposed parsed GDB response. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool GDBParserUnitTests::add_Into_Output_Buffer(int seq_stamp, String^ message) -{ - CAutoPtr apResp = convertToAutoPtrFromString(message); - char parsedMessage[GDBCommandSize]; - strcpy(parsedMessage, apResp); - return addIntoOutputBuffer(seq_stamp, parsedMessage); -} - - -/// -/// This method returns the next supposed parsed GDB response (output) for a supposed asynchronous GDB RESPONSE or a supposed non -/// synchronous GDB COMMAND. This managed part of Output buffer is circular. -/// -/// Returns the supposed parsed GDB response. -String^ GDBParserUnitTests::remove_From_Output_Buffer() -{ - char response[GDBCommandSize] = ""; - removeFromOutputBuffer(response); - string basicstring(response); - return(gcnew String(basicstring.c_str())); -} - - -/// -/// This method returns the supposed parsed GDB response (output) for a supposed synchronous GDB COMMAND (ID). Each entry in this part -/// of Output buffer was previously reserved for each GDB command. -/// -/// Returns the supposed parsed GDB response. -/// ID of the supposed GDB command. -String^ GDBParserUnitTests::remove_Sync_From_Output_Buffer(int ID) -{ - char response[GDBCommandSize] = ""; - removeSyncFromOutputBuffer(response, ID); - string basicstring(response); - return(gcnew String(basicstring.c_str())); -} - - -/// -/// Initialize / clean all the existing buffers: inputBuffer, GDBBuffer, outputBuffer. -/// -void GDBParserUnitTests::clean_Buffers() -{ - cleanBuffers(); -} diff --git a/src/GDBParser/GDBParserAPI.h b/src/GDBParser/GDBParserAPI.h deleted file mode 100644 index 87402c8b..00000000 --- a/src/GDBParser/GDBParserAPI.h +++ /dev/null @@ -1,83 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -#include - -#define NumberOfInstructions 48 -#define GDBCommandSize 256 - -using namespace std; - -BEGIN_NAMESPACE - -public ref class GDBParser abstract sealed -{ -public: - static String^ GetPIDsThroughGDB(String^, String^, bool, String^, String^, int); - static bool LaunchProcess(String^, String^, String^, bool, String^, String^, String^); - static void BlackBerryConnect(String^, String^, String^, String^); - - static String^ parseCommand(String^, int); - static String^ removeGDBResponse(); - static bool addGDBCommand(String^); - static bool is_Input_Buffer_Empty(); - static void exitGDB(); - - static bool s_running = false; - -private: - static void setNDKVars(bool); - - static DWORD s_mainThreadId; - static String^ m_pcGDBCmd; - static const int NUM_LIB_PATHS = 2; - static array^ m_libPaths = gcnew array(NUM_LIB_PATHS); - static HANDLE m_BBConnectProcess; - static String^ m_remotePath; -}; - -END_NAMESPACE - - -BEGIN_NAMESPACE - -public ref class GDBParserUnitTests abstract sealed -{ -public: - static int get_Instruction_Code(String^, [Runtime::InteropServices::Out] String^ %); - static int get_Seq_ID(String^); - static bool inserting_Command_Codes(array^, array^); - - static String^ parse_GDB(String^, String^); - static void parse_GDB(String^, String^, int); - static String^ parse_GDB(String^, String^, int, bool, array^, String^); - - static int find_Closing(char, char, String^, int); - static int get_Next_Char(char, String^, int); - static int search_Response(String^, String^, int, int, bool, char); - static String^ substitute_Variables(String^, array^); - - static bool add_Into_Input_Buffer(String^); - static String^ remove_From_Input_Buffer(); - static bool add_Into_GDB_Buffer(int, int, String^); - static int remove_From_GDB_Buffer(int, [Runtime::InteropServices::Out] String^ %); - static bool is_GDB_Buffer_Empty(); - static bool add_Into_Output_Buffer(int, String^); - static String^ remove_From_Output_Buffer(); - static String^ remove_Sync_From_Output_Buffer(int); - static void clean_Buffers(); -}; -END_NAMESPACE \ No newline at end of file diff --git a/src/GDBParser/Instructions.txt b/src/GDBParser/Instructions.txt deleted file mode 100644 index 44c015c2..00000000 --- a/src/GDBParser/Instructions.txt +++ /dev/null @@ -1,48 +0,0 @@ -asynchronous:->:??=thread-exited,id;{#51\;;??";@@";#$EOL$;};??thread-created,id;{#40\;;??";@@";#\;;??pid ;@@ ;#$EOL$;};0;??*running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};#$EOL$;};0;??*stopped;{??breakpoint-hit;{#27\;;??bkptno=";@@";#\;;??file=";@@";#\;;??line=";@@";}{??end-stepping-range;{#45;??file=";{#\;;@@";0;#\;;??line=";@@";};}{??function-finished;{#46;??file=;{#\;;??";@@";#\;;??line=";@@";};}{??exited-normally;{#42;}{??exit-code;{#43\;;??";@@";}{??signal-received;{??signal-meaning="Killed";{#47;}{??signal-meaning="Segmentation fault";{#54\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};}{??signal-meaning="Aborted";{#55\;;0;??signal-name=";@@";#\;;??signal-meaning=";@@";}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};}{??exited-signalled;{#55\;;0;??signal-name=";@@";#\;;??signal-meaning=";@@";}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};};};};};#\;;??thread-id=;{??";@@";};#$EOL$;};0;??=breakpoint-modified,bkpt=\{number=";{0;($EOR$;$1=?:($EOR$;$1=?:??(gdb);{0;#80\;";(??~";?:??^connected;{0;#80\;";(??~";?:??^done;{0;#80\;";(??~";?:??^done;#File uploaded!; --target-attach:->:??^done;{#state="stopped"\;processID=";0;??pid=";@@";#"\;thread-ID=";??thread-created,id=";@@";0;#"\;$EOL$80\;";(??~";?:??^done;#File and symbols loaded.; --gdb-set:->:??^done;{#done;}; -set:->:??^done;{#done;}; --exec-arguments:->:??^done;#Arguments loaded.; --exec-run:->:??^running;{0;#40\;;??thread-created,id=";@@";0;??pid=";#\;;@@";0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??=breakpoint-created;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{??^error;{#ERROR: ;??msg=";@@";#$EOL$;(??&";#80\;";?:??^done;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{#Function not found!;}; --break-watch:->:??^done;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{#Function not found!;}; -$-break-delete:->:??^done;{#25;@@$EOL$}; -$-break-disable:->:??^done;{#24;@@$EOL$}; -$-break-enable:->:??^done;{#23;@@$EOL$}; -$-break-after:->:??^done;{#26;@@$EOL$}; -$-break-condition:->:??^done;{#28;@@$EOL$}; --break-list:->:??^done;{(??number=";#21\;;@@";#\;;??enabled=";@@";#\;;??addr=";@@";#\;;??func=";@@";#\;;??file=";@@";#\;;??line=";@@";#\;;??times=";@@";):$EOL$;}; -kill:->:??^done;{#done;}; -generate-core-file:->:#NOT CREATED! -jump:->:#NOT CREATED! -handle:->:#NOT CREATED! -watch:->:#NOT CREATED! -interrupt:->:#NOT CREATED! -show:->:#NOT CREATED! --stack-info-depth:->:??^done,depth=";@@";$EOL$ --stack-list-frames:->:??^done;{(??level=;{??";@@";};~"\};#\;;??addr=;{??";@@";};#\;;??func=;{??";@@";};#\;;??file=;{??";@@";};#\;;??line=;{??";@@";};);}; --stack-select-frame:->:??^done;{#done;}; --stack-list-variables:->:??^done;{#70\;;(??name=;{??";@@";};~"\};#\;;??arg=;{??";@@";};#\;;??type=;{??";@@";};#\;;??value=;{??";@@";};);}{#ERROR;}; --var-create:->:??^done;{??numchild=";@@";}{#ERROR;}; --var-delete:->:??^done;{#DONE;}{#ERROR;}; --var-list-children:->:??^done;{#71\;;(??name=;{??";@@";};~"\};#\;;??numchild=;{??";@@";};#\;;??value=;{??";@@";};#\;;??type=;{??";@@";};);}{#ERROR;}; --data-evaluate-expression:->:??^done;{??=;#60\;;@@$EOL$;}{??^error;{??-data-evaluate-expression: Usage: -data-evaluate-expression expression;{#61\;Error in expression.;}{??A syntax error in expression, near `'.;{#61\;A syntax error at the end of the expression.;}{??=;#61\;;@@$EOL$;};};};}; -ptype:->:??type = ;{@@\\n";}{# ;}; -whatis:->:??type = ;{@@\\n";}{# ;}; --exec-interrupt:->:??^done;{??signal-received;{??signal-meaning="Killed";{#47;}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};#\;;??thread-id=;{??";@@";}; --target-detach:->:#NOT CREATED! --var-info-num-children:->:??numchild;{??";@@";}{#ERROR;}; -info:->:??Address;{??0x;?:??^done;{(??\{id=";@@";#\;;??state=;{??";@@";};#\;;~\};?:??^done;{#done;}; diff --git a/src/GDBParser/ProjInclude.h b/src/GDBParser/ProjInclude.h deleted file mode 100644 index 047d620a..00000000 --- a/src/GDBParser/ProjInclude.h +++ /dev/null @@ -1,33 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -using namespace System; -using namespace System::Diagnostics; -#include -#pragma warning(push) -#pragma warning(disable:4091) -#include -#pragma warning(pop) - -#define ASSERT(cond) _ASSERT(cond) -#ifdef DEBUG - #define VERIFY(statement) Debug::Assert((statement) != 0, #statement) -#else - #define VERIFY(statement) statement -#endif - -#include "ComponentException.h" -#include "WorkerUtil.h" diff --git a/src/GDBParser/WorkerThreadObject.h b/src/GDBParser/WorkerThreadObject.h deleted file mode 100644 index bd158897..00000000 --- a/src/GDBParser/WorkerThreadObject.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -BEGIN_NAMESPACE - -ref class WorkerThreadObject -{ -public: -#ifdef _DEBUG - const DWORD ThreadId; -#endif - - WorkerThreadObject() -#ifdef _DEBUG - : ThreadId(GetCurrentThreadId()) -#endif - { - } -}; - -END_NAMESPACE \ No newline at end of file diff --git a/src/GDBParser/WorkerUtil.h b/src/GDBParser/WorkerUtil.h deleted file mode 100644 index c070eed0..00000000 --- a/src/GDBParser/WorkerUtil.h +++ /dev/null @@ -1,186 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -BEGIN_NAMESPACE - -#include - -inline HRESULT HRFromWin32Error(LONG lError) -{ - HRESULT hr = HRESULT_FROM_WIN32(lError); - if (SUCCEEDED(hr)) - hr = E_FAIL; - return hr; -} - -inline HRESULT HRLastError() -{ - return HRFromWin32Error(GetLastError()); -} - -inline HRESULT HRWin32BoolCall(BOOL rc) -{ - if (!rc) - return HRLastError(); - return S_OK; -} - -inline HRESULT HRWin32ErrorCall(LONG lError) -{ - if (lError != ERROR_SUCCESS) - return HRFromWin32Error(lError); - return S_OK; -} - -inline void __declspec(noreturn) ThrowHR(HRESULT hr) -{ - throw gcnew ComponentException(hr); -} - -inline void __declspec(noreturn) ThrowLastError() -{ - HRESULT hr = HRLastError(); - - ThrowHR(hr); -} - -inline void Win32BoolCall(BOOL fCondition) -{ - if (!fCondition) - { - ThrowLastError(); - } -} - -inline void Win32ErrorCall(DWORD err) -{ - if (err != 0) - { - ThrowHR(HRESULT_FROM_WIN32(err)); - } -} - -inline HANDLE Win32HandleCall(HANDLE h) -{ - if (h == NULL || h == INVALID_HANDLE_VALUE) - { - ThrowLastError(); - } - - return h; -} - -inline int StringLength(String^ s) -{ - if (s == nullptr) - { - return 0; - } - - return s->Length; -} - -inline String^ GetProcessName(HANDLE hProcess) -{ - WCHAR szProcessNameBuff[MAX_PATH+1]; - DWORD nChars = GetModuleFileNameEx( - hProcess, // process - NULL, // Module handle - szProcessNameBuff, - _countof(szProcessNameBuff) - ); - - Win32BoolCall(nChars > 0 && nChars <= _countof(szProcessNameBuff)); - - return gcnew String(szProcessNameBuff); -} - -inline LPWSTR wcsdup(String^ source) -{ - pin_ptr pSource = PtrToStringChars( source ); - int cch = (( source->Length+1) * 2); - LPWSTR pDest = new wchar_t[cch]; - memcpy(pDest, pSource, cch * sizeof(wchar_t)); - - return pDest; -} - -inline String^ StringPrefixReplace(int oldPrefixLen, String^ newPrefix, String^ s) -{ - int lengthNeeded = s->Length + newPrefix->Length - oldPrefixLen; - Text::StringBuilder^ sb = gcnew Text::StringBuilder(lengthNeeded, lengthNeeded); - - sb->Append(newPrefix); - sb->Append(s, oldPrefixLen, s->Length-oldPrefixLen); - - return sb->ToString(); -} - -inline String^ StringPrefixReplace(String^ oldPrefix, String^ newPrefix, String^ s) -{ - return StringPrefixReplace(oldPrefix->Length, newPrefix, s); -} - -// Note: return value does not include a trailing slash -inline int FindCommonPathSuffixLength(String^ path1, String^ path2) -{ - const int len1 = path1->Length; - const int len2 = path2->Length; - - int commonSuffixLength = 0; - - // scan backwards until we find a character that is different - for (; true; commonSuffixLength++) - { - int index1 = len1 - commonSuffixLength - 1; - int index2 = len2 - commonSuffixLength - 1; - - if (index2 < 0 || index1 < 0) - break; - - wchar_t char1 = path1[index1]; - wchar_t char2 = path2[index2]; - - // first compare the characters exsactly (fast). - if (char1 == char2) - continue; - - // if they aren't exsactly the same, see if they are canonicialy the same - char1 = (char1 == '/') ? '\\' : System::Char::ToUpperInvariant(char1); - char2 = (char2 == '/') ? '\\' : System::Char::ToUpperInvariant(char2); - - if (char1 == char2) - continue; - - break; - } - - // scan forward until we find a slash - for (; commonSuffixLength > 0; commonSuffixLength--) - { - wchar_t char1 = path1[len1 - commonSuffixLength]; - - if (char1 == '\\' || char1 == '/') - { - commonSuffixLength--; - break; - } - } - - return commonSuffixLength; -} - -END_NAMESPACE \ No newline at end of file diff --git a/src/GDBParser/dllmain.cpp b/src/GDBParser/dllmain.cpp deleted file mode 100644 index 1e9eda05..00000000 --- a/src/GDBParser/dllmain.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -// dllmain.cpp : Defines the entry point for the DLL application. -#include "stdafx.h" -#include "resource.h" - -#pragma managed(off) - - -/// -/// Use the ATL Registrar to register the engine. -/// -class CGDBParserModule : public CAtlDllModuleT< CGDBParserModule > -{ - -}; - -CGDBParserModule _GDBParserModule; -HMODULE _hModThis; - - -/// -/// Adds entries to the system registry. -/// -/// HRESULT -STDAPI DllRegisterServer(void) -{ - // Get this binaries full-path - WCHAR wszThisFile[MAX_PATH + 1]; - GetModuleFileName(_hModThis, wszThisFile, MAX_PATH + 1); - - // Cut off the FileName. GDBPARSERPATH should point to GDBParserAPI - WCHAR wszPath[MAX_PATH + 1]; - WCHAR* wszFileName; - GetFullPathName(wszThisFile, MAX_PATH + 1, wszPath, &wszFileName); - *wszFileName = L'\0'; - - // Register the sample engine in the Visual Studio registry hive. See GDBParser.rgs for what is added. - _ATL_REGMAP_ENTRY rgMap[] = - { - {L"GDBPARSERPATH", wszPath}, - {NULL, NULL} - }; - - HRESULT hr = _GDBParserModule.UpdateRegistryFromResourceS(IDR_GDBPARSER, true, rgMap); - return hr; -} - - -/// -/// Removes entries from the system registry. -/// -/// HRESULT -STDAPI DllUnregisterServer(void) -{ - // Get this binaries full-path - WCHAR wszThisFile[MAX_PATH + 1]; - GetModuleFileName(_hModThis, wszThisFile, MAX_PATH + 1); - - // Cut off the FileName. GDBPARSERPATH should point to GDBParserAPI - WCHAR wszPath[MAX_PATH + 1]; - WCHAR* wszFileName; - GetFullPathName(wszThisFile, MAX_PATH + 1, wszPath, &wszFileName); - *wszFileName = L'\0'; - - // Register the sample engine in the Visual Studio registry hive. See GDBParser.rgs for what is added. - _ATL_REGMAP_ENTRY rgMap[] = - { - {L"GDBPARSERPATH", wszPath}, - {NULL, NULL} - }; - - HRESULT hr = _GDBParserModule.UpdateRegistryFromResourceS(IDR_GDBPARSER, false, rgMap); - return hr; -} - - -/// -/// -/// -/// -/// TRUE. -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - _hModThis = hModule; - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} - diff --git a/src/GDBParser/gdb-connect.cpp b/src/GDBParser/gdb-connect.cpp deleted file mode 100644 index 42bf25d6..00000000 --- a/src/GDBParser/gdb-connect.cpp +++ /dev/null @@ -1,1973 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -// gdb-connect.cpp : Defines the entry point for the console application. -// -// Based on code sample from http://support.microsoft.com/kb/190351 - -#include "stdafx.h" - -#include "gdb-connect.h" -#include -#include - -#include -#include -#include -#include -#include - -#include -#include < vcclr.h > - -using namespace std; -using namespace System; - - -/// -/// Used to send parameters for the listeningGDB thread (the one that is listening GDB responses). -/// -typedef struct ListeningThreadDataStruct -{ - GDBConsole *console; // Current instance of GDB debugger. - string *parsingInstructions; // Parsing instruction. -} ListeningThreadData; - - -/// -/// Used to send parameters for the parsing threads, when using multi-threaded parsing. -/// -typedef struct ParsingThreadDetailsStruct -{ - char* response; // GDB response. - char* parsingInstruction; // Parsing instruction. - int* seqStamp; // Output buffer index where the parsed response will be stored. -} ParsingThreadDetails; - - -/// -/// Used by sendingCommands2GDB thread to store data that listeningGDB thread will need while parsing the GDB response. -/// -typedef struct GDBBufferStruct -{ - int seqId; // The sequencial number (seqID) of the instruction that was sent to GDB. - int instructionCode; // The instruction ID. - string param; // Parameter sent by sendingCommands2GDB thread to the listeningGDB one. -} GDBBufferEntry; - - -/// -/// Mutex / Event objects -/// -HANDLE hInputBufferMutex; // Used to ensure that only one thread at a time will be manipulating the input buffer. -HANDLE hGDBBufferMutex; // Used to ensure that only one thread at a time will be manipulating the GDB (intermediate) buffer. -HANDLE hOutputBufferMutex; // Used to ensure that only one thread at a time will be manipulating the output buffer. -HANDLE inputEvent; // Used to avoid sendingCommands2GDB thread to be pooling while the input buffer is empty. -HANDLE asyncOutputEvent; // Used to avoid DebugEngine.EventDispatcher thread to be pooling while waiting for an asynchronous response from Output buffer - -extern HMODULE _hModThis; - - -/// -/// Output buffer. Each entry has a parsed GDB response. -/// -char outputBuffer[OutputBufferSize][ParsedMessageSize]; -int out_OutputBuffer = SyncInstructionsSize; // Remove element from this position (outputBuffer). Input depends on the - // seqStamp, i.e., ordered according to GDB responses. Positions 0 to 49 - // are reserved for synchronous commands. - - -/// -/// Input buffer (Circular). Each entry has a command to be sent to GDB. -/// -char inputBuffer[InputBufferSize][GDBCommandSize]; -int in_InputBuffer = 0; // Add element in this position (inputBuffer). -int out_InputBuffer = 0; // Remove element from this position (inputBuffer). - - -/// -/// An instance of GDB debugger. -/// -GDBConsole* GDBConsole::m_instance = NULL; -TCHAR* GDBConsole::m_pcGDBCmd = NULL; - - -/// -/// GDB buffer. Contains the GDBBufferEntries sent by sendingCommands2GDB therad to the listeningGDB one. -/// -struct GDBBufferMainStruct -{ - int quantity; // Contains the number of GDB entries currently filled. - GDBBufferEntry GDBBufferData[GDBBufferSize]; // See GDBBufferEntry definition above. -} GDBBuffer; - - -/// -/// Shared variable between SendingCommands2GDB and listeningGDB threads used to let the listeningGDB one know that it has -/// to terminate. SendingCommands2GDB thread sets this variable to true to terminate listeningGDB thread. -/// -bool exitGDB = false; - - -/// -/// Used to store the path to GDB output log, generated when GDB console is instantiated and needed in logPrint(). -/// -char path_log[_MAX_PATH]; - - -/// -/// Generic function to print to a log file. -/// -/// Message to be printed to a log file. -void GDBConsole::logPrint(char* buffer) { - if (LOG_GDB_RAW_IO) { - time_t tt = time(NULL); - struct tm tm; - char buf[32]; - - tm = *localtime(&tt); - - strftime(buf, 31, "%H:%M:%S", &tm); - - FILE* file = fopen((char *)path_log, "a"); - fprintf(file, "%s - %s", buf, buffer); - fclose(file); - } -} - - -/// -/// Constructor. -/// -GDBConsole::GDBConsole() : - m_hInputRead(NULL), m_hInputWrite(NULL), m_hOutputRead(NULL), - m_hOutputWrite(NULL), m_hErrorWrite(NULL), m_isClosed(FALSE), - m_hCleanupMutex(NULL) -{ - HANDLE hOutputReadTmp = NULL; - HANDLE hInputWriteTmp = NULL; - SECURITY_ATTRIBUTES sa; - - out_OutputBuffer = SyncInstructionsSize; - in_InputBuffer = 0; - out_InputBuffer = 0; - - m_hCleanupMutex = CreateMutex(NULL, FALSE, NULL); - - // Set up the security attributes struct used when creating the pipes. - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - // Create the child output pipe. - if (!CreatePipe(&hOutputReadTmp, &m_hOutputWrite, &sa, 0)) - DisplayError(_T("CreatePipe")); - - // Create a duplicate of the output write handle for the std error - // write handle. This is necessary in case the child application - // closes one of its std output handles. - if (!DuplicateHandle(GetCurrentProcess(), m_hOutputWrite, - GetCurrentProcess(), &m_hErrorWrite, 0, - TRUE, DUPLICATE_SAME_ACCESS)) - DisplayError(_T("DuplicateHandle")); - - // Create the child input pipe. - if (!CreatePipe(&m_hInputRead, &hInputWriteTmp, &sa, 0)) - DisplayError(_T("CreatePipe")); - - // Create new output read handle and the input write handles. Set - // the Properties to FALSE. Otherwise, the child inherits the - // properties and, as a result, non-closeable handles to the pipes are created. - if (!DuplicateHandle(GetCurrentProcess(), hOutputReadTmp, - GetCurrentProcess(), - &m_hOutputRead, // Address of new handle. - 0, FALSE, // Make it uninheritable. - DUPLICATE_SAME_ACCESS)) - DisplayError(_T("DuplicateHandle")); - - if (!DuplicateHandle(GetCurrentProcess(), hInputWriteTmp, - GetCurrentProcess(), - &m_hInputWrite, // Address of new handle. - 0, FALSE, // Make it uninheritable. - DUPLICATE_SAME_ACCESS)) - DisplayError(_T("DuplicateHandle")); - - // Close inheritable copies of the handles you do not want to be inherited. - if (!CloseHandle(hOutputReadTmp)) DisplayError(_T("CloseHandle")); - if (!CloseHandle(hInputWriteTmp)) DisplayError(_T("CloseHandle")); - - prepAndLaunchRedirectedChild(); - - // Close pipe handles (do not continue to modify the parent). - // You need to make sure that no handles to the write end of the - // output pipe are maintained in this process or else the pipe will - // not close when the child process exits and the ReadFile will hang. - if (!CloseHandle(m_hOutputWrite)) DisplayError(_T("CloseHandle")); - if (!CloseHandle(m_hInputRead )) DisplayError(_T("CloseHandle")); - if (!CloseHandle(m_hErrorWrite)) DisplayError(_T("CloseHandle")); - - String^ tempPath = Environment::GetEnvironmentVariable("APPDATA"); - tempPath += "\\BlackBerry\\gdb-output.log"; - pin_ptr path_buffer = PtrToStringChars(tempPath); - - int ret = wcstombs ( path_log, path_buffer, _MAX_PATH ); - - FILE* file = fopen(path_log, "w"); // Delete a possible existing file. - fclose(file); -} - - -/// -/// Get the current instance of GDB debugger, creating a new one if needed. -/// -/// Returns the current instance of GDB debugger. -GDBConsole* GDBConsole::getInstance() { - if (m_instance == NULL) { - // Initialize it. - m_instance = new GDBConsole; - } - return m_instance; -} - - -/// -/// Shut down GDB debugger. A command to exit GDB was already sent by GDBParser::exitGDB(): "-gdb-exit". However, still -/// needs to "clean up": Update variables and terminate GDBWrapper process. -/// -void GDBConsole::shutdown() { - if (m_instance != NULL) { - m_instance->cleanup(); - } -} - - -/// -/// Set m_pcGDBCmd variable with the path and command to initialize GDB/MI. It will be used to instantiate GDBConsole. -/// For example: C:/bbndk/host_10_0_10_536/win32/x86\usr\bin\ntoarm-gdb.exe --interpreter=mi2. -/// -/// String with full path and command to initialize GDB/MI. -void GDBConsole::setGDBPath(const TCHAR* pcGDBCmd) { - size_t numChars = _tcslen(pcGDBCmd) + 1; - - // The path length may have changed, so reallocate for this one. - if (m_pcGDBCmd) { - delete[] m_pcGDBCmd; - } - m_pcGDBCmd = new TCHAR[numChars * sizeof(TCHAR)]; - - _tcscpy_s(m_pcGDBCmd, numChars, pcGDBCmd); -} - - -/// -/// Check if GDB is closed. -/// -/// A boolean value: TRUE if GDB is closed; FALSE if not. -BOOL GDBConsole::isClosed() { - return m_isClosed; -} - - -/// -/// After exiting GDB, it is still needed to update some internal variables and terminate the GDBWrapper process. -/// -void GDBConsole::cleanup() { - WaitForSingleObject(m_hCleanupMutex, INFINITE); - // Check if cleanup required. - if (!m_isClosed) { - m_isClosed = TRUE; - - if (m_pcGDBCmd != NULL) { - delete[] m_pcGDBCmd; - m_pcGDBCmd = NULL; - } - - // Clean up and kill GDBWrapper process. - if (!SetEvent(m_eventTerminate)) { - // Force termination. - TerminateProcess(m_hProcess, 0); - } - - // Wait for process to terminate. - WaitForSingleObject(m_hProcess, INFINITE); - - if (!CloseHandle(m_hProcess)) DisplayError(_T("CloseHandle")); - - if (!CloseHandle(m_hOutputRead)) DisplayError(_T("CloseHandle")); - if (!CloseHandle(m_hInputWrite)) DisplayError(_T("CloseHandle")); - - m_instance = NULL; - } - ReleaseMutex(m_hCleanupMutex); -} - - -/// -/// Destructor. -/// -GDBConsole::~GDBConsole() { - cleanup(); -} - - -/// -/// Sets up STARTUPINFO structure and launches redirected child. -/// -void GDBConsole::prepAndLaunchRedirectedChild(void) -{ - HANDLE stdHandles[3]; - LPCTSTR lpApplicationName = NULL; - PROCESS_INFORMATION pi; - STARTUPINFO si; - DWORD flags = 0; - DWORD pid = GetCurrentProcessId(); - TCHAR eventCtrlCName[MAX_EVENT_NAME_LENGTH]; - TCHAR eventTerminateName[MAX_EVENT_NAME_LENGTH]; - - _stprintf(eventCtrlCName, _T("Ctrl-C-%i"), pid); - _stprintf(eventTerminateName, _T("Terminate-%i"), pid); - - // Create event for wrapper process to wait on for CTRL-C. - m_eventCtrlC = CreateEventW(NULL, FALSE, FALSE, eventCtrlCName); - - // Create event for wrapper process to wait on for termination. - m_eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName); - - // Set process information. - memset(&pi, 0, sizeof(pi)); - - // Set up the start up info struct. - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - si.hStdOutput = m_hOutputWrite; - si.hStdInput = m_hInputRead; - si.hStdError = m_hErrorWrite; - si.wShowWindow = SW_HIDE; - - flags = CREATE_NEW_CONSOLE; - - String^ StringFilePath = Environment::GetFolderPath(Environment::SpecialFolder::ProgramFilesX86) + "\\BlackBerry\\VSPlugin-NDK\\GDBWrapper.exe"; - pin_ptr FilePath = PtrToStringChars(StringFilePath); - - if (!m_pcGDBCmd) { - cleanup(); - ErrorExit(_T("m_pcGDBCmd is NULL")); - } - - /* CreateProcess can modify pCmdLine thus we allocate memory */ - size_t numChars = _tcslen(m_pcGDBCmd) + MAX_EVENT_NAME_LENGTH * 2 + 1; - TCHAR* pCmdLine = new TCHAR[numChars * sizeof(TCHAR)]; - - if (pCmdLine == 0) { - DisplayError(_T("prepAndLaunchRedirectedChild: failed to allocate memory for pCmdLine")); - } - - _stprintf(pCmdLine, _T("\"%s\" \"%s\" \"%s\" \"%s\""), FilePath, m_pcGDBCmd, eventCtrlCName, eventTerminateName); - - // Launch the process (create a new console). - if (!CreateProcess(NULL, /* executable name */ - pCmdLine, /* command line */ - NULL, /* process security attribute */ - NULL, /* thread security attribute */ - TRUE, /* inherits system handles */ - flags, /* normal attached process */ - NULL, /* environment block */ - NULL, /* change to the new current directory */ - &si, /* (in) startup information */ - &pi)) /* (out) process information */ - ErrorExit(_T("CreateProcess")); - - if(NULL != pCmdLine) { - delete[] pCmdLine; - pCmdLine = NULL; - } - - m_hProcess = pi.hProcess; - - // Close unneeded handles. - if (!CloseHandle(pi.hThread)) DisplayError(_T("CloseHandle")); -} - - -/// -/// Read the stdout of the GDB console process. -/// -/// Buffer to store output. -/// Size of buffer in bytes (leave space for the null char). -/// Returns the number of characters that was read. -/// One of these integer values: 0 - Error; 1 - Success; 2 - Read everything from buffer but the message was not written -/// completed, maybe because the message is bigger than the buffer, maybe because GDB didn't finish writing the message. Call it -/// again to keep reading. -int GDBConsole::readOutput(CHAR* lpBuffer, int bufSize, int* nCharsRead) -{ - DWORD nBytesRead; - - if (isClosed()) { - DisplayError(_T("readOutput: GDBConsole is closed")); - return 0; - } - - if (lpBuffer == NULL) { - DisplayError(_T("readOutput: null buffer pointer")); - return 0; - } - - if (bufSize < 1) { - DisplayError(_T("readOutput: needs bufSize > 1")); - return 0; - } - - if (!ReadFile(m_hOutputRead, lpBuffer, bufSize, - &nBytesRead, NULL) || !nBytesRead) - { - if (GetLastError() == ERROR_BROKEN_PIPE) { - // Pipe done - normal exit path. - cleanup(); - return 0; - } else { - ErrorExit(_T("ReadFile")); - } - } - - *nCharsRead = nBytesRead / sizeof(CHAR); - - const char* pLastChar = lpBuffer + nBytesRead; - pLastChar -= 2; - - logPrint((char*) lpBuffer); - - if (strcmp("\r\n", pLastChar)) { - // Didn't get end of line. - return 2; - } - - return 1; -} - - -/// -/// Send a GDB command to the stdin of the GDB console process. -/// -/// null-terminated string ending in \r\n -/// 0 - Error; 1 - Success -int GDBConsole::sendCommand(const CHAR* lpCmd) -{ - DWORD nBytesWrote; - int nCmdChars = strlen(lpCmd); - - if (isClosed()) { - DisplayError(_T("readOutput: GDBConsole is closed")); - return 0; - } - - // Input validation - if (nCmdChars < 2) { - DisplayError(_T("SendCommand: nCmdChars < 2")); - } else { - const char* pLastChar = strchr(lpCmd, '\0'); - pLastChar -= 2; - if (strcmp("\r\n", pLastChar)) { - DisplayError(_T("SendCommand: lpCmd doesn't end in \\r\\n")); - } - } - - if (!WriteFile(m_hInputWrite, lpCmd, nCmdChars * sizeof(CHAR), &nBytesWrote, NULL)) - { - if (GetLastError() == ERROR_NO_DATA) { - // Pipe was closed (normal exit path). - cleanup(); - return 0; - } else { - DisplayError(_T("WriteFile")); - return 0; - } - } else { - printf("Sending [%s] (%d chars)\n", lpCmd, nBytesWrote / sizeof(CHAR)); - } - - logPrint((char*) lpCmd); - - return 1; -} - - -/// -/// Get handle m_hOutputRead. -/// -/// Returns handle m_hOutputRead. -HANDLE GDBConsole::getStdOutHandle() { - return m_hOutputRead; -} - - -/// -/// Send a CtrlC event that will interrupt GDB execution. -/// -void GDBConsole::sendCtrlC() { - if (!SetEvent(m_eventCtrlC)) { - DisplayError(_T("SetEvent")); - } -} - - -/// -/// Check if there is more data to be read from GDB's stdout without removing it from the pipe's buffer. -/// -/// Instance of GDB debugger. -/// Returns TRUE (there is data to be read) or FALSE (there isn't). -BOOL GDBConsole::isMoreOutputAvailable () { - DWORD totalBytesAvail; - - if (!PeekNamedPipe(getStdOutHandle(), NULL, NULL, NULL, &totalBytesAvail, NULL)) { - TCHAR lpError[256]; - _tprintf(lpError, _T("isMoreOutputAvailable: %s"), GetLastError()); - DisplayError(lpError); - return false; - } - - return (totalBytesAvail > 0); -} - - -/// -/// Waits and returns the output received from GDB, with a timeout. In case it finishes because of a timeout while waiting for a -/// GDB response, be aware that this GDB response must be available in a later time and you must be able to handle it. -/// -/// Timeout. -/// Returns output received from GDB or "" if there is no GDB output. -string GDBConsole::waitForPromptWithTimeout(int seconds) { - char lpBuffer [1024]; - int nCharsRead = 0; - int rc = 0; - BOOL isPromptReady = FALSE; - const char* promptString = "(gdb) \r\n"; - const char* lpTmp; - clock_t start, current; - - start = clock(); - - string message = ""; - - do { - - current = clock(); - if ((message == "") && (((current - start) / CLOCKS_PER_SEC ) > seconds)) - { - message = "TIMEOUT!"; - break; - } - - memset(lpBuffer, 0, sizeof(lpBuffer)); - - if (isClosed()) { - break; - } - - if (isMoreOutputAvailable()) - { - rc = readOutput(lpBuffer, sizeof(lpBuffer) - 1, &nCharsRead); - if (rc) { - // Terminate the buffer. - - lpBuffer[nCharsRead] = '\0'; - - message += lpBuffer; - - if (nCharsRead >= strlen(promptString)) { - lpTmp = lpBuffer + nCharsRead - strlen(promptString); - if (!strcmp(lpTmp, promptString)) { - isPromptReady = TRUE; - } - } - } else { - DisplayError(_T("waitForPrompt: readOutput got error")); - message += "\n\nwaitForPrompt: readOutput got error\n\n"; - break; - } - } - } while (!isPromptReady && !isClosed()); - - return message; -} - - -/// -/// Returns the output received from GDB. -/// -/// If TRUE, this method waits for the entire GDB output, i.e., until the GDB prompt is ready. It is TRUE when -/// initializing GDB. If FALSE, that is the default behavior, returns the current GDB output or "" if there is no GDB output. -/// Returns output received from GDB or "" if there is no GDB output. -string GDBConsole::waitForPrompt(bool sync) { - char lpBuffer [1024]; - int nCharsRead = 0; - int rc = 0; - BOOL isPromptReady = FALSE; - const char* promptString = "(gdb) \r\n"; - const char* lpTmp; - - string message = ""; - - do { - memset(lpBuffer, 0, sizeof(lpBuffer)); - - if (isClosed()) { - break; - } - - if (isMoreOutputAvailable()) - { - rc = readOutput(lpBuffer, sizeof(lpBuffer) - 1, &nCharsRead); - if (rc) { - // Terminate the buffer. - - lpBuffer[nCharsRead] = '\0'; - - message += lpBuffer; - - if (nCharsRead >= strlen(promptString)) { - lpTmp = lpBuffer + nCharsRead - strlen(promptString); - if (!strcmp(lpTmp, promptString)) { - isPromptReady = TRUE; - } - } - } else { - DisplayError(_T("waitForPrompt: readOutput got error")); - message += "\n\nwaitForPrompt: readOutput got error\n\n"; - break; - } - } - else if (!sync) - break; - } while (!isPromptReady && !isClosed()); - - return message; -} - - -/// -/// Displays the error number and corresponding message. -/// -/// Error message. -void DisplayError(LPCTSTR pszAPI) -{ - LPVOID lpvMessageBuffer; - TCHAR szPrintBuffer[512]; - DWORD bufSize = 512 * sizeof(TCHAR); - DWORD nCharsWritten; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpvMessageBuffer, 0, NULL); - - StringCbPrintf(szPrintBuffer, bufSize, - _T("ERROR: API = %s.\n error code = %d.\n message = %s.\n"), - pszAPI, GetLastError(), (char *)lpvMessageBuffer); - - _tprintf(_T("%s\n"), szPrintBuffer); - - LocalFree(lpvMessageBuffer); - ExitProcess(GetLastError()); -} - - -/// -/// Retrieve the system error message for the last-error code. -/// -/// Error message. -void ErrorExit(LPTSTR lpszFunction) -{ - LPVOID lpMsgBuf; - LPVOID lpDisplayBuf; - DWORD dw = GetLastError(); - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL ); - - // Display the error message and exit the process. - - lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, - (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); - StringCchPrintf((LPTSTR)lpDisplayBuf, - LocalSize(lpDisplayBuf) / sizeof(TCHAR), - TEXT("%s failed with error %d: %s"), - lpszFunction, dw, lpMsgBuf); - MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); - - LocalFree(lpMsgBuf); - LocalFree(lpDisplayBuf); - ExitProcess(dw); -} - - -/// -/// Initialize / clean all the existing buffers: inputBuffer, GDBBuffer, outputBuffer. -/// -void cleanBuffers() -{ - for (int i = 0; i < InputBufferSize; i++) - { - strcpy(inputBuffer[i],""); - } - in_InputBuffer = 0; - out_InputBuffer = 0; - for (int i = 0; i < GDBBufferSize; i++) - { - GDBBuffer.GDBBufferData[i].seqId = -1; - GDBBuffer.GDBBufferData[i].param = ""; - } - GDBBuffer.quantity = 0; - for (int i = 0; i < OutputBufferSize; i++) - { - strcpy(outputBuffer[i], ""); - } - out_OutputBuffer = SyncInstructionsSize; -} - - -/// -/// Verify if GDB buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool isGDBBufferEmpty() -{ - bool empty = true; - WaitForSingleObject( hGDBBufferMutex, INFINITE ); - if (GDBBuffer.quantity == 0) - empty = true; - else - empty = false; - ReleaseMutex( hGDBBufferMutex); - return empty; -} - - -/// -/// For every command sent to GDB, the following parameters must be added into GDBBuffer. -/// -/// Sequential ID of the command sent to GDB. It is used to identify, when evaluating GDB responses, which command -/// generated a given response. This ID is also used to specify the location in which this entry will be stored in this buffer. -/// Each command sent to GDB has an associated instruction code, that corresponds to the parsing -/// instruction that will be used to parse the GDB response. -/// Used to store the GDB command parameters, so they could be used during the parsing task. There are some GDB -/// commands, like -break-delete for example, that results in a simple "^done" GDB response. The parser can identify which command -/// caused that response but cannot know what was affected by it (considering the -break-delete command, the parser will know that some -/// breakpoint was successfully deleted but won't know which of them was deleted). Using "param" helps the parser letting it knows -/// which parameters were sent together with a given GDB command. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool addIntoGDBBuffer(int seq_id, int instructionCode, string param) -{ - if (seq_id < 0) - return false; - bool got = false; - int pos = seq_id % GDBBufferSize; - WaitForSingleObject( hGDBBufferMutex, INFINITE ); - if (GDBBuffer.GDBBufferData[pos].seqId == -1) // -1 means that the [pos] entry is "empty" or "not used". - { - GDBBuffer.GDBBufferData[pos].seqId = seq_id; - GDBBuffer.GDBBufferData[pos].instructionCode = instructionCode; - GDBBuffer.GDBBufferData[pos].param = param; - GDBBuffer.quantity += 1; - got = true; - } - ReleaseMutex( hGDBBufferMutex); - return (got); -} - - -/// -/// This method is called to find the right parsing instruction for a given GDB response. -/// -/// Sequential ID of the GDB response. -/// Returns the parameters sent together with the GDB command that generated this response, if there are some. -/// Returns the instruction code associated to the sequential id (seq). -int removeFromGDBBuffer(int seq, string *param) -{ - int output = -1; - if (seq < 0) // Means that: the GDB response is asynchronous or the response is not completed yet (GDB is still writing it) - if (seq == -2) // Means the GDB response is asynchronous and is not related to a GDB command. - return 0; // 0 is the instruction code for asynchronous responses. - else if (seq == -3) // Means that a breakpoint was modified. It is one of the GDB asynchronous messages. - return 1; // 1 is the instruction code for modified breakpoints responses. - else - return seq; // GDB response is incomplete. - - if (seq >= SyncInstructionsSize) // Means it was not a synchronous COMMAND. This number starts with SyncInstructionsSize - // and is increased for each new non synchronous COMMAND that is sent to GDB. - seq = (seq % SyncInstructionsSize) + SyncInstructionsSize; // seq must stay between SyncInstructionsSize and the buffer size. - - WaitForSingleObject( hGDBBufferMutex, INFINITE ); - if (GDBBuffer.GDBBufferData[seq].seqId != -1) - { - output = GDBBuffer.GDBBufferData[seq].instructionCode; - *param = GDBBuffer.GDBBufferData[seq].param; - GDBBuffer.GDBBufferData[seq].seqId = -1; // Marking this entry as "empty" or "not used". - GDBBuffer.quantity -= 1; - } - ReleaseMutex( hGDBBufferMutex); - return output; -} - - -/// -/// Store the parsed GDB response in the "seq_stamp" position of the Output buffer. -/// -/// Position in the Output buffer to store the parsed GDB response. -/// Parsed GDB response. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool addIntoOutputBuffer(int seq_stamp, char *parsedMessage) -{ - if (seq_stamp < 0) - return false; - bool got = false; - int pos = seq_stamp % OutputBufferSize; - WaitForSingleObject( hOutputBufferMutex, INFINITE ); - if (strcmp(outputBuffer[pos], "") == 0) // "" means that the [pos] entry is "empty" or "not used". - { - strcpy(outputBuffer[pos], parsedMessage); - got = true; - if (pos >= SyncInstructionsSize) - SetEvent(asyncOutputEvent); // Wake up "removeFromOutputBuffer", if needed. - } - ReleaseMutex( hOutputBufferMutex); - return (got); -} - - -/// -/// This method is called to send back to the debug engine the next parsed GDB response (output) for an -/// asynchronous GDB RESPONSE or a non synchronous GDB COMMAND. This managed part of Output buffer is circular. -/// -/// Returns the parsed GDB response. -void removeFromOutputBuffer(char * output) -{ - WaitForSingleObject( hOutputBufferMutex, INFINITE ); - if (strcmp(outputBuffer[out_OutputBuffer], "") != 0) - { - strcpy(output, outputBuffer[out_OutputBuffer]); - strcpy(outputBuffer[out_OutputBuffer], ""); - out_OutputBuffer += 1; - if (out_OutputBuffer == OutputBufferSize) - out_OutputBuffer = SyncInstructionsSize; // Positions 0 to "SyncInstructionsSize - 1" are reserved for synchronous commands. - } - ReleaseMutex( hOutputBufferMutex); - if (strcmp(output, "") == 0) // Means that the asynchronous part of output buffer is empty. - WaitForSingleObject(asyncOutputEvent, WAIT_TIME); - if (strcmp(output, "$#@EMPTY@#$") == 0) // This string means that both GDB and the parser worked well and returned an empty string. - output = ""; -} - - -/// -/// This method is called to send back to the debug engine the expected parsed GDB response (output) for a given synchronous -/// GDB COMMAND (ID). Each entry in this part of Output buffer was previously reserved for each GDB command. There are some free entries -/// that can be used by other GDB commands in the future. -/// -/// Returns the parsed GDB response. -/// ID of the GDB command. -void removeSyncFromOutputBuffer(char * output, int ID) -{ - if ((ID < 0) || (ID >= SyncInstructionsSize)) - return; - WaitForSingleObject( hOutputBufferMutex, INFINITE ); - if (strcmp(outputBuffer[ID], "") != 0) - { - strcpy(output, outputBuffer[ID]); - strcpy(outputBuffer[ID], ""); - } - ReleaseMutex( hOutputBufferMutex); -} - - -/// -/// Verify if Input buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool isInputBufferEmpty() -{ - bool empty; - WaitForSingleObject( hInputBufferMutex, INFINITE ); - if (in_InputBuffer == out_InputBuffer) - empty = true; - else - empty = false; - ReleaseMutex( hInputBufferMutex); - return empty; -} - - -/// -/// This method is called by the debug engine to store each command that must be sent to GDB. Input buffer is a circular one. -/// -/// Command to be sent to GDB. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool addIntoInputBuffer(char GDBCommand[GDBCommandSize]) -{ - bool got = false; - bool fireEvent = false; - WaitForSingleObject( hInputBufferMutex, INFINITE ); - if (!((in_InputBuffer == (InputBufferSize - 1) && out_InputBuffer == 0) || ((in_InputBuffer + 1) == out_InputBuffer))) - { - if (in_InputBuffer == out_InputBuffer) - fireEvent = true; - strcpy(inputBuffer[in_InputBuffer], GDBCommand); - in_InputBuffer += 1; - if (in_InputBuffer == InputBufferSize) - in_InputBuffer = 0; - got = true; - } - if (fireEvent) - SetEvent(inputEvent); // Wake up "sendingCommands2GDB", if needed. - ReleaseMutex( hInputBufferMutex); - return (got); -} - - -/// -/// Used by sendingCommands2GDB thread to get the next command to be sent to GDB. Input buffer is a circular one. -/// -/// Returns the next command to be sent to GDB. -void removeFromInputBuffer(char * input) -{ - WaitForSingleObject( hInputBufferMutex, INFINITE ); - if (in_InputBuffer != out_InputBuffer) - { - strcpy(input, inputBuffer[out_InputBuffer]); - strcpy(inputBuffer[out_InputBuffer],""); - out_InputBuffer += 1; - if (out_InputBuffer == InputBufferSize) - out_InputBuffer = 0; - } - ReleaseMutex( hInputBufferMutex); -} - - -/// -/// Get the sequential ID of the response. -/// -/// The GDB response. -/// If the response is synchronous, this ID corresponds to the sequential ID of the command sent to GDB that generated such -/// response. If the response is asynchronous, there is no sequential ID in the response, so it returns: -/// -3 - when it shows that a breakpoint was modified; -/// -2 - for any other asynchronous response -/// -1 - when the response is not completed or in case of an error. -int getSeqID(string response) -{ - int end; - int begin; - char seqIDstr[11] = ""; - int seqID = -1; - - end = response.find("^done", 0); - if (end == -1) - { - end = response.find("^running", 0); - if (end == -1) - { - end = response.find("^error", 0); - if (end == -1) - { - end = response.find("^connected", 0); - if (end == -1) - { - end = response.find("*running", 0); - if (end != -1) - return -2; // Means the GDB response is asynchronous. - else - { - end = response.find("*stopped", 0); - if (end != -1) - { - return -2; // Means the GDB response is asynchronous. - } - else - { - if (response.substr(0, 20) == "=breakpoint-modified") - { - return -3; // Means that a breakpoint was modified. - } - else - { - return -1; // Error / message incomplete. - } - } - } - } - } - } - } - if (end < 15) // SeqID is the first data in the string - begin = 0; - else - { - begin = end - 1; - while ((response[begin] != '"') && (response[begin] != '}')) - begin--; - begin++; - } - response.copy(seqIDstr, end - begin, begin); - seqID = atoi(seqIDstr); - return(seqID); -} - - -/// -/// Get the next position of a given character (token) in a string message (txt), starting from a given position (pos). -/// -/// Character to search for. -/// String message in which it will search for the given character. -/// Starting position in the string message. -/// An integer that corresponds to the next position of the character in the string. If the character is not found, returns -/// the length of the string. -int getNextChar(char token, string txt, int pos) -{ - int end = pos; - int slash, aux; - do - { - slash = 0; - end = txt.find(token, pos); - if (end == -1) - end = txt.length(); - aux = end - 1; - while ((aux >= 0) && (txt[aux] == '\\')) - { - slash++; - aux--; - } - pos = end + 1; - } while ((slash % 2) != 0); - return end; -} - - -/// -/// Get the position of a given string (txt) in the string GDB response (response), starting from a given position (begin). -/// -/// GDB string response where the search will be performed. -/// String to search for in the GDB response. -/// Starting position in the GDB string response. -/// Search for that string "times" times. Ex: I want to find the third occurrence of word "qaqa" in the GDB -/// response. -/// Direction: if true, search forwards; if not, search backwards. Only '?' instruction can search backwards. -/// The kind of parsing instruction that called this method. '?', '@', or '~'. Only '?' instruction can -/// search backwards. -/// An integer that corresponds to the next position of the string in the GDB response. -1 in case of an error. -int searchResponse(string response, string txt, int begin, int times, bool forward, char instruction) -{ - for (; times > 0; times--) - { - if ((begin >= response.length()) || (begin == -1)) - break; - if (forward) - { - if (begin == 0) - { - if ((txt[0] == '\r') && (txt[1] == '\n')) - { - string check = txt.substr(2, txt.length() - 2); - if (response.substr(0, check.length()) == check) - continue; - } - } - begin = response.find(txt, begin); - if ((begin != -1) && ((times != 1) || (instruction == '?'))) - begin += txt.length(); - } - else - { - begin = response.rfind(txt, begin); - if (begin != -1) - { - if (times == 1) - begin += txt.length(); - else - begin--; - } - if ((begin == -1) && ((txt[0] == '\r') && (txt[1] == '\n'))) - begin = 2; // 2 is the size of "\r\n". - } - } - if (times == 0) - return begin; - return -1; -} - - -/// -/// Substitute the existing variables in the string "txt" by their values, stored in the "variables" array. Each variable name -/// has this format: $9$, where $ characters are used to identify the variable while the number corresponds to the variable ID, that also -/// corresponds to the array index. There is a special variable "$EOL$" that is substituted by "\r\n". -/// -/// String to search for variables. -/// Array with the variable values. -/// Returns the new modified string. -string substituteVariables(string txt, char variables[10][128]) -{ - do - { - int aux = getNextChar('$', txt, 0); - if (aux < txt.length()) - { - aux++; - int aux2 = getNextChar('$', txt, aux); - string index = txt.substr(aux, aux2 - aux); - if (index == "EOL") - { - txt = txt.substr(0, aux - 1) + '\r' + '\n' + txt.substr(aux2 + 1, txt.length()); - } - else - txt = txt.substr(0, aux - 1) + variables[atoi(index.c_str())] + txt.substr(aux2 + 1, txt.length()); - } - else - break; - } while (true); - return txt; -} - - -/// -/// Find the position of the associated closing bracket/parenthesis. -/// -/// The associated opening character ("(", "{" or "["). -/// The associated closing character (")", "}" or "]"). -/// The string where the search will be made. -/// Start position in the parsingInstruction string. This position normally corresponds to the position of the opening -/// character, but it could be smaller than that (never bigger!). However, if it is smaller, it cannot have the same character between -/// the 'ini' position and the corresponding one for the opening one. If need to have another one, precede it by the character '\'. -/// Returns the position of the associated closing bracket/parenthesis. If it is not found, returns the length of the string. -int findClosing(char opening, char closing, string parsingInstruction, int ini) -{ - int end = getNextChar(closing, parsingInstruction, ini); - int other = ini; - bool found = true; - do - { - other = getNextChar(opening, parsingInstruction, other + 1); - if (other < end) - { - end = getNextChar(closing, parsingInstruction, end + 1); - } - else - found = false; - } while (found); - return end; -} - - -/// -/// Reponsible for parsing each GDB response. Depending on the parsing instruction, the parser can get the first occurrence -/// from GDB response or get all of them that satisfies this parsing instruction. -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Current character to be read in GDB response. -/// If the parsing instruction specifies that it has to get all occurences from a GDB response, this value must -/// be true. -/// A variable stores a string parsed from GDB response and can be used as many times as needed to create the -/// parsed response. Up to 10 variables can be created for a given parsing instruction. -/// If the parsing instruction allows the parser to get all occurrences from GDB response, this separator will -/// be used at the end of each occurence. The default one is '#' but it can be specified in the parsing instruction. -/// Returns the parsed GDB response. -string parseGDB(string *response, string parsingInstruction, int respBegin, bool repeat, char variables[10][128], string separator) -{ - string result = ""; // This variable will be the parsed GDB response. - string originalParsingInstruction = parsingInstruction; // Backup of parsing instruction. - int parsePos = 0; // Current character to be read in parsing instruction. - int home = respBegin; // Save the current position in GDB response. - int respEnd = 0; - int limit = (*response).length(); - bool found = false; - - bool removeSelection = false; - int removeFromHere = -2; // -2 - not set; -1 - indicates that it will be set in the first '?' instruction; >=0 - already set. - - if (separator == "$EOL$") - separator = "\r\n"; - - while ((parsePos < parsingInstruction.length()) || repeat) - { - if ((repeat) && (parsePos >= parsingInstruction.length())) // repeat instructions till the end of the response - { - if (found) - { - if (result != "") - result += separator; - parsePos = 0; - parsingInstruction = originalParsingInstruction; - limit = (*response).length(); - found = false; - } - else - repeat = false; - continue; - } - - if (parsingInstruction[parsePos] == '(') // repeat instructions till the end of the response - { - int end = parsePos; - string repeatInstruction; - - end = findClosing('(', ')', parsingInstruction, parsePos); - - repeatInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)); - - end++; - if (parsingInstruction[end] == ':') - { - parsePos = end + 1; - end = getNextChar(';', parsingInstruction, parsePos); - separator = parsingInstruction.substr(parsePos, end - parsePos); - int aux = separator.find("\\;"); - if (aux != -1) - separator.erase(aux,1); - } - parsePos = end + 1; - - result += parseGDB(response, repeatInstruction, respBegin, true, variables, separator); - - continue; - } - - if (parsingInstruction[parsePos] == '?') // search and set the beginning of the searched string. - { - int times = 1; - bool forward = true; - int end; - int aux; - string txt; - - parsePos++; - if (parsingInstruction[parsePos] == '%') // consider this position to extract and use the data and them remove this - // one from the GDB response string. - { - removeFromHere = -1; - parsePos++; - } - - if (parsingInstruction[parsePos] == '<') // means to search backwards. - { - forward = false; - parsePos++; - } - - if (parsingInstruction[parsePos] != '?') // the number of times to search for a given string. - { - end = getNextChar('?', parsingInstruction, parsePos); - times = atoi(parsingInstruction.substr(parsePos, end - parsePos).c_str()); - parsePos = end; - } - parsePos++; - - end = getNextChar(';', parsingInstruction, parsePos); - - txt = substituteVariables(parsingInstruction.substr(parsePos, end - parsePos), variables); - - aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - int previousRespBegin = respBegin; - respBegin = searchResponse(*response, txt, respBegin, times, forward, '?'); - -// check if it was defined a set of instructions to be executed if the search is NOT valid, i.e., there is a '{' after the ';'. -// If the search is not valid, go to the '}' and keep going. If there is no '{}' and the search is not valid, just end evaluating -// these instructions. Normally, there is '{}' to allow handling gdb errors. - if (parsingInstruction[end + 1] == '{') - { - parsePos = end + 1; - - end = findClosing('{', '}', parsingInstruction, parsePos); - - if ((respBegin != -1) && (respBegin <= limit)) - { - found = true; - // the following instructions to be evaluated are between '{' and '}'. - if (((end + 1) < parsingInstruction.length()) && (parsingInstruction[end+1] != '{')) - { - parsingInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.substr(end + 2, parsingInstruction.length()); - } - else - { - // if there is '{' after a '}', it means that there is an 'else' sentence. - int else_end; - else_end = findClosing('{', '}', parsingInstruction, end + 1); - parsingInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.substr(else_end + 2, parsingInstruction.length()); - } - - parsePos = 0; - if (removeFromHere == -1) - removeFromHere = respBegin - txt.length(); - } - else - { - respBegin = previousRespBegin; - removeFromHere = -2; - if (((end + 1) < parsingInstruction.length()) && (parsingInstruction[end+1] != '{')) - { - parsePos = end + 2; // move it to the next instruction, after the "};" - } - else - { - parsePos = end + 1; - end = findClosing('{', '}', parsingInstruction, parsePos); - parsingInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.substr(end + 2, parsingInstruction.length()); - parsePos = 0; - } - } - } - else - { - if ((respBegin == -1) || (respBegin > limit)) - { - if (respBegin > limit) - respBegin = previousRespBegin; - - parsePos = parsingInstruction.length(); - removeFromHere = -2; - removeSelection = false; - } - else - { - found = true; - parsePos = end + 1; - if (removeFromHere == -1) - removeFromHere = respBegin - txt.length(); - } - } - - continue; - } - - if (parsingInstruction[parsePos] == '@') // till here: search and set the end of the searched string. Return the string - // between the last ? and this "till here" position - { - int times = 1; - int end; - string txt; - int aux; - - parsePos++; - - if (parsingInstruction[parsePos] != '@') // get the number of times to search for a given string. - { - end = getNextChar('@', parsingInstruction, parsePos); - times = atoi(parsingInstruction.substr(parsePos, end - parsePos).c_str()); - parsePos = end; - } - parsePos++; - - end = getNextChar(';', parsingInstruction, parsePos); - - txt = substituteVariables(parsingInstruction.substr(parsePos, end - parsePos), variables); - - aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - respEnd = searchResponse(*response, txt, respBegin, times, true, '@'); - if ((respEnd == -1) || (respEnd > limit)) - { - result = ""; - break; - } - if (!removeSelection) - result += (*response).substr(respBegin, respEnd - respBegin); - - respBegin = respEnd; - - if (removeFromHere >= 0) - { - (*response).erase(removeFromHere, respEnd + txt.length() - removeFromHere); - respBegin = removeFromHere; - removeFromHere = -2; - removeSelection = false; - } - - parsePos = end + 1; - continue; - } - - if (parsingInstruction[parsePos] == '#') // insert the following string into the result - { - int end = getNextChar(';', parsingInstruction, parsePos); - parsePos++; - - string txt = parsingInstruction.substr(parsePos, end - parsePos); - int aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - result += substituteVariables(txt, variables); - - parsePos = end + 1; - continue; - } - - if (parsingInstruction[parsePos] == '~') // specify a limit, so the search instructions will search till this position. - { - int end = getNextChar(';', parsingInstruction, parsePos); - parsePos++; - - string txt = parsingInstruction.substr(parsePos, end - parsePos); - int aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - limit = searchResponse(*response, txt, respBegin, 1, true, '~'); - if (limit == -1) - { - limit = (*response).length(); - } - - parsePos = end + 1; - continue; - } - - if (parsingInstruction[parsePos] == '0') // set the response cursor position to home_pos (normally 0, but '(' can set a different - // value for home_pos) - { - respBegin = home; - parsePos += 2; // jump the '0' and ';' characters - continue; - } - - if (parsingInstruction[parsePos] == '%') // delete the string (between ? and @) from response - { - removeSelection = true; - removeFromHere = -1; - parsePos++; - continue; - } - - if (parsingInstruction[parsePos] == '$') // create a variable to store a value from response string. This value is defined by - // the instructions between the '=' and the @ symbol (till here) - { - int end, varNumber, aux; - - parsePos++; - end = getNextChar('=', parsingInstruction, parsePos); - aux = getNextChar('$', parsingInstruction, parsePos); - if ((aux > 0) && (aux < end)) - end = parsingInstruction.length(); - if (end < parsingInstruction.length()) // variable assignment - { - varNumber = atoi(parsingInstruction.substr(parsePos, end - parsePos).c_str()); - - parsePos = end + 1; - end = parsingInstruction.find("$$", parsePos); - string r = parseGDB(response, parsingInstruction.substr(parsePos, end - parsePos), respBegin, false, variables, "#"); - if (r == "") - break; - strcpy(variables[varNumber], r.c_str()); - - parsePos = end + 3; // jump $$; - } - else // pre-defined variable: Finish the parsing task or move to the end of the GDB response. - { - end = parsingInstruction.find('$', parsePos); - if (parsingInstruction.substr(parsePos, end - parsePos) == "END") - break; - if (parsingInstruction.substr(parsePos, end - parsePos) == "EOR") // move respBegin to the end of the response, probably - // to start looking from the end to the begin. - respBegin = response->length() - 1; - parsePos = end + 2; - } - continue; - } - - } - return(result); -} - - -/// -/// Function used to call the parser that will parse a GDB response according to the parsing instruction, returning this parsed -/// response. Call this function when starting GDB (this one doesn't use the OutputBuffer because it returns the parsed response). -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Returns the parsed GDB response. -string parseGDB(string response, string parsingInstruction) -{ - char variables[10][128]; - char result[ParsedMessageSize] = ""; - - strcpy(result, parseGDB(&response, parsingInstruction, 0, false, variables, "#").substr(0, ParsedMessageSize - 1).c_str()); - - return (result); -} - - -/// -/// Function used to call the parser that will parse a GDB response according to the parsing instruction, storing the parsed -/// response in the Output Buffer. Call this function if NOT USING multithreaded parsing -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Position in the Output Buffer in which the parsed response will be stored. -void parseGDB(string response, string parsingInstruction, int seqStamp) -{ - char variables[10][128]; - char result[ParsedMessageSize] = ""; - - strcpy(result, parseGDB(&response, parsingInstruction, 0, false, variables, "#").substr(0, ParsedMessageSize - 1).c_str()); - - if (strcmp(result,"") == 0) - { - // TODO? Unexpected response. Must handle it. - strcpy(result, "$#@EMPTY@#$"); // Sending this string to be sure that the parser worked well and returned an empty string. - } - - while (!addIntoOutputBuffer(seqStamp, result)) - Sleep(0); -} - - -/// -/// Thread used to call the parser that will parse a GDB response according to the parsing instruction, storing the parsed -/// response in the Output Buffer. Call this function if USING multithreaded parsing. One thread per each GDB response. -/// -/// A ParsingThreadDetails data structure that stores the following data: -/// - response (GDB response); -/// - parsingInstruction (Parsing instruction); and -/// - seqStamp (Output buffer index where the parsed response will be stored). -/// 0 -unsigned __stdcall parseGDBResponseThread(void *arg) -{ - ParsingThreadDetails *d = (ParsingThreadDetails *)arg; - string response = d->response; - string parsingInstruction = d->parsingInstruction; - int seqStamp = *(d->seqStamp); - - char result[ParsedMessageSize] = ""; - char variables[10][128]; - - strcpy(result, parseGDB(&response, parsingInstruction, 0, false, variables, "#").substr(0, ParsedMessageSize - 1).c_str()); - - if (strcmp(result,"") == 0) - { - // TODO? Unexpected response. Must handle it. - strcpy(result, "$#@EMPTY@#$"); // Sending this string to be sure that parsed worked well and returned an empty string. - } - - while (!addIntoOutputBuffer(seqStamp, result)) - Sleep(0); - - return 0; -} - - -/// -/// Thread responsible for listening for GDB outputs. Thread sendingCommands2GDB start this one, that stays alive till the -/// end of the debugging session. -/// -/// A ListeningThreadData data structure that stores the following data: -/// - console (Current instance of GDB debugger); and -/// - parsingInstructions (Parsing instruction). -/// 0 -unsigned __stdcall listeningGDB(void *arg) -{ - ListeningThreadData *listen = (ListeningThreadData *)arg; - - int seqStamp = SyncInstructionsSize; // Positions 0 to 49 are reserved for synchronous commands - - string response = ""; - int getMoreData = 10; // used when the GDB output does not have a complete response. - - while(!exitGDB) // exitGDB is set to true by sendingCommands2GDB thread, when the debugging sessiong ends. - { - int instructionCode; - int gdbPos; - - response += listen->console->waitForPrompt(false); - - gdbPos = response.find("(gdb)"); - - while (gdbPos == 0) - { - response.erase(0,5); - gdbPos = response.find("(gdb)"); - } - - if ((gdbPos == -1) && (response.length() > 3)) - gdbPos = response.length(); - - while (gdbPos != -1) // Just in case gdb was faster than our debugger. If that happens, there will be two or more responses - // in the buffer, so we have to parse each of them individually. - { - int asyncRunning = -1; - int asyncStopped = -1; - int seqId; - string param = ""; - string oneResponse; - - oneResponse = response.substr(0, gdbPos); - - asyncRunning = oneResponse.find("*running"); - asyncStopped = oneResponse.find("*stopped"); - if ((asyncRunning != -1) && (asyncStopped != -1)) - { - if (asyncRunning > asyncStopped) - gdbPos = asyncRunning; - else - gdbPos = asyncStopped; - oneResponse = oneResponse.substr(0, gdbPos); - } - - seqId = getSeqID(oneResponse); - instructionCode = removeFromGDBBuffer(seqId, ¶m); - - if (param != "") - { - oneResponse = oneResponse.erase(oneResponse.length() - 2, 2); - oneResponse = oneResponse + param + '\r' + '\n'; - } - - if (instructionCode == -1) - { - getMoreData -= 1; // get more data from buffer to try to identify the type of the response - if (getMoreData == 0) - instructionCode = 0; // it was not possible to identify the type of the response after reading buffer 10 times. - // Consider it an asynchronous one. - else - break; // don't erase the response... Trying to get more data. - } - - getMoreData = 10; - - if (instructionCode != -1) - { - // Create a thread to parse the response with parsingInstructions[instructionCode]. Send also a sequencial number, - // so VS can sort the results. Can use multiple parsing threads or not, depending on the const value MultipleThreads - // defined in gdb-connect.h - if (MultipleThreads) - { - HANDLE ParsingThread = new(HANDLE); - unsigned ParsingThreadID; - - ParsingThreadDetails *details = new(ParsingThreadDetails); - - details->parsingInstruction = new(char[listen->parsingInstructions[instructionCode].length()]); - strcpy(details->parsingInstruction, listen->parsingInstructions[instructionCode].c_str()); - details->response = new(char[oneResponse.length()]); - strcpy(details->response, oneResponse.c_str()); - details->seqStamp = new(int); - if ((seqId >= 0) && (seqId < SyncInstructionsSize)) - *(details->seqStamp) = seqId; - else - *(details->seqStamp) = seqStamp; - - ParsingThread = (HANDLE)_beginthreadex( NULL, 0, &parseGDBResponseThread, (void *)details, 0, &ParsingThreadID); - } - else // Without multiple parsing threads - { - if ((seqId >= 0) && (seqId < SyncInstructionsSize)) - parseGDB(oneResponse.c_str(), listen->parsingInstructions[instructionCode].c_str(), seqId); - else - parseGDB(oneResponse.c_str(), listen->parsingInstructions[instructionCode].c_str(), seqStamp); - } - - if ((seqId < 0) || (seqId >= SyncInstructionsSize)) - { - seqStamp++; - seqStamp = (seqStamp % SyncInstructionsSize) + SyncInstructionsSize; - } - } - if ((asyncRunning == -1) || (asyncStopped == -1)) - gdbPos += 5; - response.erase(0, gdbPos); - gdbPos = response.find("(gdb)"); - - if (gdbPos == -1) - if (response.length() > 3) - gdbPos = response.length(); - else - response = ""; - }; - } - - exitGDB = false; - - return 0; -} - - -/// -/// Get the associated instruction ID from the command to be sent to GDB. -/// -/// Command to be sent to GDB. -/// Hash map data structure that contains the GDB commands recognized by the parser and their respectives -/// instructions IDs. -/// When the instruction code stored in "map" is negative, it means that the commands parameters must be saved to -/// be used by the listeningGDB thread. When that happens, update and return variable "param". -/// Returns the instruction code for the command to be sent to GDB or -1 in case of an error. It can also return the command -/// parameters, as it was described above. -int getInstructionCode(string command, unordered_map map, string *param) -{ - int pos = command.find(" "); - if (pos != -1) - { - *param = command.substr(pos, (command.length() -pos)); - (*param)[0] = ';'; - int i = (*param).find(" "); - while (i != -1) - { - (*param)[i] = ';'; - i = (*param).find(" "); - } - command = command.substr(0, pos); - } - unordered_map::iterator it = map.find(command); - if (it != map.end()) - { - if (it->second > 0) - { - *param = ""; - return (it->second); - } - else - { - return ((it->second) * -1); - } - } - printf("Command code not found."); - return -1; -} - - -/// -/// Initialize the hash map data structure "map" in which each entry contains a GDB command that is currently recognized by -/// the parser with its respective instruction ID. It loads these information from Instructions.txt file, in where each line has the -/// following format: -/// {$}gdb-command:->:parsing-instruction; -/// It must have the $ sign in front of the GDB command when it is needed to store the command parameters to be used later by the -/// listeningGDB thread. This usually happens whenever the GDB response for a given command does not contains enough information, like -/// only "^done" for example, when the parser needs something else. The ":->:" separates the GDB command from the parsing Instruction. -/// -/// Hash map data structure that contains the GDB commands recognized by the parser and their respectives -/// instructions IDs. -/// A string array with all of the currently recognized parsing instructions. The index position -/// correponds to the instruction ID used in "map" for the respective GDB command. -/// 1 in case of sucess; 0 if there is an error when opening the Instructions.txt file. -bool insertingCommandCodes(unordered_map *map, string parsingInstructions[NumberOfInstructions]) -{ - String^ StringFilePath = Environment::GetFolderPath(Environment::SpecialFolder::ProgramFilesX86) + "\\BlackBerry\\VSPlugin-NDK\\Instructions.txt"; - pin_ptr FilePath = PtrToStringChars(StringFilePath); - - ifstream inputs; - inputs.open (FilePath); - - if (!inputs.is_open()) - { - cout << "\nCouldn't open Instructions.txt.\n"; - return 0; - } - int count = 0; - while(true) - { - string instruction; - int pos; - getline(inputs, instruction); - if (inputs.eof()) - { - break; - } - - pos = instruction.find(":->:"); - if (instruction[0] != '$') - { - (*map).insert(unordered_map::value_type(instruction.substr(0, pos), count)); - } - else // need to get the parameters from the GDB command and insert them into the GDB response. Count will be negative so sending and listening threads will know about that. - { - (*map).insert(unordered_map::value_type(instruction.substr(1, pos - 1), count * -1)); - } - instruction.erase(0, pos + 4); - parsingInstructions[count] = instruction; - count++; - } - - inputs.close(); - return (1); -} - - -/// -/// Thread responsible for sending commands to GDB. The GDBParserAPI LaunchProcess start this one, that stays alive until it receives -/// a -gdb-exit instruction. This thread initializes the main data structures that are needed by teh parser and the listeningGDB thread. -/// -/// A reference to the GDB console (Current instance of GDB debugger). -/// 0 -unsigned __stdcall sendingCommands2GDB(void *arg) -{ - GDBConsole *console = (GDBConsole *)arg; - - // Initializing listeningGDB thread data. - HANDLE listeningThread; - unsigned threadID; - ListeningThreadData listeningThreadData; - void *listen = &listeningThreadData; - - int seq_id = SyncInstructionsSize; // Positions 0 to 49 are reserved for synchronous commands. - int countExecInterrupt = 0; - - // Initializing mutex and event objects. - hGDBBufferMutex = CreateMutex (NULL, FALSE, NULL); - hOutputBufferMutex = CreateMutex (NULL, FALSE, NULL); - hInputBufferMutex = CreateMutex (NULL, FALSE, NULL); - inputEvent = CreateEventW(NULL, FALSE, FALSE, _T("inputEvent")); - asyncOutputEvent = CreateEventW(NULL, FALSE, FALSE, _T("asyncOutputEvent")); - - GDBBuffer.quantity = 0; - - unordered_map commandCodesMap; - string parsingInstructions[NumberOfInstructions]; - - if(!insertingCommandCodes(&commandCodesMap, parsingInstructions)) - { - printf("Error initializing parsing data structures"); - } - - // Starting listeningGDB thread. - listeningThreadData.console = console; - listeningThreadData.parsingInstructions = parsingInstructions; - listeningThread = (HANDLE)_beginthreadex( NULL, 0, &listeningGDB, (void *)listen, 0, &threadID); - - char lastCommandSend[GDBCommandSize] = ""; - - while (true) - { - char inputCommandSend[GDBCommandSize] = ""; - char commandSend[GDBCommandSize] = ""; - int instructionCodeSend; - string param = ""; - bool sync = false; - int previousSeqId; - - removeFromInputBuffer(inputCommandSend); - while (strcmp(inputCommandSend,"") == 0) - { - if (in_InputBuffer == out_InputBuffer) // if true, input buffer is empty. - WaitForSingleObject(inputEvent, WAIT_TIME); - removeFromInputBuffer(inputCommandSend); - } - - if ((inputCommandSend[0] >= '0') && (inputCommandSend[0] <= '4')) // Means that it is a synchronous command and the instruction - // already has the ID. - { - sync = true; - previousSeqId = seq_id; - seq_id = ((inputCommandSend[0] - '0') * 10) + (inputCommandSend[1] - '0'); - char *aux_str = inputCommandSend + 2; - strcpy(inputCommandSend, aux_str); - } - - if (strcmp(inputCommandSend, "-exec-interrupt") == 0) - { - if ((strcmp(lastCommandSend, "-exec-interrupt") == 0) && (countExecInterrupt < 5)) - { - countExecInterrupt++; - console->sendCtrlC(); - continue; - } - countExecInterrupt = 0; - // Wait for existing commands to finish - while (!isGDBBufferEmpty()) - Sleep(0); - - console->sendCtrlC(); - } - - if (strcmp(inputCommandSend, "-gdb-exit") == 0) - { - break; - } - - if ((strcmp(inputCommandSend, "-exec-continue") == 0) || (strcmp(inputCommandSend, "-exec-continue --thread 1") == 0)) - // GDB some times lose the commands that were sent while it was running an -exec-continue, what can cause a deadlock. So, - // waiting for the previous commands to finish. - { - while (!isGDBBufferEmpty()) - Sleep(0); - } - - itoa(seq_id, commandSend, 10); - - strcat(commandSend, inputCommandSend); - strcat(commandSend, "\r\n"); - - instructionCodeSend = getInstructionCode(inputCommandSend, commandCodesMap, ¶m); - if (instructionCodeSend == -1) - break; - - int bufferPos = seq_id; // Calculate GDB buffer position. Had to do now because I know if the instruction is synchronous or not. - if (bufferPos >= SyncInstructionsSize) - { // Avoid writing in the first 50 positions that are reserved for synchronous instructions. - bufferPos = (bufferPos % SyncInstructionsSize) + SyncInstructionsSize; - } - - while (!addIntoGDBBuffer(bufferPos, instructionCodeSend, param)) - { - printf("Position in GDB buffer is full!"); - Sleep(0); - } - - console->sendCommand(commandSend); - - if ((strcmp(inputCommandSend, "-exec-continue") == 0) || (strcmp(inputCommandSend, "-exec-continue --thread 1") == 0)) - { - while (!isGDBBufferEmpty()) - Sleep(0); - } - strcpy(lastCommandSend, inputCommandSend); - - if (!sync) - seq_id++; - else - seq_id = previousSeqId; - }; - - exitGDB = true; - WaitForSingleObject(listeningThread, INFINITE); - - // Once GDB exits, further attempts to read or write to the GDB console will result in errors - if (console != NULL) { - delete console; - console = NULL; - } - - return 0; -} \ No newline at end of file diff --git a/src/GDBParser/gdb-connect.h b/src/GDBParser/gdb-connect.h deleted file mode 100644 index 450faa46..00000000 --- a/src/GDBParser/gdb-connect.h +++ /dev/null @@ -1,110 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -#include - -#include "stdafx.h" -#include -#include -#include -#include - -using namespace std; - -#define NumberOfInstructions 48 // Number of parsing instructions in Instructios.txt file. -#define InputBufferSize 50 // Input buffer is used by the debug engine to send GDB commands. -#define GDBBufferSize 100 // Intermediate buffer is used as a communication channel between - // sendingCommands2GDB and listeningGDB threads. -#define OutputBufferSize 100 // Output buffer is used to send the parsed GDB responses to the debug engine. -#define SyncInstructionsSize 50 // This number is used to separate the Output buffer in two parts: first part - // for synchronous commands; and second for asynchronous ones. -#define GDBCommandSize 256 // Maximum size for a GDB command. -#define ParsedMessageSize 8192 // Maximum size for a parsed GDB response. -#define MultipleThreads 0 // 1 - use multiple parsing threads, 0 - single parsing thread. -#define MAX_EVENT_NAME_LENGTH 256 -#define WAIT_TIME 1000L // max amount of time to wait for single events. - -#define LOG_GDB_RAW_IO 1 // 1 - generate GDB output log file; 0 - do not generate. - -class GDBConsole { - -private: - static GDBConsole* m_instance; // represents an instance of GDB debugger. - HANDLE m_hInputRead, m_hInputWrite, m_hOutputRead, m_hOutputWrite, m_hErrorWrite; - BOOL m_isClosed; - static TCHAR* m_pcGDBCmd; - DWORD m_pid; - HANDLE m_hProcess; - HANDLE m_eventCtrlC; - HANDLE m_eventTerminate; - HANDLE m_hCleanupMutex; - - GDBConsole(); - void cleanup(); - HANDLE getStdOutHandle(); - BOOL isClosed(); - BOOL isMoreOutputAvailable (); - void logPrint(char*); - void prepAndLaunchRedirectedChild(); - int readOutput(CHAR*, int, int*); - -public: - ~GDBConsole(); - static GDBConsole* getInstance(); - int sendCommand(const CHAR*); - void sendCtrlC(); - static void setGDBPath(const TCHAR*); - static void shutdown(); - string waitForPrompt(bool); - string waitForPromptWithTimeout(int); -}; - -void DisplayError(LPCTSTR); -void ErrorExit(LPTSTR); - -// Threads responsible for calling the right GDBConsole methods to send commands to GDB and to get responses from GDB. They are also -// responsible for handling the messages that are sent to/received from GDB. -unsigned __stdcall listeningGDB(void *); -unsigned __stdcall sendingCommands2GDB(void *); - -// Functions that perform some specific tasks to the above threads responsible for sending GDB commands and receiving GDB responses. -int getInstructionCode(string, unordered_map, string*); -int getSeqID(string); -bool insertingCommandCodes(unordered_map *, string [NumberOfInstructions]); - -// Functions/thread responsible for parsing GDB responses. -unsigned __stdcall parseGDBResponseThread(void *); // Call this function if using multithreaded parsing or (see below). -void parseGDB(string, string, int); // call this function if not using multithreaded parsing. -string parseGDB(string, string); // Call this function when starting GDB (this one doesn't use the OutputBuffer). -string parseGDB(string*, string, int, bool, char[10][128], string); // The above functions will call this one that is the one responsible for parsing the GDB response. - -// Functions that perform some specific tasks to the one responsible for parsing GDB responses. -int findClosing(char, char, string, int); -int getNextChar(char, string, int); -int searchResponse(string, string, int, int, bool, char); -string substituteVariables(string, char[10][128]); - -// The following methods are responsible for manipulating the buffers (Input, GDB and Output). -void cleanBuffers(); -bool addIntoInputBuffer(char [GDBCommandSize]); -void removeFromInputBuffer(char *); -bool isInputBufferEmpty(); -bool addIntoGDBBuffer(int, int, string); -int removeFromGDBBuffer(int, string*); -bool isGDBBufferEmpty(); -bool addIntoOutputBuffer(int, char *); -void removeFromOutputBuffer(char *); -void removeSyncFromOutputBuffer(char *, int); \ No newline at end of file diff --git a/src/GDBParser/resource.h b/src/GDBParser/resource.h deleted file mode 100644 index b5cbeb73..00000000 --- a/src/GDBParser/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - - -#define IDR_GDBPARSER 101 diff --git a/src/GDBParser/stdafx.cpp b/src/GDBParser/stdafx.cpp deleted file mode 100644 index 94616139..00000000 --- a/src/GDBParser/stdafx.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#include "stdafx.h" - diff --git a/src/GDBParser/stdafx.h b/src/GDBParser/stdafx.h deleted file mode 100644 index 09d97b98..00000000 --- a/src/GDBParser/stdafx.h +++ /dev/null @@ -1,54 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -// 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 XP or later. -#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. -#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. -#endif - -#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. -#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. -#endif - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include -#include -//#include - -#include - -#define BEGIN_NAMESPACE namespace VSNDK { namespace Parser { -#define END_NAMESPACE }; }; - -BEGIN_NAMESPACE -END_NAMESPACE - -using namespace VSNDK::Parser; diff --git a/src/GDBWrapper/GDBWrapper.cpp b/src/GDBWrapper/GDBWrapper.cpp deleted file mode 100644 index 8acc8736..00000000 --- a/src/GDBWrapper/GDBWrapper.cpp +++ /dev/null @@ -1,324 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - - -// GDBWrapper.cpp : Utility to run GDB in console mode so that CTRL-C works. -// - -#include "stdafx.h" - -#include -#include - -#include -#include -#include -#include - -#include - -#include "GDBWrapper.h" -#include < vcclr.h > - -// ******************************************************************* -// TODO: Put the following functions in a library that both GDBWrapper -// and GDBConsole can use - -using namespace std; -using namespace System; - -char path_log[_MAX_PATH]; // contains the path to the Wrapper output log, needed in logPrint() - - -/// -/// Displays the error number and corresponding message. -/// -/// Error message. -void DisplayError(LPCTSTR pszAPI) -{ - LPVOID lpvMessageBuffer; - TCHAR szPrintBuffer[512]; - DWORD bufSize = 512 * sizeof(TCHAR); - DWORD nCharsWritten; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpvMessageBuffer, 0, NULL); - - StringCbPrintf(szPrintBuffer, bufSize, - _T("ERROR: API = %s.\n error code = %d.\n message = %s.\n"), - pszAPI, GetLastError(), (char *)lpvMessageBuffer); - - _tprintf(_T("%s\n"), szPrintBuffer); - - LocalFree(lpvMessageBuffer); - ExitProcess(GetLastError()); -} - - -/// -/// Retrieve the system error message for the last-error code. -/// -/// Error message. -void ErrorExit(LPTSTR lpszFunction) -{ - LPVOID lpMsgBuf; - LPVOID lpDisplayBuf; - DWORD dw = GetLastError(); - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL ); - - // Display the error message and exit the process - - lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, - (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); - StringCchPrintf((LPTSTR)lpDisplayBuf, - LocalSize(lpDisplayBuf) / sizeof(TCHAR), - TEXT("%s failed with error %d: %s"), - lpszFunction, dw, lpMsgBuf); - MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); - - LocalFree(lpMsgBuf); - LocalFree(lpDisplayBuf); - ExitProcess(dw); -} - - -/// -/// Generic function to print to a log file. -/// -/// Message to be printed to a log file. -void logPrint(TCHAR* buffer) { - if (LOG_GDB_RAW_IO) { - FILE* file = fopen(path_log, "a"); - _ftprintf(file, _T("%s\r\n"), buffer); - fclose(file); - } -} - -// End region that needs to go into a library -// ******************************************************************* - - -/// -/// CTRL-C handler. -/// -/// CTRL type. -/// True; False. -BOOL WINAPI ctrlHandler(DWORD dwCtrlType) -{ - logPrint(_T("ctrlHandler")); - if (dwCtrlType == CTRL_C_EVENT) { - logPrint(_T("ctrlHandler got CTRL_C_EVENT")); - return true; - } - logPrint(_T("ctrlHandler returns false")); - return false; -} - - -/// -/// Constructor. -/// -/// String with full path and command to initialize GDB/MI. -/// Ctrl-C handler; -/// Terminate handler; -GDBWrapper::GDBWrapper(TCHAR* pcGDBCmd, HANDLE eventCtrlC, HANDLE eventTerminate) : - m_eventCtrlC(eventCtrlC), m_eventTerminate(eventTerminate), m_isClosed(FALSE) -{ - SECURITY_ATTRIBUTES sa; - - // Copy path to GDB - size_t numChars = _tcslen(pcGDBCmd) + 1; - m_pcGDBCmd = new TCHAR[numChars * sizeof(TCHAR)]; - _tcscpy_s(m_pcGDBCmd, numChars, pcGDBCmd); - - // Register CTRL-C handler - if (!SetConsoleCtrlHandler(ctrlHandler, TRUE)) { - DisplayError(_T("SetConsoleCtrlHandler")); - } - - // Set up the security attributes struct used when creating the pipes - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - prepAndLaunchRedirectedChild(); -} - - -/// -/// Shut down GDB Wrapper: Update variables and terminate GDBWrapper process. -/// -void GDBWrapper::shutdown() { - logPrint(_T("+shutdown")); - m_isClosed = TRUE; - - if (m_pcGDBCmd != NULL) { - delete[] m_pcGDBCmd; - m_pcGDBCmd = NULL; - } - - // Kill GDB process - TerminateProcess(m_hProcess, 0); - - if (!CloseHandle(m_hProcess)) DisplayError(_T("CloseHandle")); - logPrint(_T("-shutdown")); -} - - -/// -/// Destructor. -/// -GDBWrapper::~GDBWrapper() { - logPrint(_T("+~GDBWrapper")); - if (!m_isClosed) { - shutdown(); - } - logPrint(_T("-~GDBWrapper")); -} - - -/// -/// Sets up STARTUPINFO structure and launches redirected child. -/// -void GDBWrapper::prepAndLaunchRedirectedChild(void) -{ - LPCTSTR lpApplicationName = NULL; - PROCESS_INFORMATION pi; - STARTUPINFO si; - DWORD flags = 0; - - memset(&pi, 0, sizeof(pi)); - - // Set up the start up info struct. - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES; - - // Pass the redirected handles - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - - // Use this if you want to hide the child: - // si.wShowWindow = SW_HIDE; - // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to - // use the wShowWindow flags. - - /* CreateProcessW can modify pCmdLine thus we allocate memory */ - int pCmdSz = _tcslen(m_pcGDBCmd) + 1; - LPTSTR pCmdLine = new TCHAR[pCmdSz]; - if (pCmdLine == 0) { - DisplayError(_T("GDBWrapper::launch: failed to allocate memory for pCmdLine")); - } - _tcscpy_s(pCmdLine, pCmdSz, m_pcGDBCmd); - - // Launch the process - if (!CreateProcess(NULL, pCmdLine, NULL, NULL, TRUE, - flags, NULL, NULL, &si, &pi)) - ErrorExit(_T("CreateProcess")); - - m_hProcess = pi.hProcess; - - if (!CloseHandle(pi.hThread)) DisplayError(_T("CloseHandle")); -} - - -/// -/// GDBWrapper Main function. -/// -/// Not used. -/// argv[0] -> Full path of the GDBWrapper executable file. -/// argv[1] -> String with full path and command to initialize GDB/MI -/// argv[2] -> Ctrl-C handler; -/// argv[3] -> Terminate handler. -/// 0 -int _tmain(int argc, _TCHAR* argv[]) -{ - TCHAR msg[1024]; - memset(msg, 0, 1024); - - WCHAR wszThisFile[MAX_PATH + 1]; - GetModuleFileName(NULL, wszThisFile, MAX_PATH + 1); - - String^ tempPath = Environment::GetEnvironmentVariable("APPDATA"); - tempPath += "\\BlackBerry\\wrapper.log"; - pin_ptr path_buffer = PtrToStringChars(tempPath); - - int ret = wcstombs ( path_log, path_buffer, _MAX_PATH ); - - FILE* file = fopen(path_log, "w"); // just to delete a possible existing file - fclose(file); - - logPrint(_T("Starting")); - - HANDLE handles[2]; - handles[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[2]); // Ctrl-C signal - handles[1] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]); // Signal to terminate the wrapper process - - _stprintf(msg, _T("args: %s %s %s %s\r\n"), argv[0], argv[1], argv[2], argv[3]); - _tprintf(msg); - logPrint(msg); - - _stprintf(msg, _T("Ctrl-C handler: name: %s handle: %p\r\n"), argv[2], handles[0]); - _tprintf(msg); - logPrint(msg); - - _stprintf(msg, _T("Terminate handler: name: %s handle: %p\r\n"), argv[3], handles[1]); - _tprintf(msg); - logPrint(msg); - - GDBWrapper* g = new GDBWrapper(argv[1], handles[0], handles[1]); - - BOOL exitProc = FALSE; - while(!exitProc) - { - // Wait for a CTRL-C event indicating GDB should be interrupted - logPrint(_T("WaitForMultipleObjects")); - DWORD event = WaitForMultipleObjects(2, handles, false, INFINITE); - switch (event) - { - case WAIT_OBJECT_0: - logPrint(_T("WAIT_OBJECT_0 (Ctrl-C)")); - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); - break; - case WAIT_OBJECT_0 + 1: - logPrint(_T("WAIT_OBJECT_0 + 1 (Terminate)")); - exitProc = TRUE; - break; - case WAIT_FAILED: - DisplayError(_T("WaitForSingleObject WAIT_FAILED")); - exitProc = TRUE; - break; - default: - exitProc = TRUE; - break; - } - } - - g->shutdown(); - - return 0; -} diff --git a/src/GDBWrapper/GDBWrapper.h b/src/GDBWrapper/GDBWrapper.h deleted file mode 100644 index 6568e359..00000000 --- a/src/GDBWrapper/GDBWrapper.h +++ /dev/null @@ -1,47 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -#include -#include - -#include "stdafx.h" -#include -#include -#include - -using namespace std; - -#define LOG_GDB_RAW_IO 1 - -class GDBWrapper { - -private: - BOOL m_isClosed; - HANDLE m_hProcess; - HANDLE m_eventCtrlC; - HANDLE m_eventTerminate; - TCHAR* m_pcGDBCmd; - - void prepAndLaunchRedirectedChild(); - -public: - GDBWrapper(TCHAR*, HANDLE, HANDLE); - ~GDBWrapper(); - void shutdown(); -}; - -void ErrorExit(LPTSTR); -void DisplayError(LPCTSTR); \ No newline at end of file diff --git a/src/GDBWrapper/GDBWrapper.vcxproj b/src/GDBWrapper/GDBWrapper.vcxproj deleted file mode 100644 index 86896fe8..00000000 --- a/src/GDBWrapper/GDBWrapper.vcxproj +++ /dev/null @@ -1,100 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {9A560339-44DB-413F-868C-403962C2CF01} - Win32Proj - GDBWrapper - - - - Application - true - Unicode - true - - - Application - false - true - Unicode - true - - - - - - - - - - - - - true - - - false - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - false - - - xcopy "$(OutDir)GDBWrapper.*" "$(OutputPath)" /d /y - Copying Executable to output directory. - - - - - - - - - - - Create - Create - - - - - - \ No newline at end of file diff --git a/src/GDBWrapper/GDBWrapper.vcxproj.filters b/src/GDBWrapper/GDBWrapper.vcxproj.filters deleted file mode 100644 index 58ea2b2e..00000000 --- a/src/GDBWrapper/GDBWrapper.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/src/GDBWrapper/GDBWrapper.vcxproj.user b/src/GDBWrapper/GDBWrapper.vcxproj.user deleted file mode 100644 index 79ff5bc5..00000000 --- a/src/GDBWrapper/GDBWrapper.vcxproj.user +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - WindowsLocalDebugger - - \ No newline at end of file diff --git a/src/GDBWrapper/ReadMe.txt b/src/GDBWrapper/ReadMe.txt deleted file mode 100644 index 051b81d3..00000000 --- a/src/GDBWrapper/ReadMe.txt +++ /dev/null @@ -1,40 +0,0 @@ -======================================================================== - CONSOLE APPLICATION : GDBWrapper Project Overview -======================================================================== - -AppWizard has created this GDBWrapper application for you. - -This file contains a summary of what you will find in each of the files that -make up your GDBWrapper application. - - -GDBWrapper.vcxproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -GDBWrapper.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -GDBWrapper.cpp - This is the main application source file. - -///////////////////////////////////////////////////////////////////////////// -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named GDBWrapper.pch and a precompiled types file named StdAfx.obj. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" comments to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/src/GDBWrapper/stdafx.h b/src/GDBWrapper/stdafx.h deleted file mode 100644 index ee239709..00000000 --- a/src/GDBWrapper/stdafx.h +++ /dev/null @@ -1,29 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" - -#include -#include - - - -// TODO: reference additional headers your program requires here diff --git a/src/VSNDK.AddIn/AssemblyInfo.cs b/src/VSNDK.AddIn/AssemblyInfo.cs deleted file mode 100644 index 12ea939e..00000000 Binary files a/src/VSNDK.AddIn/AssemblyInfo.cs and /dev/null differ diff --git a/src/VSNDK.AddIn/Connect.cs b/src/VSNDK.AddIn/Connect.cs deleted file mode 100644 index 86d6f067..00000000 Binary files a/src/VSNDK.AddIn/Connect.cs and /dev/null differ diff --git a/src/VSNDK.AddIn/Guids.cs b/src/VSNDK.AddIn/Guids.cs deleted file mode 100644 index 8ce421f7..00000000 --- a/src/VSNDK.AddIn/Guids.cs +++ /dev/null @@ -1,28 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace VSNDK.AddIn -{ - static class GuidList - { - public const string guidVSStd97String = "{5efc7975-14bc-11cf-9b2b-00aa00573819}"; - public const string guidVSStd2KString = "{1496A755-94DE-11D0-8C3F-00C04FC2AAE2}"; - public const string guidVSDebugGroup = "{C9DD4A59-47FB-11D2-83E7-00C04F9902C1}"; - }; -} diff --git a/src/VSNDK.AddIn/NameValueCollectionHelper.cs b/src/VSNDK.AddIn/NameValueCollectionHelper.cs deleted file mode 100644 index 1fa05e9c..00000000 --- a/src/VSNDK.AddIn/NameValueCollectionHelper.cs +++ /dev/null @@ -1,76 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections.Specialized; - -namespace VSNDK.AddIn -{ - /// - /// - /// - public static class NameValueCollectionHelper - { - - /// - /// - /// - /// - /// - public static string DumpToString(NameValueCollection value) - { - var xSB = new StringBuilder(); - foreach (string xKey in value.Keys) - { - xSB.AppendFormat("{0}={1};", xKey, (string)value[xKey]); - } - return xSB.ToString(); - } - - - /// - /// - /// - /// - /// - public static void LoadFromString(NameValueCollection target, string value) - { - if (target.Count > 0) - { - throw new Exception("Target is not empty!"); - } - if (String.IsNullOrEmpty(value)) - { - return; - } - - string[] xPairs = value.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - foreach (var xPair in xPairs) - { - string[] xParts = xPair.Split('='); - if (xParts.Length > 1) - { - target.Add(xParts[0], xParts[1]); - } - else - { - target.Add(xParts[0], ""); - } - } - } - } -} \ No newline at end of file diff --git a/src/VSNDK.AddIn/NativeMethods.cs b/src/VSNDK.AddIn/NativeMethods.cs deleted file mode 100644 index 4c2c5035..00000000 --- a/src/VSNDK.AddIn/NativeMethods.cs +++ /dev/null @@ -1,713 +0,0 @@ -/*************************************************************************** - -Copyright (c) Microsoft Corporation. All rights reserved. -This code is licensed under the Visual Studio SDK license terms. -THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. - -***************************************************************************/ - -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.TextManager.Interop; -using Microsoft.VisualStudio.OLE.Interop; - -namespace Microsoft.VisualStudio.Project -{ - public static class NativeMethods - { - // IIDS - public static readonly Guid IID_IUnknown = new Guid("{00000000-0000-0000-C000-000000000046}"); - - public const int - CLSCTX_INPROC_SERVER = 0x1; - - public const int - S_FALSE = 0x00000001, - S_OK = 0x00000000, - - IDOK = 1, - IDCANCEL = 2, - IDABORT = 3, - IDRETRY = 4, - IDIGNORE = 5, - IDYES = 6, - IDNO = 7, - IDCLOSE = 8, - IDHELP = 9, - IDTRYAGAIN = 10, - IDCONTINUE = 11, - - OLECMDERR_E_NOTSUPPORTED = unchecked((int)0x80040100), - OLECMDERR_E_UNKNOWNGROUP = unchecked((int)0x80040104), - - UNDO_E_CLIENTABORT = unchecked((int)0x80044001), - E_OUTOFMEMORY = unchecked((int)0x8007000E), - E_INVALIDARG = unchecked((int)0x80070057), - E_FAIL = unchecked((int)0x80004005), - E_NOINTERFACE = unchecked((int)0x80004002), - E_POINTER = unchecked((int)0x80004003), - E_NOTIMPL = unchecked((int)0x80004001), - E_UNEXPECTED = unchecked((int)0x8000FFFF), - E_HANDLE = unchecked((int)0x80070006), - E_ABORT = unchecked((int)0x80004004), - E_ACCESSDENIED = unchecked((int)0x80070005), - E_PENDING = unchecked((int)0x8000000A); - - public const int - OLECLOSE_SAVEIFDIRTY = 0, - OLECLOSE_NOSAVE = 1, - OLECLOSE_PROMPTSAVE = 2; - - public const int - OLEIVERB_PRIMARY = 0, - OLEIVERB_SHOW = -1, - OLEIVERB_OPEN = -2, - OLEIVERB_HIDE = -3, - OLEIVERB_UIACTIVATE = -4, - OLEIVERB_INPLACEACTIVATE = -5, - OLEIVERB_DISCARDUNDOSTATE = -6, - OLEIVERB_PROPERTIES = -7; - - public const int - OFN_READONLY = unchecked((int)0x00000001), - OFN_OVERWRITEPROMPT = unchecked((int)0x00000002), - OFN_HIDEREADONLY = unchecked((int)0x00000004), - OFN_NOCHANGEDIR = unchecked((int)0x00000008), - OFN_SHOWHELP = unchecked((int)0x00000010), - OFN_ENABLEHOOK = unchecked((int)0x00000020), - OFN_ENABLETEMPLATE = unchecked((int)0x00000040), - OFN_ENABLETEMPLATEHANDLE = unchecked((int)0x00000080), - OFN_NOVALIDATE = unchecked((int)0x00000100), - OFN_ALLOWMULTISELECT = unchecked((int)0x00000200), - OFN_EXTENSIONDIFFERENT = unchecked((int)0x00000400), - OFN_PATHMUSTEXIST = unchecked((int)0x00000800), - OFN_FILEMUSTEXIST = unchecked((int)0x00001000), - OFN_CREATEPROMPT = unchecked((int)0x00002000), - OFN_SHAREAWARE = unchecked((int)0x00004000), - OFN_NOREADONLYRETURN = unchecked((int)0x00008000), - OFN_NOTESTFILECREATE = unchecked((int)0x00010000), - OFN_NONETWORKBUTTON = unchecked((int)0x00020000), - OFN_NOLONGNAMES = unchecked((int)0x00040000), - OFN_EXPLORER = unchecked((int)0x00080000), - OFN_NODEREFERENCELINKS = unchecked((int)0x00100000), - OFN_LONGNAMES = unchecked((int)0x00200000), - OFN_ENABLEINCLUDENOTIFY = unchecked((int)0x00400000), - OFN_ENABLESIZING = unchecked((int)0x00800000), - OFN_USESHELLITEM = unchecked((int)0x01000000), - OFN_DONTADDTORECENT = unchecked((int)0x02000000), - OFN_FORCESHOWHIDDEN = unchecked((int)0x10000000); - - // for READONLYSTATUS - public const int - ROSTATUS_NotReadOnly = 0x0, - ROSTATUS_ReadOnly = 0x1, - ROSTATUS_Unknown = unchecked((int)0xFFFFFFFF); - - public const int - IEI_DoNotLoadDocData = 0x10000000; - - public const int - CB_SETDROPPEDWIDTH = 0x0160, - - GWL_STYLE = (-16), - GWL_EXSTYLE = (-20), - - DWL_MSGRESULT = 0, - - SW_SHOWNORMAL = 1, - - HTMENU = 5, - - WS_POPUP = unchecked((int)0x80000000), - WS_CHILD = 0x40000000, - WS_MINIMIZE = 0x20000000, - WS_VISIBLE = 0x10000000, - WS_DISABLED = 0x08000000, - WS_CLIPSIBLINGS = 0x04000000, - WS_CLIPCHILDREN = 0x02000000, - WS_MAXIMIZE = 0x01000000, - WS_CAPTION = 0x00C00000, - WS_BORDER = 0x00800000, - WS_DLGFRAME = 0x00400000, - WS_VSCROLL = 0x00200000, - WS_HSCROLL = 0x00100000, - WS_SYSMENU = 0x00080000, - WS_THICKFRAME = 0x00040000, - WS_TABSTOP = 0x00010000, - WS_MINIMIZEBOX = 0x00020000, - WS_MAXIMIZEBOX = 0x00010000, - WS_EX_DLGMODALFRAME = 0x00000001, - WS_EX_MDICHILD = 0x00000040, - WS_EX_TOOLWINDOW = 0x00000080, - WS_EX_CLIENTEDGE = 0x00000200, - WS_EX_CONTEXTHELP = 0x00000400, - WS_EX_RIGHT = 0x00001000, - WS_EX_LEFT = 0x00000000, - WS_EX_RTLREADING = 0x00002000, - WS_EX_LEFTSCROLLBAR = 0x00004000, - WS_EX_CONTROLPARENT = 0x00010000, - WS_EX_STATICEDGE = 0x00020000, - WS_EX_APPWINDOW = 0x00040000, - WS_EX_LAYERED = 0x00080000, - WS_EX_TOPMOST = 0x00000008, - WS_EX_NOPARENTNOTIFY = 0x00000004, - - LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000 + 54), - - LVS_EX_LABELTIP = 0x00004000, - - // winuser.h - WH_JOURNALPLAYBACK = 1, - WH_GETMESSAGE = 3, - WH_MOUSE = 7, - WSF_VISIBLE = 0x0001, - WM_NULL = 0x0000, - WM_CREATE = 0x0001, - WM_DELETEITEM = 0x002D, - WM_DESTROY = 0x0002, - WM_MOVE = 0x0003, - WM_SIZE = 0x0005, - WM_ACTIVATE = 0x0006, - WA_INACTIVE = 0, - WA_ACTIVE = 1, - WA_CLICKACTIVE = 2, - WM_SETFOCUS = 0x0007, - WM_KILLFOCUS = 0x0008, - WM_ENABLE = 0x000A, - WM_SETREDRAW = 0x000B, - WM_SETTEXT = 0x000C, - WM_GETTEXT = 0x000D, - WM_GETTEXTLENGTH = 0x000E, - WM_PAINT = 0x000F, - WM_CLOSE = 0x0010, - WM_QUERYENDSESSION = 0x0011, - WM_QUIT = 0x0012, - WM_QUERYOPEN = 0x0013, - WM_ERASEBKGND = 0x0014, - WM_SYSCOLORCHANGE = 0x0015, - WM_ENDSESSION = 0x0016, - WM_SHOWWINDOW = 0x0018, - WM_WININICHANGE = 0x001A, - WM_SETTINGCHANGE = 0x001A, - WM_DEVMODECHANGE = 0x001B, - WM_ACTIVATEAPP = 0x001C, - WM_FONTCHANGE = 0x001D, - WM_TIMECHANGE = 0x001E, - WM_CANCELMODE = 0x001F, - WM_SETCURSOR = 0x0020, - WM_MOUSEACTIVATE = 0x0021, - WM_CHILDACTIVATE = 0x0022, - WM_QUEUESYNC = 0x0023, - WM_GETMINMAXINFO = 0x0024, - WM_PAINTICON = 0x0026, - WM_ICONERASEBKGND = 0x0027, - WM_NEXTDLGCTL = 0x0028, - WM_SPOOLERSTATUS = 0x002A, - WM_DRAWITEM = 0x002B, - WM_MEASUREITEM = 0x002C, - WM_VKEYTOITEM = 0x002E, - WM_CHARTOITEM = 0x002F, - WM_SETFONT = 0x0030, - WM_GETFONT = 0x0031, - WM_SETHOTKEY = 0x0032, - WM_GETHOTKEY = 0x0033, - WM_QUERYDRAGICON = 0x0037, - WM_COMPAREITEM = 0x0039, - WM_GETOBJECT = 0x003D, - WM_COMPACTING = 0x0041, - WM_COMMNOTIFY = 0x0044, - WM_WINDOWPOSCHANGING = 0x0046, - WM_WINDOWPOSCHANGED = 0x0047, - WM_POWER = 0x0048, - WM_COPYDATA = 0x004A, - WM_CANCELJOURNAL = 0x004B, - WM_NOTIFY = 0x004E, - WM_INPUTLANGCHANGEREQUEST = 0x0050, - WM_INPUTLANGCHANGE = 0x0051, - WM_TCARD = 0x0052, - WM_HELP = 0x0053, - WM_USERCHANGED = 0x0054, - WM_NOTIFYFORMAT = 0x0055, - WM_CONTEXTMENU = 0x007B, - WM_STYLECHANGING = 0x007C, - WM_STYLECHANGED = 0x007D, - WM_DISPLAYCHANGE = 0x007E, - WM_GETICON = 0x007F, - WM_SETICON = 0x0080, - WM_NCCREATE = 0x0081, - WM_NCDESTROY = 0x0082, - WM_NCCALCSIZE = 0x0083, - WM_NCHITTEST = 0x0084, - WM_NCPAINT = 0x0085, - WM_NCACTIVATE = 0x0086, - WM_GETDLGCODE = 0x0087, - WM_NCMOUSEMOVE = 0x00A0, - WM_NCLBUTTONDOWN = 0x00A1, - WM_NCLBUTTONUP = 0x00A2, - WM_NCLBUTTONDBLCLK = 0x00A3, - WM_NCRBUTTONDOWN = 0x00A4, - WM_NCRBUTTONUP = 0x00A5, - WM_NCRBUTTONDBLCLK = 0x00A6, - WM_NCMBUTTONDOWN = 0x00A7, - WM_NCMBUTTONUP = 0x00A8, - WM_NCMBUTTONDBLCLK = 0x00A9, - WM_NCXBUTTONDOWN = 0x00AB, - WM_NCXBUTTONUP = 0x00AC, - WM_NCXBUTTONDBLCLK = 0x00AD, - WM_KEYFIRST = 0x0100, - WM_KEYDOWN = 0x0100, - WM_KEYUP = 0x0101, - WM_CHAR = 0x0102, - WM_DEADCHAR = 0x0103, - WM_CTLCOLOR = 0x0019, - WM_SYSKEYDOWN = 0x0104, - WM_SYSKEYUP = 0x0105, - WM_SYSCHAR = 0x0106, - WM_SYSDEADCHAR = 0x0107, - WM_KEYLAST = 0x0108, - WM_IME_STARTCOMPOSITION = 0x010D, - WM_IME_ENDCOMPOSITION = 0x010E, - WM_IME_COMPOSITION = 0x010F, - WM_IME_KEYLAST = 0x010F, - WM_INITDIALOG = 0x0110, - WM_COMMAND = 0x0111, - WM_SYSCOMMAND = 0x0112, - WM_TIMER = 0x0113, - WM_HSCROLL = 0x0114, - WM_VSCROLL = 0x0115, - WM_INITMENU = 0x0116, - WM_INITMENUPOPUP = 0x0117, - WM_MENUSELECT = 0x011F, - WM_MENUCHAR = 0x0120, - WM_ENTERIDLE = 0x0121, - WM_CHANGEUISTATE = 0x0127, - WM_UPDATEUISTATE = 0x0128, - WM_QUERYUISTATE = 0x0129, - WM_CTLCOLORMSGBOX = 0x0132, - WM_CTLCOLOREDIT = 0x0133, - WM_CTLCOLORLISTBOX = 0x0134, - WM_CTLCOLORBTN = 0x0135, - WM_CTLCOLORDLG = 0x0136, - WM_CTLCOLORSCROLLBAR = 0x0137, - WM_CTLCOLORSTATIC = 0x0138, - WM_MOUSEFIRST = 0x0200, - WM_MOUSEMOVE = 0x0200, - WM_LBUTTONDOWN = 0x0201, - WM_LBUTTONUP = 0x0202, - WM_LBUTTONDBLCLK = 0x0203, - WM_RBUTTONDOWN = 0x0204, - WM_RBUTTONUP = 0x0205, - WM_RBUTTONDBLCLK = 0x0206, - WM_MBUTTONDOWN = 0x0207, - WM_MBUTTONUP = 0x0208, - WM_MBUTTONDBLCLK = 0x0209, - WM_XBUTTONDOWN = 0x020B, - WM_XBUTTONUP = 0x020C, - WM_XBUTTONDBLCLK = 0x020D, - WM_MOUSEWHEEL = 0x020A, - WM_MOUSELAST = 0x020A, - WM_PARENTNOTIFY = 0x0210, - WM_ENTERMENULOOP = 0x0211, - WM_EXITMENULOOP = 0x0212, - WM_NEXTMENU = 0x0213, - WM_SIZING = 0x0214, - WM_CAPTURECHANGED = 0x0215, - WM_MOVING = 0x0216, - WM_POWERBROADCAST = 0x0218, - WM_DEVICECHANGE = 0x0219, - WM_IME_SETCONTEXT = 0x0281, - WM_IME_NOTIFY = 0x0282, - WM_IME_CONTROL = 0x0283, - WM_IME_COMPOSITIONFULL = 0x0284, - WM_IME_SELECT = 0x0285, - WM_IME_CHAR = 0x0286, - WM_IME_KEYDOWN = 0x0290, - WM_IME_KEYUP = 0x0291, - WM_MDICREATE = 0x0220, - WM_MDIDESTROY = 0x0221, - WM_MDIACTIVATE = 0x0222, - WM_MDIRESTORE = 0x0223, - WM_MDINEXT = 0x0224, - WM_MDIMAXIMIZE = 0x0225, - WM_MDITILE = 0x0226, - WM_MDICASCADE = 0x0227, - WM_MDIICONARRANGE = 0x0228, - WM_MDIGETACTIVE = 0x0229, - WM_MDISETMENU = 0x0230, - WM_ENTERSIZEMOVE = 0x0231, - WM_EXITSIZEMOVE = 0x0232, - WM_DROPFILES = 0x0233, - WM_MDIREFRESHMENU = 0x0234, - WM_MOUSEHOVER = 0x02A1, - WM_MOUSELEAVE = 0x02A3, - WM_CUT = 0x0300, - WM_COPY = 0x0301, - WM_PASTE = 0x0302, - WM_CLEAR = 0x0303, - WM_UNDO = 0x0304, - WM_RENDERFORMAT = 0x0305, - WM_RENDERALLFORMATS = 0x0306, - WM_DESTROYCLIPBOARD = 0x0307, - WM_DRAWCLIPBOARD = 0x0308, - WM_PAINTCLIPBOARD = 0x0309, - WM_VSCROLLCLIPBOARD = 0x030A, - WM_SIZECLIPBOARD = 0x030B, - WM_ASKCBFORMATNAME = 0x030C, - WM_CHANGECBCHAIN = 0x030D, - WM_HSCROLLCLIPBOARD = 0x030E, - WM_QUERYNEWPALETTE = 0x030F, - WM_PALETTEISCHANGING = 0x0310, - WM_PALETTECHANGED = 0x0311, - WM_HOTKEY = 0x0312, - WM_PRINT = 0x0317, - WM_PRINTCLIENT = 0x0318, - WM_HANDHELDFIRST = 0x0358, - WM_HANDHELDLAST = 0x035F, - WM_AFXFIRST = 0x0360, - WM_AFXLAST = 0x037F, - WM_PENWINFIRST = 0x0380, - WM_PENWINLAST = 0x038F, - WM_APP = unchecked((int)0x8000), - WM_USER = 0x0400, - WM_REFLECT = - WM_USER + 0x1C00, - WS_OVERLAPPED = 0x00000000, - WPF_SETMINPOSITION = 0x0001, - WM_CHOOSEFONT_GETLOGFONT = (0x0400 + 1), - - WHEEL_DELTA = 120, - DWLP_MSGRESULT = 0, - PSNRET_NOERROR = 0, - PSNRET_INVALID = 1, - PSNRET_INVALID_NOCHANGEPAGE = 2; - - public const int - PSN_APPLY = ((0 - 200) - 2), - PSN_KILLACTIVE = ((0 - 200) - 1), - PSN_RESET = ((0 - 200) - 3), - PSN_SETACTIVE = ((0 - 200) - 0); - - public const int - GMEM_MOVEABLE = 0x0002, - GMEM_ZEROINIT = 0x0040, - GMEM_DDESHARE = 0x2000; - - public const int - SWP_NOACTIVATE = 0x0010, - SWP_NOZORDER = 0x0004, - SWP_NOSIZE = 0x0001, - SWP_NOMOVE = 0x0002, - SWP_FRAMECHANGED = 0x0020; - - public const int - TVM_SETINSERTMARK = (0x1100 + 26), - TVM_GETEDITCONTROL = (0x1100 + 15); - - public const int - FILE_ATTRIBUTE_READONLY = 0x00000001; - - public const int - PSP_DEFAULT = 0x00000000, - PSP_DLGINDIRECT = 0x00000001, - PSP_USEHICON = 0x00000002, - PSP_USEICONID = 0x00000004, - PSP_USETITLE = 0x00000008, - PSP_RTLREADING = 0x00000010, - PSP_HASHELP = 0x00000020, - PSP_USEREFPARENT = 0x00000040, - PSP_USECALLBACK = 0x00000080, - PSP_PREMATURE = 0x00000400, - PSP_HIDEHEADER = 0x00000800, - PSP_USEHEADERTITLE = 0x00001000, - PSP_USEHEADERSUBTITLE = 0x00002000; - - public const int - PSH_DEFAULT = 0x00000000, - PSH_PROPTITLE = 0x00000001, - PSH_USEHICON = 0x00000002, - PSH_USEICONID = 0x00000004, - PSH_PROPSHEETPAGE = 0x00000008, - PSH_WIZARDHASFINISH = 0x00000010, - PSH_WIZARD = 0x00000020, - PSH_USEPSTARTPAGE = 0x00000040, - PSH_NOAPPLYNOW = 0x00000080, - PSH_USECALLBACK = 0x00000100, - PSH_HASHELP = 0x00000200, - PSH_MODELESS = 0x00000400, - PSH_RTLREADING = 0x00000800, - PSH_WIZARDCONTEXTHELP = 0x00001000, - PSH_WATERMARK = 0x00008000, - PSH_USEHBMWATERMARK = 0x00010000, // user pass in a hbmWatermark instead of pszbmWatermark - PSH_USEHPLWATERMARK = 0x00020000, // - PSH_STRETCHWATERMARK = 0x00040000, // stretchwatermark also applies for the header - PSH_HEADER = 0x00080000, - PSH_USEHBMHEADER = 0x00100000, - PSH_USEPAGELANG = 0x00200000, // use frame dialog template matched to page - PSH_WIZARD_LITE = 0x00400000, - PSH_NOCONTEXTHELP = 0x02000000; - - public const int - PSBTN_BACK = 0, - PSBTN_NEXT = 1, - PSBTN_FINISH = 2, - PSBTN_OK = 3, - PSBTN_APPLYNOW = 4, - PSBTN_CANCEL = 5, - PSBTN_HELP = 6, - PSBTN_MAX = 6; - - public const int - TRANSPARENT = 1, - OPAQUE = 2, - FW_BOLD = 700; - - [StructLayout(LayoutKind.Sequential)] - public struct NMHDR - { - public IntPtr hwndFrom; - public int idFrom; - public int code; - } - - /// - /// Helper class for setting the text parameters to OLECMDTEXT structures. - /// - public static class OLECMDTEXT - { - - /// - /// Flags for the OLE command text - /// - public enum OLECMDTEXTF - { - /// No flag - OLECMDTEXTF_NONE = 0, - /// The name of the command is required. - OLECMDTEXTF_NAME = 1, - /// A description of the status is required. - OLECMDTEXTF_STATUS = 2 - } - } - - /// - /// OLECMDF enums for IOleCommandTarget - /// - public enum tagOLECMDF - { - OLECMDF_SUPPORTED = 1, - OLECMDF_ENABLED = 2, - OLECMDF_LATCHED = 4, - OLECMDF_NINCHED = 8, - OLECMDF_INVISIBLE = 16 - } - - /// - /// This method takes a file URL and converts it to an absolute path. The trick here is that - /// if there is a '#' in the path, everything after this is treated as a fragment. So - /// we need to append the fragment to the end of the path. - /// - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public static string GetAbsolutePath(string fileName) - { - System.Diagnostics.Debug.Assert(fileName != null && fileName.Length > 0, "Cannot get absolute path, fileName is not valid"); - - Uri uri = new Uri(fileName); - return uri.LocalPath + uri.Fragment; - } - - /// - /// Please use this "approved" method to compare file names. - /// - public static bool IsSamePath(string file1, string file2) - { - if(file1 == null || file1.Length == 0) - { - return (file2 == null || file2.Length == 0); - } - - Uri uri1 = null; - Uri uri2 = null; - - try - { - if(!Uri.TryCreate(file1, UriKind.Absolute, out uri1) || !Uri.TryCreate(file2, UriKind.Absolute, out uri2)) - { - return false; - } - - if(uri1 != null && uri1.IsFile && uri2 != null && uri2.IsFile) - { - return 0 == String.Compare(uri1.LocalPath, uri2.LocalPath, StringComparison.OrdinalIgnoreCase); - } - - return file1 == file2; - } - catch(UriFormatException e) - { - Trace.WriteLine("Exception " + e.Message); - } - - return false; - } - - [ComImport(), Guid("9BDA66AE-CA28-4e22-AA27-8A7218A0E3FA"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEventHandler - { - - // converts the underlying codefunction into an event handler for the given event - // if the given event is NULL, then the function will handle no events - [PreserveSig] - int AddHandler(string bstrEventName); - - [PreserveSig] - int RemoveHandler(string bstrEventName); - - IVsEnumBSTR GetHandledEvents(); - - bool HandlesEvent(string bstrEventName); - } - - [ComImport(), Guid("A55CCBCC-7031-432d-B30A-A68DE7BDAD75"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IParameterKind - { - - void SetParameterPassingMode(PARAMETER_PASSING_MODE ParamPassingMode); - void SetParameterArrayDimensions(int uDimensions); - int GetParameterArrayCount(); - int GetParameterArrayDimensions(int uIndex); - int GetParameterPassingMode(); - } - - public enum PARAMETER_PASSING_MODE - { - cmParameterTypeIn = 1, - cmParameterTypeOut = 2, - cmParameterTypeInOut = 3 - } - - [ - ComImport, ComVisible(true), Guid("3E596484-D2E4-461a-A876-254C4F097EBB"), - InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown) - ] - public interface IMethodXML - { - // Generate XML describing the contents of this function's body. - void GetXML(ref string pbstrXML); - - // Parse the incoming XML with respect to the CodeModel XML schema and - // use the result to regenerate the body of the function. - /// - [PreserveSig] - int SetXML(string pszXML); - - // This is really a textpoint - [PreserveSig] - int GetBodyPoint([MarshalAs(UnmanagedType.Interface)]out object bodyPoint); - } - - [ComImport(), Guid("EA1A87AD-7BC5-4349-B3BE-CADC301F17A3"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - public interface IVBFileCodeModelEvents - { - - [PreserveSig] - int StartEdit(); - - [PreserveSig] - int EndEdit(); - } - - ///-------------------------------------------------------------------------- - /// ICodeClassBase: - ///-------------------------------------------------------------------------- - [GuidAttribute("23BBD58A-7C59-449b-A93C-43E59EFC080C")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport()] - public interface ICodeClassBase - { - [PreserveSig()] - int GetBaseName(out string pBaseName); - } - - public const ushort CF_HDROP = 15; // winuser.h - public const uint MK_CONTROL = 0x0008; //winuser.h - public const uint MK_SHIFT = 0x0004; - public const int MAX_PATH = 260; // windef.h - - public static bool Succeeded(int hr) - { - return (hr >= 0); - } - - - /// - /// Specifies options for a bitmap image associated with a task item. - /// - public enum VSTASKBITMAP - { - BMP_COMPILE = -1, - BMP_SQUIGGLE = -2, - BMP_COMMENT = -3, - BMP_SHORTCUT = -4, - BMP_USER = -5 - }; - - public const int ILD_NORMAL = 0x0000, - ILD_TRANSPARENT = 0x0001, - ILD_MASK = 0x0010, - ILD_ROP = 0x0040; - - /// - /// Defines the values that are not supported by the System.Environment.SpecialFolder enumeration - /// - [ComVisible(true)] - public enum ExtendedSpecialFolder - { - /// - /// Identical to CSIDL_COMMON_STARTUP - /// - CommonStartup = 0x0018, - - /// - /// Identical to CSIDL_WINDOWS - /// - Windows = 0x0024, - } - - - // APIS - - /// - /// Changes the parent window of the specified child window. - /// - /// Handle to the child window. - /// Handle to the new parent window. If this parameter is NULL, the desktop window becomes the new parent window. - /// A handle to the previous parent window indicates success. NULL indicates failure. - [DllImport("User32", ExactSpelling = true, CharSet = CharSet.Auto)] - public static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent); - - [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] - public static extern bool DestroyIcon(IntPtr handle); - - [DllImport("user32.dll", EntryPoint = "IsDialogMessageA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] - public static extern bool IsDialogMessageA(IntPtr hDlg, ref MSG msg); - - /// - /// Indicates whether the file type is binary or not - /// - /// Full path to the file to check - /// If file isbianry the bitness of the app is indicated by lpBinaryType value. - /// True if the file is binary false otherwise - [DllImport("kernel32.dll")] - public static extern bool GetBinaryType([MarshalAs(UnmanagedType.LPWStr)]string lpApplicationName, out uint lpBinaryType); - - } -} - diff --git a/src/VSNDK.AddIn/TokenProcessor.cs b/src/VSNDK.AddIn/TokenProcessor.cs deleted file mode 100644 index 2855e18c..00000000 --- a/src/VSNDK.AddIn/TokenProcessor.cs +++ /dev/null @@ -1,461 +0,0 @@ -/*************************************************************************** - -Copyright (c) Microsoft Corporation. All rights reserved. -This code is licensed under the Visual Studio SDK license terms. -THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. - -***************************************************************************/ - -using System; -using System.Collections; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Text; - -namespace Microsoft.VisualStudio.Project -{ - /// - /// Replacement type - /// - public enum TokenReplaceType - { - ReplaceString, - ReplaceNumber, - ReplaceCode - } - - /// - /// Contain a number of functions that handle token replacement - /// - public class TokenProcessor - { - #region fields - // Internal fields - private ArrayList tokenlist; - - - #endregion - - #region Initialization - /// - /// Constructor - /// - public TokenProcessor() - { - tokenlist = new ArrayList(); - } - - /// - /// Reset list of TokenReplacer entries - /// - public virtual void Reset() - { - tokenlist.Clear(); - } - - - /// - /// Add a replacement type entry - /// - /// token to replace - /// replacement string - public virtual void AddReplace(string token, string replacement) - { - tokenlist.Add(new ReplacePairToken(token, replacement)); - } - - /// - /// Add replace between entry - /// - /// Start token - /// End token - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "tokenid")] - public virtual void AddReplaceBetween(string tokenid, string tokenStart, string tokenEnd, string replacement) - { - tokenlist.Add(new ReplaceBetweenPairToken(tokenid, tokenStart, tokenEnd, replacement)); - } - - /// - /// Add a deletion entry - /// - /// Token to delete - public virtual void AddDelete(string tokenToDelete) - { - tokenlist.Add(new DeleteToken(tokenToDelete)); - } - #endregion - - #region TokenProcessing - /// - /// For all known token, replace token with correct value - /// - /// File of the source file - /// File of the destination file - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily"), SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Untoken")] - public virtual void UntokenFile(string source, string destination) - { - if(string.IsNullOrEmpty(source)) - throw new ArgumentNullException("source"); - - if(string.IsNullOrEmpty(destination)) - throw new ArgumentNullException("destination"); - - // Make sure that the destination folder exists. - string destinationFolder = Path.GetDirectoryName(destination); - if(!Directory.Exists(destinationFolder)) - { - Directory.CreateDirectory(destinationFolder); - } - - //Open the file. Check to see if the File is binary or text. - // NOTE: This is not correct because GetBinaryType will return true - // only if the file is executable, not if it is a dll, a library or - // any other type of binary file. - - uint binaryType; - if(!NativeMethods.GetBinaryType(source, out binaryType)) - { - Encoding encoding = Encoding.Default; - string buffer = null; - // Create the reader to get the text. Note that we will default to ASCII as - // encoding if the file does not contains a different signature. - using(StreamReader reader = new StreamReader(source, Encoding.ASCII, true)) - { - // Get the content of the file. - buffer = reader.ReadToEnd(); - // Detect the encoding of the source file. Note that we - // can get the encoding only after a read operation is - // performed on the file. - encoding = reader.CurrentEncoding; - } - foreach(object pair in tokenlist) - { - if(pair is DeleteToken) - DeleteTokens(ref buffer, (DeleteToken)pair); - if(pair is ReplaceBetweenPairToken) - ReplaceBetweenTokens(ref buffer, (ReplaceBetweenPairToken)pair); - if(pair is ReplacePairToken) - ReplaceTokens(ref buffer, (ReplacePairToken)pair); - } - File.WriteAllText(destination, buffer, encoding); - } - else - File.Copy(source, destination); - - } - - /// - /// Replaces the tokens in a buffer with the replacement string - /// - /// Buffer to update - /// replacement data - public virtual void ReplaceTokens(ref string buffer, ReplacePairToken tokenToReplace) - { - if (tokenToReplace == null) - { - throw new ArgumentNullException("tokenToReplace"); - } - - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - buffer = buffer.Replace(tokenToReplace.Token, tokenToReplace.Replacement); - } - - /// - /// Deletes the token from the buffer - /// - /// Buffer to update - /// token to delete - public virtual void DeleteTokens(ref string buffer, DeleteToken tokenToDelete) - { - if (tokenToDelete == null) - { - throw new ArgumentNullException("tokenToDelete"); - } - - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - buffer = buffer.Replace(tokenToDelete.StringToDelete, string.Empty); - } - - /// - /// Replaces the token from the buffer between the provided tokens - /// - /// Buffer to update - /// replacement token - public virtual void ReplaceBetweenTokens(ref string buffer, ReplaceBetweenPairToken rpBetweenToken) - { - if (rpBetweenToken == null) - { - throw new ArgumentNullException("rpBetweenToken"); - } - - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - string regularExp = rpBetweenToken.TokenStart + "[^" + rpBetweenToken.TokenIdentifier + "]*" + rpBetweenToken.TokenEnd; - buffer = System.Text.RegularExpressions.Regex.Replace(buffer, regularExp, rpBetweenToken.TokenReplacement); - } - - #endregion - - #region Guid generators - /// - /// Generates a string representation of a guid with the following format: - /// 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 - /// - /// Guid to be generated - /// The guid as string - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] - public string GuidToForm1(Guid value) - { - byte[] GuidBytes = value.ToByteArray(); - StringBuilder ResultingStr = new StringBuilder(80); - - // First 4 bytes - int i = 0; - int Number = 0; - for(i = 0; i < 4; ++i) - { - int CurrentByte = GuidBytes[i]; - Number += CurrentByte << (8 * i); - } - UInt32 FourBytes = (UInt32)Number; - ResultingStr.AppendFormat(CultureInfo.InvariantCulture, "0x{0}", FourBytes.ToString("X", CultureInfo.InvariantCulture)); - - // 2 chunks of 2 bytes - for(int j = 0; j < 2; ++j) - { - Number = 0; - for(int k = 0; k < 2; ++k) - { - int CurrentByte = GuidBytes[i++]; - Number += CurrentByte << (8 * k); - } - UInt16 TwoBytes = (UInt16)Number; - ResultingStr.AppendFormat(CultureInfo.InvariantCulture, ", 0x{0}", TwoBytes.ToString("X", CultureInfo.InvariantCulture)); - } - - // 8 chunks of 1 bytes - for(int j = 0; j < 8; ++j) - { - ResultingStr.AppendFormat(CultureInfo.InvariantCulture, ", 0x{0}", GuidBytes[i++].ToString("X", CultureInfo.InvariantCulture)); - } - - return ResultingStr.ToString(); - } - #endregion - - #region Helper Methods - /// - /// This function will accept a subset of the characters that can create an - /// identifier name: there are other unicode char that can be inside the name, but - /// this function will not allow. By now it can work this way, but when and if the - /// VSIP package will handle also languages different from english, this function - /// must be changed. - /// - /// Character to validate - /// true if successful false otherwise - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "c")] - protected static bool IsValidIdentifierChar(char c) - { - if((c >= 'a') && (c <= 'z')) - { - return true; - } - if((c >= 'A') && (c <= 'Z')) - { - return true; - } - if(c == '_') - { - return true; - } - if((c >= '0') && (c <= '9')) - { - return true; - } - - return false; - } - - /// - /// Verifies if the start character is valid - /// - /// Start character - /// true if successful false otherwise - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "c")] - protected static bool IsValidIdentifierStartChar(char c) - { - if(!IsValidIdentifierChar(c)) - { - return false; - } - if((c >= '0') && (c <= '9')) - { - return false; - } - - return true; - } - - #endregion - - } - - /// - /// Storage classes for replacement tokens - /// - public class ReplacePairToken - { - /// - /// token string - /// - private string token; - - /// - /// Replacement string - /// - private string replacement; - - /// - /// Constructor - /// - /// replaceable token - /// replacement string - public ReplacePairToken(string token, string replacement) - { - this.token = token; - this.replacement = replacement; - } - - /// - /// Token that needs to be replaced - /// - public string Token - { - get { return token; } - } - /// - /// String to replace the token with - /// - public string Replacement - { - get { return replacement; } - } - } - - /// - /// Storage classes for token to be deleted - /// - public class DeleteToken - { - /// - /// String to delete - /// - private string token; - - /// - /// Constructor - /// - /// Deletable token. - public DeleteToken(string token) - { - this.token = token; - } - - /// - /// Token marking the end of the block to delete - /// - public string StringToDelete - { - get { return token; } - } - } - - /// - /// Storage classes for string to be deleted between tokens to be deleted - /// - public class ReplaceBetweenPairToken - { - /// - /// Token start - /// - private string tokenStart; - - /// - /// End token - /// - private string tokenEnd; - - /// - /// Replacement string - /// - private string replacement; - - /// - /// Token identifier string - /// - private string tokenidentifier; - - /// - /// Constructor - /// - /// Start token - /// End Token - /// Replacement string. - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "tokenid")] - public ReplaceBetweenPairToken(string tokenid, string blockStart, string blockEnd, string replacement) - { - tokenStart = blockStart; - tokenEnd = blockEnd; - this.replacement = replacement; - tokenidentifier = tokenid; - } - - /// - /// Token marking the begining of the block to delete - /// - public string TokenStart - { - get { return tokenStart; } - } - - /// - /// Token marking the end of the block to delete - /// - public string TokenEnd - { - get { return tokenEnd; } - } - - /// - /// Token marking the end of the block to delete - /// - public string TokenReplacement - { - get { return replacement; } - } - - /// - /// Token Identifier - /// - public string TokenIdentifier - { - get { return tokenidentifier; } - } - } -} diff --git a/src/VSNDK.AddIn/VSNDK.AddIn.AddIn b/src/VSNDK.AddIn/VSNDK.AddIn.AddIn deleted file mode 100644 index d5b57585..00000000 Binary files a/src/VSNDK.AddIn/VSNDK.AddIn.AddIn and /dev/null differ diff --git a/src/VSNDK.AddIn/VSNDK.AddIn.csproj b/src/VSNDK.AddIn/VSNDK.AddIn.csproj deleted file mode 100644 index 6aeabd70..00000000 --- a/src/VSNDK.AddIn/VSNDK.AddIn.csproj +++ /dev/null @@ -1,186 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30424 - 2.0 - {D4644752-F6B1-47EE-A0FB-1197355A525E} - Library - - - false - VSNDK.AddIn - .\bin\ - - - true - false - .\bin\Debug\ - false - DEBUG;TRACE - 4 - false - - - full - - - true - true - .\bin\Release\ - false - TRACE - 4 - false - VSNDK.AddIn.xml - pdbonly - - - VSNDK.AddIn - - - OnBuildSuccess - - - false - - - - False - - - - - - - - True - - - False - ..\..\..\..\..\..\..\Program Files\Microsoft Visual Studio 2010 SDK\VisualStudioIntegration\Common\Assemblies\v2.0\Microsoft.VisualStudio.Debugger.Interop.10.0.dll - - - False - ..\..\..\..\..\Microsoft.VisualStudio.Debugger.InteropA.dll - - - True - - - - - - - - - - - - Code - - - Code - - - - - - - - - - - - {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2} - 8 - 0 - 0 - primary - False - False - - - {26AD1324-4B7C-44BC-84F8-B86AED45729F} - 10 - 0 - 0 - primary - False - False - - - {1A31287A-4D7D-413E-8E32-3B374931BD89} - 8 - 0 - 0 - primary - False - False - - - {2CE2370E-D744-4936-A090-3FFFE667B0E1} - 9 - 0 - 0 - primary - False - False - - - {1CBA492E-7263-47BB-87FE-639000619B15} - 8 - 0 - 0 - primary - False - False - - - {00020430-0000-0000-C000-000000000046} - 2 - 0 - 0 - primary - False - False - - - - - Always - Designer - - - - - - - - - - - - - $(AssemblyName).dll - $(AssemblyName).pdb - $(AssemblyName).xml - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.AddIn/VSNDK.AddIn.csproj.user b/src/VSNDK.AddIn/VSNDK.AddIn.csproj.user deleted file mode 100644 index ce8d3677..00000000 --- a/src/VSNDK.AddIn/VSNDK.AddIn.csproj.user +++ /dev/null @@ -1,15 +0,0 @@ - - - - Program - C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe - - - - - Program - C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe - - - - \ No newline at end of file diff --git a/src/VSNDK.AddIn/VSNDK.AddIn.xml b/src/VSNDK.AddIn/VSNDK.AddIn.xml deleted file mode 100644 index 007eb575..00000000 --- a/src/VSNDK.AddIn/VSNDK.AddIn.xml +++ /dev/null @@ -1,467 +0,0 @@ - - - - VSNDK.AddIn - - - - - The object for implementing an Add-in. - - 1. Disable the IntelliSense Error Reporting property - 2. ... - To register the addin, copy the VSNDK.AddIn.dll and VSNDK.Addin.AddIn files to - the one of the folders specified by "Add-In File path" in Add-In Security option page. - - - - - Implements the constructor for the Add-in object. Place your initialization code within this method. - - - - - Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded. - - Root object of the host application. - Describes how the Add-in is being loaded. - Object representing this Add-in. - - - - - Implements the OnDisconnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is - being unloaded. - - Describes how the Add-in is being unloaded. - Array of parameters that are host application specific. - - - - - Implements the OnAddInsUpdate method of the IDTExtensibility2 interface. Receives notification when the collection - of Add-ins has changed. - - Array of parameters that are host application specific. - - - - - Implements the OnStartupComplete method of the IDTExtensibility2 interface. Receives notification that the host - application has completed loading. - - Array of parameters that are host application specific. - - - - - Implements the OnBeginShutdown method of the IDTExtensibility2 interface. Receives notification that the host - application is being unloaded. - - Array of parameters that are host application specific. - - - - - - - - - - - - - - - - - - - - - - - - This method takes a file URL and converts it to an absolute path. The trick here is that - if there is a '#' in the path, everything after this is treated as a fragment. So - we need to append the fragment to the end of the path. - - - - - Please use this "approved" method to compare file names. - - - - - Changes the parent window of the specified child window. - - Handle to the child window. - Handle to the new parent window. If this parameter is NULL, the desktop window becomes the new parent window. - A handle to the previous parent window indicates success. NULL indicates failure. - - - - Indicates whether the file type is binary or not - - Full path to the file to check - If file isbianry the bitness of the app is indicated by lpBinaryType value. - True if the file is binary false otherwise - - - - Helper class for setting the text parameters to OLECMDTEXT structures. - - - - - Flags for the OLE command text - - - - No flag - - - The name of the command is required. - - - A description of the status is required. - - - - OLECMDF enums for IOleCommandTarget - - - - - - - -------------------------------------------------------------------------- - ICodeClassBase: - -------------------------------------------------------------------------- - - - - Specifies options for a bitmap image associated with a task item. - - - - - Defines the values that are not supported by the System.Environment.SpecialFolder enumeration - - - - - Identical to CSIDL_COMMON_STARTUP - - - - - Identical to CSIDL_WINDOWS - - - - - Replacement type - - - - - Contain a number of functions that handle token replacement - - - - - Constructor - - - - - Reset list of TokenReplacer entries - - - - - Add a replacement type entry - - token to replace - replacement string - - - - Add replace between entry - - Start token - End token - - - - Add a deletion entry - - Token to delete - - - - For all known token, replace token with correct value - - File of the source file - File of the destination file - - - - Replaces the tokens in a buffer with the replacement string - - Buffer to update - replacement data - - - - Deletes the token from the buffer - - Buffer to update - token to delete - - - - Replaces the token from the buffer between the provided tokens - - Buffer to update - replacement token - - - - Generates a string representation of a guid with the following format: - 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 - - Guid to be generated - The guid as string - - - - This function will accept a subset of the characters that can create an - identifier name: there are other unicode char that can be inside the name, but - this function will not allow. By now it can work this way, but when and if the - VSIP package will handle also languages different from english, this function - must be changed. - - Character to validate - true if successful false otherwise - - - - Verifies if the start character is valid - - Start character - true if successful false otherwise - - - - Storage classes for replacement tokens - - - - - token string - - - - - Replacement string - - - - - Constructor - - replaceable token - replacement string - - - - Token that needs to be replaced - - - - - String to replace the token with - - - - - Storage classes for token to be deleted - - - - - String to delete - - - - - Constructor - - Deletable token. - - - - Token marking the end of the block to delete - - - - - Storage classes for string to be deleted between tokens to be deleted - - - - - Token start - - - - - End token - - - - - Replacement string - - - - - Token identifier string - - - - - Constructor - - Start token - End Token - Replacement string. - - - - Token marking the begining of the block to delete - - - - - Token marking the end of the block to delete - - - - - Token marking the end of the block to delete - - - - - Token Identifier - - - - - - - - - - Run initialization code on first connection of the AddIn. - - Application Object. - Add In Object. - - - - Terminate the AddIn. - - - - - Solution Platform command is shown in the Standard toolbar by default with Visual C++ settings. Add the - command if not in the Standard toolbar. - - - - - Set the DisableErrorReporting property value. - - The property value to set. - - - - New Platform Before Execution Event Handler. - - Command GUID. - Command ID. - Custom IN Object. - Custom OUT Object. - Cancel the default execution of the command. - - - - New Platform After Execution Event Handler. - - Command GUID. - Command ID. - Custom IN Object. - Custom OUT Object. - - - - New Function Breakpoint Before Execution Event Handler. - - Command GUID. - Command ID. - Custom IN Object. - Custom OUT Object. - Cancel the default execution of the command. - - - - New Function Breakpoint After Execution Event Handler. - - Command GUID. - Command ID. - Custom IN Object. - Custom OUT Object. - - - - Add Bar Descriptor to each project. - - - - - Add BlackBerry configurations to the project. - - Represents a project in the integrated development environment. - - - - Responsible for customization of VSShell command events for VSNDK. - - - - - - - Application Object. - - - - - - - - - - - - - Command IDs exposed by VisualStudio. - - - - diff --git a/src/VSNDK.AddIn/VSNDK.csproj b/src/VSNDK.AddIn/VSNDK.csproj deleted file mode 100644 index de75af62..00000000 --- a/src/VSNDK.AddIn/VSNDK.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - Debug - AnyCPU - {00000000-0000-0000-0000-000000000000} - Library - false - ClassLibrary - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.AddIn/VSNDKAddIn.cs b/src/VSNDK.AddIn/VSNDKAddIn.cs deleted file mode 100644 index 814c49d7..00000000 --- a/src/VSNDK.AddIn/VSNDKAddIn.cs +++ /dev/null @@ -1,328 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using EnvDTE80; -using EnvDTE; -using Microsoft.VisualStudio.VCProjectEngine; -using System.Diagnostics; -using System.Globalization; -using Microsoft.VisualStudio.CommandBars; -using Microsoft.VisualStudio.Project; -using Microsoft.Build.Execution; -using System.Xml; -using Microsoft.Win32; -using System.Security.Cryptography; -using System.IO; - -using Extensibility; -using System.Resources; -using System.Reflection; -using System.Text.RegularExpressions; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.OLE.Interop; - -using NameValueCollection = System.Collections.Specialized.NameValueCollection; -using NameValueCollectionHelper = VSNDK.AddIn.NameValueCollectionHelper; -using System.Runtime.InteropServices; - -namespace VSNDK.AddIn -{ - - /// - /// - /// - public class VSNDKAddIn - { - private VSNDKCommandEvents _commandEvents; - private DTE2 _applicationObject; - private EnvDTE.AddIn _addInInstance; - private TokenProcessor tokenProcessor; - - private const string BLACKBERRY = "BlackBerry"; - private const string BLACKBERRYSIMULATOR = "BlackBerrySimulator"; - private const string STANDARD_TOOL_BAR = "Standard"; - private const string SOLUTION_CONFIGURATIONS = "Solution Configurations"; - private const string SOLUTION_PLATFORMS = "Solution Platforms"; - private const string BAR_DESCRIPTOR = "bar-descriptor.xml"; - private const string BAR_DESCRIPTOR_PATH = @"\..\VCWizards\CodeWiz\BlackBerry\BarDescriptor\Templates\1033\"; - -// public static bool isDebugEngineRunning = false; - - public VSNDKAddIn() - { - } - - - /// - /// Run initialization code on first connection of the AddIn. - /// - /// Application Object. - /// Add In Object. - public void Connect(DTE2 appObj, EnvDTE.AddIn addin) - { - /// Initialize External and Internal Variables. - _applicationObject = appObj; - _addInInstance = addin; - - /// Register Command Events - _commandEvents = new VSNDKCommandEvents(appObj); - _commandEvents.RegisterCommand(GuidList.guidVSStd2KString, CommandConstants.cmdidSolutionPlatform, cmdNewPlatform_afterExec, cmdNewPlatform_beforeExec); - _commandEvents.RegisterCommand(GuidList.guidVSStd2KString, CommandConstants.cmdidSolutionCfg, cmdNewPlatform_afterExec, cmdNewPlatform_beforeExec); - _commandEvents.RegisterCommand(GuidList.guidVSDebugGroup, CommandConstants.cmdidDebugBreakatFunction, cmdNewFunctionBreakpoint_afterExec, cmdNewFunctionBreakpoint_beforeExec); - - DisableIntelliSenseErrorReport(true); - CheckSolutionPlatformCommand(); - } - - - /// - /// Terminate the AddIn. - /// - public void Disconnect() - { - DisableIntelliSenseErrorReport(false); - } - - - /// - /// Solution Platform command is shown in the Standard toolbar by default with Visual C++ settings. Add the - /// command if not in the Standard toolbar. - /// - private void CheckSolutionPlatformCommand() - { - DTE dte = (DTE)_applicationObject; - CommandBars commandBars = (CommandBars)dte.CommandBars; - CommandBar standardCommandBar = commandBars[STANDARD_TOOL_BAR]; - int pos = 0; - foreach (CommandBarControl cmd in standardCommandBar.Controls) - { - if (cmd.Caption == SOLUTION_CONFIGURATIONS) - pos = cmd.Index; - if (cmd.Caption == SOLUTION_PLATFORMS) - return; - } - - Command sp = null; - foreach (Command c in dte.Commands) - { - if (c.Guid == GuidList.guidVSStd2KString && c.ID == CommandConstants.cmdidSolutionPlatform) - { - sp = c; - break; - } - } - if (sp != null) - sp.AddControl(standardCommandBar, pos + 1); - } - - - /// - /// Set the DisableErrorReporting property value. - /// - /// The property value to set. - private void DisableIntelliSenseErrorReport(bool disable) - { - DTE dte = _applicationObject as DTE; - EnvDTE.Properties txtEdCpp = dte.get_Properties("TextEditor", "C/C++ Specific"); - EnvDTE.Property prop = txtEdCpp.Item("DisableErrorReporting"); - if (prop != null) - prop.Value = disable; - } - - - /// - /// New Platform Before Execution Event Handler. - /// - /// Command GUID. - /// Command ID. - /// Custom IN Object. - /// Custom OUT Object. - /// Cancel the default execution of the command. - private void cmdNewPlatform_beforeExec(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault) - { - /// Add Code Here - } - - - /// - /// New Platform After Execution Event Handler. - /// - /// Command GUID. - /// Command ID. - /// Custom IN Object. - /// Custom OUT Object. - private void cmdNewPlatform_afterExec(string Guid, int ID, object CustomIn, object CustomOut) - { - AddBarDescriptor(); - } - - - /// - /// New Function Breakpoint Before Execution Event Handler. - /// - /// Command GUID. - /// Command ID. - /// Custom IN Object. - /// Custom OUT Object. - /// Cancel the default execution of the command. - private void cmdNewFunctionBreakpoint_beforeExec(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault) - { - /// Add Code Here - } - - - /// - /// New Function Breakpoint After Execution Event Handler. - /// - /// Command GUID. - /// Command ID. - /// Custom IN Object. - /// Custom OUT Object. - private void cmdNewFunctionBreakpoint_afterExec(string Guid, int ID, object CustomIn, object CustomOut) - { - Breakpoint functionBP = _applicationObject.Debugger.Breakpoints.Item(_applicationObject.Debugger.Breakpoints.Count); - - if (functionBP != null) - { - if ((functionBP.FunctionColumnOffset != 1) || (functionBP.FunctionLineOffset != 1)) - { - System.Windows.Forms.MessageBox.Show("The breakpoint cannot be set. Function breakpoints are only supported on the first line.", "Microsoft Visual Studio", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); - functionBP.Delete(); - } - } - } - - - /// - /// Add Bar Descriptor to each project. - /// - private void AddBarDescriptor() - { - try - { - DTE dte = _applicationObject as DTE; - Projects projs = dte.Solution.Projects; - - List projList = new List(); - foreach (Project proj in projs) - { - projList.Add(proj); - } - - while (projList.Count > 0) - { - Project proj = projList.ElementAt(0); - projList.RemoveAt(0); - - Configuration config; - Property prop; - try - { - config = proj.ConfigurationManager.ActiveConfiguration; - prop = config.Properties.Item("ConfigurationType"); - } - catch - { - config = null; - prop = null; - } - - if (prop == null) - { - if (proj.ProjectItems != null) - { - foreach (ProjectItem projItem in proj.ProjectItems) - { - if (projItem.SubProject != null) - projList.Add(projItem.SubProject); - } - } - continue; - } - - if (Convert.ToInt16(prop.Value) != Convert.ToInt16(ConfigurationTypes.typeApplication)) - continue; - - if (config.PlatformName != BLACKBERRY && config.PlatformName != BLACKBERRYSIMULATOR) - continue; - - ProjectItem baritem = proj.ProjectItems.Item(BAR_DESCRIPTOR); - string n = proj.Name; - if (baritem == null) - { - tokenProcessor = new TokenProcessor(); - Debug.WriteLine("Add bar descriptor file to the project"); - string templatePath = dte.Solution.ProjectItemsTemplatePath(proj.Kind); - templatePath += BAR_DESCRIPTOR_PATH + BAR_DESCRIPTOR; - tokenProcessor.AddReplace(@"[!output PROJECT_NAME]", proj.Name); - string destination = System.IO.Path.GetFileName(templatePath); - - // Remove directory used in previous versions of this plug-in. - string folder = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(proj.FullName), proj.Name + "_barDescriptor"); - if (Directory.Exists(folder)) - { - try - { - Directory.Delete(folder); - } - catch (Exception e) - { - } - } - - folder = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(proj.FullName), "BlackBerry-" + proj.Name); - System.IO.Directory.CreateDirectory(folder); - destination = System.IO.Path.Combine(folder, destination); - tokenProcessor.UntokenFile(templatePath, destination); - ProjectItem projectitem = proj.ProjectItems.AddFromFile(destination); - } - } - } - catch (Exception e) - { - Debug.WriteLine(e.Message); - } - } - - - /// - /// Add BlackBerry configurations to the project. - /// - /// Represents a project in the integrated development environment. - private void AddBlackBerryConfigurations(Project proj) - { - try - { - ConfigurationManager mgr = proj.ConfigurationManager; - Configurations cfgs = mgr.AddPlatform(BLACKBERRY, "Win32", true); - mgr.DeletePlatform("Win32"); - mgr.AddConfigurationRow("Device-Debug", "Debug", true); - mgr.AddConfigurationRow("Simulator", "Debug", true); - mgr.DeleteConfigurationRow("Debug"); - mgr.AddConfigurationRow("Device-Release", "Release", true); - mgr.DeleteConfigurationRow("Release"); - } - catch (Exception e) - { - Debug.WriteLine(e.Message); - } - } - } -} diff --git a/src/VSNDK.AddIn/VSNDKCommandEvents.cs b/src/VSNDK.AddIn/VSNDKCommandEvents.cs deleted file mode 100644 index 66e15d4c..00000000 --- a/src/VSNDK.AddIn/VSNDKCommandEvents.cs +++ /dev/null @@ -1,64 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using EnvDTE; -using Microsoft.VisualStudio.Shell; -using EnvDTE80; - -namespace VSNDK.AddIn -{ - - /// - /// Responsible for customization of VSShell command events for VSNDK. - /// - public class VSNDKCommandEvents - { - private DTE2 dte; - private Dictionary cmdEvents; - - - /// - /// - /// - /// Application Object. - public VSNDKCommandEvents(DTE2 dte) - { - this.dte = dte; - cmdEvents = new Dictionary(); - } - - - /// - /// - /// - /// - /// - /// - /// - public void RegisterCommand( string guid, int cmdId, _dispCommandEvents_AfterExecuteEventHandler afterHandler, _dispCommandEvents_BeforeExecuteEventHandler beforeHandler) - { - cmdEvents[cmdId] = dte.Events.get_CommandEvents(guid, cmdId); - CommandEvents e = cmdEvents[cmdId]; - if ( e != null) - { - e.AfterExecute += afterHandler; - e.BeforeExecute += beforeHandler; - } - } - } -} diff --git a/src/VSNDK.AddIn/VSNDKConstants.cs b/src/VSNDK.AddIn/VSNDKConstants.cs deleted file mode 100644 index c27674dd..00000000 --- a/src/VSNDK.AddIn/VSNDKConstants.cs +++ /dev/null @@ -1,44 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace VSNDK.AddIn -{ - /// - /// Command IDs exposed by VisualStudio. - /// - public static class CommandConstants - { - public const int cmdidAddSolutionSCC = 21016; - public const int cmdidUndoCheckoutSCC = 21009; - public const int cmdidGetLatestVersionSCC = 21011; - public const int cmdidGetSCC = 21501; - public const int cmdidViewHistorySCC = 21508; - public const int cmdidStartDebug = 295; - public const int cmdidStartDebugContext = 356; - public const int cmdidRestartDebug = 296; - public const int cmdidStopDebug = 179; - public const int cmdidPreviewInBrowser = 334; - public const int cmdidBrowseWith = 336; - public const int cmdidStartNoDebug = 368; - public const int cmdidSolutionCfg = 684; - public const int cmdidSolutionPlatform = 1990; - public const int cmdidSolutionPlatformGetList = 1991; - public const int cmdidDebugBreakatFunction = 311; - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Definitions/AD7Enums.cs b/src/VSNDK.DebugEngine/AD7.Definitions/AD7Enums.cs deleted file mode 100644 index c92f031b..00000000 --- a/src/VSNDK.DebugEngine/AD7.Definitions/AD7Enums.cs +++ /dev/null @@ -1,100 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - - -namespace VSNDK.DebugEngine -{ - /// - /// Flags passed by the debugger to the engine to describe the desired format and execution options for properties - /// (locals, arguments, etc...) - /// - public enum DEBUGPROP_INFO_FLAGS - { - DEBUGPROP_INFO_FULLNAME = 0x00000001, - DEBUGPROP_INFO_NAME = 0x00000002, - DEBUGPROP_INFO_TYPE = 0x00000004, - DEBUGPROP_INFO_VALUE = 0x00000008, - DEBUGPROP_INFO_ATTRIB = 0x00000010, - DEBUGPROP_INFO_PROP = 0x00000020, - - DEBUGPROP_INFO_VALUE_AUTOEXPAND = 0x00010000, - DEBUGPROP_INFO_NOFUNCEVAL = 0x00020000, // Tell EE not to perform ANY type of func-eval. - DEBUGPROP_INFO_VALUE_RAW = 0x00040000, // Tell EE not to return any beautified values or members. - DEBUGPROP_INFO_VALUE_NO_TOSTRING = 0x00080000, // Tell EE not to return any special synthesized values (ToString() for instance). - DEBUGPROP_INFO_NO_NONPUBLIC_MEMBERS = 0x00100000, // Tell EE to return non-public members for non-user objects. - - DEBUGPROP_INFO_NONE = 0x00000000, - DEBUGPROP_INFO_STANDARD = DEBUGPROP_INFO_ATTRIB | DEBUGPROP_INFO_NAME | DEBUGPROP_INFO_TYPE | DEBUGPROP_INFO_VALUE, - } - - public static class DBG_ATTRIB_FLAGS - { - public static readonly ulong DBG_ATTRIB_NONE = 0x0000000000000000; - public static readonly ulong DBG_ATTRIB_ALL = 0x00000000ffffffff; - - // Attributes about the object itself - public static readonly ulong DBG_ATTRIB_OBJ_IS_EXPANDABLE = 0x0000000000000001; - public static readonly ulong DBG_ATTRIB_OBJ_HAS_ID = 0x0000000000000002; - public static readonly ulong DBG_ATTRIB_OBJ_CAN_HAVE_ID = 0x0000000000000004; - - // Attributes about the value of the object - public static readonly ulong DBG_ATTRIB_VALUE_READONLY = 0x0000000000000010; - public static readonly ulong DBG_ATTRIB_VALUE_ERROR = 0x0000000000000020; - public static readonly ulong DBG_ATTRIB_VALUE_SIDE_EFFECT= 0x0000000000000040; - public static readonly ulong DBG_ATTRIB_OVERLOADED_CONTAINER = 0x0000000000000080; - public static readonly ulong DBG_ATTRIB_VALUE_BOOLEAN = 0x0000000000000100; - public static readonly ulong DBG_ATTRIB_VALUE_BOOLEAN_TRUE = 0x0000000000000200; - public static readonly ulong DBG_ATTRIB_VALUE_INVALID = 0x0000000000000400; - public static readonly ulong DBG_ATTRIB_VALUE_NAT = 0x0000000000000800; - public static readonly ulong DBG_ATTRIB_VALUE_AUTOEXPANDED = 0x0000000000001000; - public static readonly ulong DBG_ATTRIB_VALUE_TIMEOUT = 0x0000000000002000; - public static readonly ulong DBG_ATTRIB_VALUE_RAW_STRING = 0x0000000000004000; - public static readonly ulong DBG_ATTRIB_VALUE_CUSTOM_VIEWER = 0x0000000000008000; - - // Attributes about field access types for the object - public static readonly ulong DBG_ATTRIB_ACCESS_NONE = 0x0000000000010000; - public static readonly ulong DBG_ATTRIB_ACCESS_PUBLIC = 0x0000000000020000; - public static readonly ulong DBG_ATTRIB_ACCESS_PRIVATE = 0x0000000000040000; - public static readonly ulong DBG_ATTRIB_ACCESS_PROTECTED = 0x0000000000080000; - public static readonly ulong DBG_ATTRIB_ACCESS_FINAL = 0x0000000000100000; - public static readonly ulong DBG_ATTRIB_ACCESS_ALL = 0x00000000001f0000; - - // Attributes for the storage types of the object - public static readonly ulong DBG_ATTRIB_STORAGE_NONE = 0x0000000001000000; - public static readonly ulong DBG_ATTRIB_STORAGE_GLOBAL = 0x0000000002000000; - public static readonly ulong DBG_ATTRIB_STORAGE_STATIC = 0x0000000004000000; - public static readonly ulong DBG_ATTRIB_STORAGE_REGISTER = 0x0000000008000000; - public static readonly ulong DBG_ATTRIB_STORAGE_ALL= 0x000000000f000000; - - // Attributes for the type modifiers on the object - public static readonly ulong DBG_ATTRIB_TYPE_NONE = 0x0000000100000000; - public static readonly ulong DBG_ATTRIB_TYPE_VIRTUAL = 0x0000000200000000; - public static readonly ulong DBG_ATTRIB_TYPE_CONSTANT = 0x0000000400000000; - public static readonly ulong DBG_ATTRIB_TYPE_SYNCHRONIZED = 0x0000000800000000; - public static readonly ulong DBG_ATTRIB_TYPE_VOLATILE = 0x0000001000000000; - public static readonly ulong DBG_ATTRIB_TYPE_ALL = 0x0000001f00000000; - - // Attributes that describe the type of object - public static readonly ulong DBG_ATTRIB_DATA = 0x0000010000000000; - public static readonly ulong DBG_ATTRIB_METHOD = 0x0000020000000000; - public static readonly ulong DBG_ATTRIB_PROPERTY = 0x0000040000000000; - public static readonly ulong DBG_ATTRIB_CLASS = 0x0000080000000000; - public static readonly ulong DBG_ATTRIB_BASECLASS = 0x0000100000000000; - public static readonly ulong DBG_ATTRIB_INTERFACE = 0x0000200000000000; - public static readonly ulong DBG_ATTRIB_INNERCLASS = 0x0000400000000000; - public static readonly ulong DBG_ATTRIB_MOSTDERIVED = 0x0000800000000000; - public static readonly ulong DBG_ATTRIB_CHILD_ALL = 0x0000ff0000000000; - - } -} \ No newline at end of file diff --git a/src/VSNDK.DebugEngine/AD7.Definitions/AD7Guids.cs b/src/VSNDK.DebugEngine/AD7.Definitions/AD7Guids.cs deleted file mode 100644 index ffea3fbe..00000000 --- a/src/VSNDK.DebugEngine/AD7.Definitions/AD7Guids.cs +++ /dev/null @@ -1,70 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; - -namespace VSNDK.DebugEngine -{ - /// - /// These are well-known guids in AD7. Most of these are used to specify filters in what the debugger UI is requesting. - /// For instance, guidFilterLocals can be passed to IDebugStackFrame2::EnumProperties to specify only locals are requested. - /// - static class AD7Guids - { - static private Guid _guidFilterRegisters = new Guid("223ae797-bd09-4f28-8241-2763bdc5f713"); - static public Guid guidFilterRegisters - { - get { return _guidFilterRegisters; } - } - - static private Guid _guidFilterLocals = new Guid("b200f725-e725-4c53-b36a-1ec27aef12ef"); - static public Guid guidFilterLocals - { - get { return _guidFilterLocals; } - } - - static private Guid _guidFilterAllLocals = new Guid("196db21f-5f22-45a9-b5a3-32cddb30db06"); - static public Guid guidFilterAllLocals - { - get { return _guidFilterAllLocals; } - } - - static private Guid _guidFilterArgs = new Guid("804bccea-0475-4ae7-8a46-1862688ab863"); - static public Guid guidFilterArgs - { - get { return _guidFilterArgs; } - } - - static private Guid _guidFilterLocalsPlusArgs = new Guid("e74721bb-10c0-40f5-807f-920d37f95419"); - static public Guid guidFilterLocalsPlusArgs - { - get { return _guidFilterLocalsPlusArgs; } - } - - static private Guid _guidFilterAllLocalsPlusArgs = new Guid("939729a8-4cb0-4647-9831-7ff465240d5f"); - static public Guid guidFilterAllLocalsPlusArgs - { - get { return _guidFilterAllLocalsPlusArgs; } - } - - // Language guid for C++. Used when the language for a document context or a stack frame is requested. - static private Guid _guidLanguageCpp = new Guid("3a12d0b7-c26c-11d0-b442-00a0244a1dd2"); - static public Guid guidLanguageCpp - { - get { return _guidLanguageCpp; } - } - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Definitions/AD7Hresult.cs b/src/VSNDK.DebugEngine/AD7.Definitions/AD7Hresult.cs deleted file mode 100644 index 316b5488..00000000 --- a/src/VSNDK.DebugEngine/AD7.Definitions/AD7Hresult.cs +++ /dev/null @@ -1,254 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -namespace VSNDK.DebugEngine -{ - /// - /// These are managed definitions of the well-known AD7 HRESULTS. Defined in msdbg.idl. - /// - static public class AD7_HRESULT - { - public const int S_ATTACH_DEFERRED=unchecked((int)0x40004); - public const int S_ATTACH_IGNORED=unchecked((int)0x40005); - public const int S_JIT_USERCANCELLED=unchecked((int)0x400B0); - public const int S_JIT_NOT_REG_FOR_ENGINE=unchecked((int)0x400B5); - public const int S_TERMINATE_PROCESSES_STILL_DETACHING=unchecked((int)0x400C0); - public const int S_TERMINATE_PROCESSES_STILL_TERMINATING=unchecked((int)0x400C1); - public const int S_ENC_SETIP_REQUIRES_CONTINUE=unchecked((int)0x40106); - public const int S_WEBDBG_UNABLE_TO_DIAGNOSE=unchecked((int)0x40120); - public const int S_WEBDBG_DEBUG_VERB_BLOCKED=unchecked((int)0x40121); - public const int S_ASP_USER_ACCESS_DENIED=unchecked((int)0x40125); - public const int S_JMC_LIMITED_SUPPORT=unchecked((int)0x40146); - public const int S_CANNOT_REMAP_IN_EXCEPTION=unchecked((int)0x40150); - public const int S_CANNOT_REMAP_NOT_AT_SEQUENCE_POINT=unchecked((int)0x40151); - public const int S_GETPARENT_NO_PARENT=unchecked((int)0x40531); - public const int S_GETDERIVEDMOST_NO_DERIVED_MOST=unchecked((int)0x40541); - public const int S_GETMEMORYBYTES_NO_MEMORY_BYTES=unchecked((int)0x40551); - public const int S_GETMEMORYCONTEXT_NO_MEMORY_CONTEXT=unchecked((int)0x40561); - public const int S_GETSIZE_NO_SIZE=unchecked((int)0x40571); - public const int S_GETEXTENDEDINFO_NO_EXTENDEDINFO=unchecked((int)0x40591); - public const int S_ASYNC_STOP=unchecked((int)0x40B02); - public const int E_ATTACH_DEBUGGER_ALREADY_ATTACHED=unchecked((int)0x80040001); - public const int E_ATTACH_DEBUGGEE_PROCESS_SECURITY_VIOLATION=unchecked((int)0x80040002); - public const int E_ATTACH_CANNOT_ATTACH_TO_DESKTOP=unchecked((int)0x80040003); - public const int E_LAUNCH_NO_INTEROP=unchecked((int)0x80040005); - public const int E_LAUNCH_DEBUGGING_NOT_POSSIBLE=unchecked((int)0x80040006); - public const int E_LAUNCH_KERNEL_DEBUGGER_ENABLED=unchecked((int)0x80040007); - public const int E_LAUNCH_KERNEL_DEBUGGER_PRESENT=unchecked((int)0x80040008); - public const int E_INTEROP_NOT_SUPPORTED=unchecked((int)0x80040009); - public const int E_TOO_MANY_PROCESSES=unchecked((int)0x8004000A); - public const int E_MSHTML_SCRIPT_DEBUGGING_DISABLED=unchecked((int)0x8004000B); - public const int E_SCRIPT_PDM_NOT_REGISTERED=unchecked((int)0x8004000C); - public const int E_DE_CLR_DBG_SERVICES_NOT_INSTALLED=unchecked((int)0x8004000D); - public const int E_ATTACH_NO_CLR_PROGRAMS=unchecked((int)0x8004000E); - public const int E_REMOTE_SERVER_CLOSED=unchecked((int)0x80040010); - public const int E_CLR_NOT_SUPPORTED=unchecked((int)0x80040016); - public const int E_64BIT_CLR_NOT_SUPPORTED=unchecked((int)0x80040017); - public const int E_CANNOT_MIX_MINDUMP_DEBUGGING=unchecked((int)0x80040018); - public const int E_DEBUG_ENGINE_NOT_REGISTERED=unchecked((int)0x80040019); - public const int E_LAUNCH_SXS_ERROR=unchecked((int)0x8004001A); - public const int E_REMOTE_SERVER_DOES_NOT_EXIST=unchecked((int)0x80040020); - public const int E_REMOTE_SERVER_ACCESS_DENIED=unchecked((int)0x80040021); - public const int E_REMOTE_SERVER_MACHINE_DOES_NOT_EXIST=unchecked((int)0x80040022); - public const int E_DEBUGGER_NOT_REGISTERED_PROPERLY=unchecked((int)0x80040023); - public const int E_FORCE_GUEST_MODE_ENABLED=unchecked((int)0x80040024); - public const int E_GET_IWAM_USER_FAILURE=unchecked((int)0x80040025); - public const int E_REMOTE_SERVER_INVALID_NAME=unchecked((int)0x80040026); - public const int E_REMOTE_SERVER_MACHINE_NO_DEFAULT=unchecked((int)0x80040027); - public const int E_AUTO_LAUNCH_EXEC_FAILURE=unchecked((int)0x80040028); - public const int E_SERVICE_ACCESS_DENIED=unchecked((int)0x80040029); - public const int E_SERVICE_ACCESS_DENIED_ON_CALLBACK=unchecked((int)0x8004002A); - public const int E_REMOTE_COMPONENTS_NOT_REGISTERED=unchecked((int)0x8004002B); - public const int E_DCOM_ACCESS_DENIED=unchecked((int)0x8004002C); - public const int E_SHARE_LEVEL_ACCESS_CONTROL_ENABLED=unchecked((int)0x8004002D); - public const int E_WORKGROUP_REMOTE_LOGON_FAILURE=unchecked((int)0x8004002E); - public const int E_WINAUTH_CONNECT_NOT_SUPPORTED=unchecked((int)0x8004002F); - public const int E_EVALUATE_BUSY_WITH_EVALUATION=unchecked((int)0x80040030); - public const int E_EVALUATE_TIMEOUT=unchecked((int)0x80040031); - public const int E_INTEROP_NOT_SUPPORTED_FOR_THIS_CLR=unchecked((int)0x80040032); - public const int E_CLR_INCOMPATIBLE_PROTOCOL=unchecked((int)0x80040033); - public const int E_CLR_CANNOT_DEBUG_FIBER_PROCESS=unchecked((int)0x80040034); - public const int E_PROCESS_OBJECT_ACCESS_DENIED=unchecked((int)0x80040035); - public const int E_PROCESS_TOKEN_ACCESS_DENIED=unchecked((int)0x80040036); - public const int E_PROCESS_TOKEN_ACCESS_DENIED_NO_TS=unchecked((int)0x80040037); - public const int E_OPERATION_REQUIRES_ELEVATION=unchecked((int)0x80040038); - public const int E_ATTACH_REQUIRES_ELEVATION=unchecked((int)0x80040039); - public const int E_MEMORY_NOTSUPPORTED=unchecked((int)0x80040040); - public const int E_DISASM_NOTSUPPORTED=unchecked((int)0x80040041); - public const int E_DISASM_BADADDRESS=unchecked((int)0x80040042); - public const int E_DISASM_NOTAVAILABLE=unchecked((int)0x80040043); - public const int E_BP_DELETED=unchecked((int)0x80040060); - public const int E_PROCESS_DESTROYED=unchecked((int)0x80040070); - public const int E_PROCESS_DEBUGGER_IS_DEBUGGEE=unchecked((int)0x80040071); - public const int E_TERMINATE_FORBIDDEN=unchecked((int)0x80040072); - public const int E_THREAD_DESTROYED=unchecked((int)0x80040075); - public const int E_PORTSUPPLIER_NO_PORT=unchecked((int)0x80040080); - public const int E_PORT_NO_REQUEST=unchecked((int)0x80040090); - public const int E_COMPARE_CANNOT_COMPARE=unchecked((int)0x800400A0); - public const int E_JIT_INVALID_PID=unchecked((int)0x800400B1); - public const int E_JIT_VSJITDEBUGGER_NOT_REGISTERED=unchecked((int)0x800400B3); - public const int E_JIT_APPID_NOT_REGISTERED=unchecked((int)0x800400B4); - public const int E_SESSION_TERMINATE_DETACH_FAILED=unchecked((int)0x800400C2); - public const int E_SESSION_TERMINATE_FAILED=unchecked((int)0x800400C3); - public const int E_DETACH_NO_PROXY=unchecked((int)0x800400D0); - public const int E_DETACH_TS_UNSUPPORTED=unchecked((int)0x800400E0); - public const int E_DETACH_IMPERSONATE_FAILURE=unchecked((int)0x800400F0); - public const int E_CANNOT_SET_NEXT_STATEMENT_ON_NONLEAF_FRAME=unchecked((int)0x80040100); - public const int E_TARGET_FILE_MISMATCH=unchecked((int)0x80040101); - public const int E_IMAGE_NOT_LOADED=unchecked((int)0x80040102); - public const int E_FIBER_NOT_SUPPORTED=unchecked((int)0x80040103); - public const int E_CANNOT_SETIP_TO_DIFFERENT_FUNCTION=unchecked((int)0x80040104); - public const int E_CANNOT_SET_NEXT_STATEMENT_ON_EXCEPTION=unchecked((int)0x80040105); - public const int E_ENC_SETIP_REQUIRES_CONTINUE=unchecked((int)0x80040107); - public const int E_CANNOT_SET_NEXT_STATEMENT_INTO_FINALLY=unchecked((int)0x80040108); - public const int E_CANNOT_SET_NEXT_STATEMENT_OUT_OF_FINALLY=unchecked((int)0x80040109); - public const int E_CANNOT_SET_NEXT_STATEMENT_INTO_CATCH=unchecked((int)0x8004010A); - public const int E_CANNOT_SET_NEXT_STATEMENT_GENERAL=unchecked((int)0x8004010B); - public const int E_CANNOT_SET_NEXT_STATEMENT_INTO_OR_OUT_OF_FILTER=unchecked((int)0x8004010C); - public const int E_ASYNCBREAK_NO_PROGRAMS=unchecked((int)0x80040110); - public const int E_ASYNCBREAK_DEBUGGEE_NOT_INITIALIZED=unchecked((int)0x80040111); - public const int E_WEBDBG_DEBUG_VERB_BLOCKED=unchecked((int)0x80040121); - public const int E_ASP_USER_ACCESS_DENIED=unchecked((int)0x80040125); - public const int E_AUTO_ATTACH_NOT_REGISTERED=unchecked((int)0x80040126); - public const int E_AUTO_ATTACH_DCOM_ERROR=unchecked((int)0x80040127); - public const int E_AUTO_ATTACH_NOT_SUPPORTED=unchecked((int)0x80040128); - public const int E_AUTO_ATTACH_CLASSNOTREG=unchecked((int)0x80040129); - public const int E_CANNOT_CONTINUE_DURING_PENDING_EXPR_EVAL=unchecked((int)0x80040130); - public const int E_REMOTE_REDIRECTION_UNSUPPORTED=unchecked((int)0x80040135); - public const int E_INVALID_WORKING_DIRECTORY=unchecked((int)0x80040136); - public const int E_LAUNCH_FAILED_WITH_ELEVATION=unchecked((int)0x80040137); - public const int E_LAUNCH_ELEVATION_REQUIRED=unchecked((int)0x80040138); - public const int E_CANNOT_FIND_INTERNET_EXPLORER=unchecked((int)0x80040139); - public const int E_EXCEPTION_CANNOT_BE_INTERCEPTED=unchecked((int)0x80040140); - public const int E_EXCEPTION_CANNOT_UNWIND_ABOVE_CALLBACK=unchecked((int)0x80040141); - public const int E_INTERCEPT_CURRENT_EXCEPTION_NOT_SUPPORTED=unchecked((int)0x80040142); - public const int E_INTERCEPT_CANNOT_UNWIND_LASTCHANCE_INTEROP=unchecked((int)0x80040143); - public const int E_JMC_CANNOT_SET_STATUS=unchecked((int)0x80040145); - public const int E_DESTROYED=unchecked((int)0x80040201); - public const int E_REMOTE_NOMSVCMON=unchecked((int)0x80040202); - public const int E_REMOTE_BADIPADDRESS=unchecked((int)0x80040203); - public const int E_REMOTE_MACHINEDOWN=unchecked((int)0x80040204); - public const int E_REMOTE_MACHINEUNSPECIFIED=unchecked((int)0x80040205); - public const int E_CRASHDUMP_ACTIVE=unchecked((int)0x80040206); - public const int E_ALL_THREADS_SUSPENDED=unchecked((int)0x80040207); - public const int E_LOAD_DLL_TL=unchecked((int)0x80040208); - public const int E_LOAD_DLL_SH=unchecked((int)0x80040209); - public const int E_LOAD_DLL_EM=unchecked((int)0x8004020A); - public const int E_LOAD_DLL_EE=unchecked((int)0x8004020B); - public const int E_LOAD_DLL_DM=unchecked((int)0x8004020C); - public const int E_LOAD_DLL_MD=unchecked((int)0x8004020D); - public const int E_IOREDIR_BADFILE=unchecked((int)0x8004020E); - public const int E_IOREDIR_BADSYNTAX=unchecked((int)0x8004020F); - public const int E_REMOTE_BADVERSION=unchecked((int)0x80040210); - public const int E_CRASHDUMP_UNSUPPORTED=unchecked((int)0x80040211); - public const int E_REMOTE_BAD_CLR_VERSION=unchecked((int)0x80040212); - public const int E_UNSUPPORTED_BINARY=unchecked((int)0x80040215); - public const int E_DEBUGGEE_BLOCKED=unchecked((int)0x80040216); - public const int E_REMOTE_NOUSERMSVCMON=unchecked((int)0x80040217); - public const int E_STEP_WIN9xSYSCODE=unchecked((int)0x80040218); - public const int E_INTEROP_ORPC_INIT=unchecked((int)0x80040219); - public const int E_CANNOT_DEBUG_WIN32=unchecked((int)0x8004021B); - public const int E_CANNOT_DEBUG_WIN64=unchecked((int)0x8004021C); - public const int E_MINIDUMP_READ_WIN9X=unchecked((int)0x8004021D); - public const int E_CROSS_TSSESSION_ATTACH=unchecked((int)0x8004021E); - public const int E_STEP_BP_SET_FAILED=unchecked((int)0x8004021F); - public const int E_LOAD_DLL_TL_INCORRECT_VERSION=unchecked((int)0x80040220); - public const int E_LOAD_DLL_DM_INCORRECT_VERSION=unchecked((int)0x80040221); - public const int E_REMOTE_NOMSVCMON_PIPE=unchecked((int)0x80040222); - public const int E_LOAD_DLL_DIA=unchecked((int)0x80040223); - public const int E_DUMP_CORRUPTED=unchecked((int)0x80040224); - public const int E_INTEROP_WIN64=unchecked((int)0x80040225); - public const int E_CRASHDUMP_DEPRECATED=unchecked((int)0x80040227); - public const int E_DEVICEBITS_NOT_SIGNED=unchecked((int)0x80040401); - public const int E_ATTACH_NOT_ENABLED=unchecked((int)0x80040402); - public const int E_REMOTE_DISCONNECT=unchecked((int)0x80040403); - public const int E_BREAK_ALL_FAILED=unchecked((int)0x80040404); - public const int E_DEVICE_ACCESS_DENIED_SELECT_YES=unchecked((int)0x80040405); - public const int E_DEVICE_ACCESS_DENIED=unchecked((int)0x80040406); - public const int E_DEVICE_CONNRESET=unchecked((int)0x80040407); - public const int E_BAD_NETCF_VERSION=unchecked((int)0x80040408); - public const int E_REFERENCE_NOT_VALID=unchecked((int)0x80040501); - public const int E_PROPERTY_NOT_VALID=unchecked((int)0x80040511); - public const int E_SETVALUE_VALUE_CANNOT_BE_SET=unchecked((int)0x80040521); - public const int E_SETVALUE_VALUE_IS_READONLY=unchecked((int)0x80040522); - public const int E_SETVALUEASREFERENCE_NOTSUPPORTED=unchecked((int)0x80040523); - public const int E_CANNOT_GET_UNMANAGED_MEMORY_CONTEXT=unchecked((int)0x80040561); - public const int E_GETREFERENCE_NO_REFERENCE=unchecked((int)0x80040581); - public const int E_CODE_CONTEXT_OUT_OF_SCOPE=unchecked((int)0x800405A1); - public const int E_INVALID_SESSIONID=unchecked((int)0x800405A2); - public const int E_SERVER_UNAVAILABLE_ON_CALLBACK=unchecked((int)0x800405A3); - public const int E_ACCESS_DENIED_ON_CALLBACK=unchecked((int)0x800405A4); - public const int E_UNKNOWN_AUTHN_SERVICE_ON_CALLBACK=unchecked((int)0x800405A5); - public const int E_NO_SESSION_AVAILABLE=unchecked((int)0x800405A6); - public const int E_CLIENT_NOT_LOGGED_ON=unchecked((int)0x800405A7); - public const int E_OTHER_USERS_SESSION=unchecked((int)0x800405A8); - public const int E_USER_LEVEL_ACCESS_CONTROL_REQUIRED=unchecked((int)0x800405A9); - public const int E_SCRIPT_CLR_EE_DISABLED=unchecked((int)0x800405B0); - public const int E_HTTP_SERVERERROR=unchecked((int)0x80040700); - public const int E_HTTP_UNAUTHORIZED=unchecked((int)0x80040701); - public const int E_HTTP_SENDREQUEST_FAILED=unchecked((int)0x80040702); - public const int E_HTTP_FORBIDDEN=unchecked((int)0x80040703); - public const int E_HTTP_NOT_SUPPORTED=unchecked((int)0x80040704); - public const int E_HTTP_NO_CONTENT=unchecked((int)0x80040705); - public const int E_HTTP_NOT_FOUND=unchecked((int)0x80040706); - public const int E_HTTP_BAD_REQUEST=unchecked((int)0x80040707); - public const int E_HTTP_ACCESS_DENIED=unchecked((int)0x80040708); - public const int E_HTTP_CONNECT_FAILED=unchecked((int)0x80040709); - public const int E_HTTP_EXCEPTION=unchecked((int)0x8004070A); - public const int E_HTTP_TIMEOUT=unchecked((int)0x8004070B); - public const int E_64BIT_COMPONENTS_NOT_INSTALLED=unchecked((int)0x80040750); - public const int E_UNMARSHAL_SERVER_FAILED=unchecked((int)0x80040751); - public const int E_UNMARSHAL_CALLBACK_FAILED=unchecked((int)0x80040752); - public const int E_RPC_REQUIRES_AUTHENTICATION=unchecked((int)0x80040755); - public const int E_LOGON_FAILURE_ON_CALLBACK=unchecked((int)0x80040756); - public const int E_REMOTE_SERVER_UNAVAILABLE=unchecked((int)0x80040757); - public const int E_FIREWALL_USER_CANCELED=unchecked((int)0x80040758); - public const int E_REMOTE_CREDENTIALS_PROHIBITED=unchecked((int)0x80040759); - public const int E_FIREWALL_NO_EXCEPTIONS=unchecked((int)0x8004075A); - public const int E_FIREWALL_CANNOT_OPEN_APPLICATION=unchecked((int)0x8004075B); - public const int E_FIREWALL_CANNOT_OPEN_PORT=unchecked((int)0x8004075C); - public const int E_FIREWALL_CANNOT_OPEN_FILE_SHARING=unchecked((int)0x8004075D); - public const int E_REMOTE_DEBUGGING_UNSUPPORTED=unchecked((int)0x8004075E); - public const int E_REMOTE_BAD_MSDBG2=unchecked((int)0x8004075F); - public const int E_ATTACH_USER_CANCELED=unchecked((int)0x80040760); - public const int E_FUNCTION_NOT_JITTED=unchecked((int)0x80040800); - public const int E_NO_CODE_CONTEXT=unchecked((int)0x80040801); - public const int E_BAD_CLR_DIASYMREADER=unchecked((int)0x80040802); - public const int E_CLR_SHIM_ERROR=unchecked((int)0x80040803); - public const int E_AUTOATTACH_ACCESS_DENIED=unchecked((int)0x80040900); - public const int E_AUTOATTACH_WEBSERVER_NOT_FOUND=unchecked((int)0x80040901); - public const int E_DBGEXTENSION_NOT_FOUND=unchecked((int)0x80040910); - public const int E_DBGEXTENSION_FUNCTION_NOT_FOUND=unchecked((int)0x80040911); - public const int E_DBGEXTENSION_FAULTED=unchecked((int)0x80040912); - public const int E_DBGEXTENSION_RESULT_INVALID=unchecked((int)0x80040913); - public const int E_PROGRAM_IN_RUNMODE=unchecked((int)0x80040914); - public const int E_CAUSALITY_NO_SERVER_RESPONSE=unchecked((int)0x80040920); - public const int E_CAUSALITY_REMOTE_NOT_REGISTERED=unchecked((int)0x80040921); - public const int E_CAUSALITY_BREAKPOINT_NOT_HIT=unchecked((int)0x80040922); - public const int E_CAUSALITY_BREAKPOINT_BIND_ERROR=unchecked((int)0x80040923); - public const int E_CAUSALITY_PROJECT_DISABLED=unchecked((int)0x80040924); - public const int E_NO_ATTACH_WHILE_DDD=unchecked((int)0x80040A00); - public const int E_SQLLE_ACCESSDENIED=unchecked((int)0x80040A01); - public const int E_SQL_SP_ENABLE_PERMISSION_DENIED=unchecked((int)0x80040A02); - public const int E_SQL_DEBUGGING_NOT_ENABLED_ON_SERVER=unchecked((int)0x80040A03); - public const int E_SQL_CANT_FIND_SSDEBUGPS_ON_CLIENT=unchecked((int)0x80040A04); - public const int E_SQL_EXECUTED_BUT_NOT_DEBUGGED=unchecked((int)0x80040A05); - public const int E_SQL_VDT_INIT_RETURNED_SQL_ERROR=unchecked((int)0x80040A06); - public const int E_ATTACH_FAILED_ABORT_SILENTLY=unchecked((int)0x80040A07); - public const int E_SQL_REGISTER_FAILED=unchecked((int)0x80040A08); - public const int E_DE_NOT_SUPPORTED_PRE_8_0=unchecked((int)0x80040B00); - public const int E_PROGRAM_DESTROY_PENDING=unchecked((int)0x80040B01); - public const int E_MANAGED_FEATURE_NOTSUPPORTED=unchecked((int)0x80040BAD); - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7BoundBreakpoint.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7BoundBreakpoint.cs deleted file mode 100644 index 43d4d4ac..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7BoundBreakpoint.cs +++ /dev/null @@ -1,584 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Threading; -using System.IO; - -namespace VSNDK.DebugEngine -{ - - /// - /// This class represents a breakpoint that has been bound to a location in the debuggee. It is a child of the pending - /// breakpoint that creates it. Unless the pending breakpoint only has one bound breakpoint, each bound breakpoint is displayed as - /// a child of the pending breakpoint in the breakpoints window. Otherwise, only one is displayed. - /// (http://msdn.microsoft.com/en-us/library/bb161979.aspx) - /// - public class AD7BoundBreakpoint : IDebugBoundBreakpoint2 - { - private AD7PendingBreakpoint m_pendingBreakpoint; - private AD7BreakpointResolution m_breakpointResolution; - private AD7Engine m_engine; - - private bool m_enabled; - private bool m_deleted; - public uint m_hitCount; - - public uint m_bpLocationType; - public string m_filename = ""; - public string m_fullPath = ""; - public uint m_line = 0; - public string m_func = ""; - - /// - /// This breakpoint's index in the list of active bound breakpoints. - /// - protected int m_remoteID = -1; - public int RemoteID - { - get { return m_remoteID; } - } - - public BP_PASSCOUNT m_bpPassCount; - public BP_CONDITION m_bpCondition; - - /// - /// TRUE if the program has to stop when the hit count is equal to a given value. - /// - public bool m_isHitCountEqual = false; - - /// - /// Different than 0 if the program has to stop whenever the hit count is multiple of a given value - /// - public uint m_hitCountMultiple = 0; - public bool m_breakWhenCondChanged = false; - public string m_previousCondEvaluation = ""; - - /// - /// Indicates if a given breakpoint is being manipulated in one of these 2 methods: SetPassCount and BreakpointHit. - /// - public bool m_blockedPassCount = false; - - /// - /// Indicates if a given breakpoint is being manipulated in one of these 2 methods: SetCondition and BreakpointHit. - /// - public bool m_blockedConditional = false; - - /// - /// GDB member variables. - /// - protected uint m_GDB_ID = 0; - protected string m_GDB_filename = ""; - protected uint m_GDB_linePos = 0; - protected string m_GDB_Address = ""; - - - /// - /// GDB_ID Property. - /// - public uint GDB_ID - { - get { return m_GDB_ID; } - set { m_GDB_ID = value; } - } - - - /// - /// GDB_FileName Property. - /// - public string GDB_FileName - { - get { return m_GDB_filename; } - set { m_GDB_filename = value; } - } - - - /// - /// GDB_LinePos Property. - /// - public uint GDB_LinePos - { - get { return m_GDB_linePos; } - set { m_GDB_linePos = value; } - } - - - /// - /// GDB_Address Property. - /// - public string GDB_Address - { - get { return m_GDB_Address; } - set { m_GDB_Address = value; } - } - - - /// - /// GDB works with short path names only, which requires converting the path names to/from long ones. This function - /// returns the short path name for a given long one. - /// - /// Long path name. - /// Returns this short path name. - /// Lenght of this short path name. - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern int GetShortPathName( - [MarshalAs(UnmanagedType.LPTStr)] - string path, - [MarshalAs(UnmanagedType.LPTStr)] - StringBuilder shortPath, - int shortPathLength - ); - - - /// - /// AD7BoundBreakpoint constructor for file/line breaks. - /// - /// AD7 Engine. - /// Contains the information required to implement a breakpoint. - /// Associated pending breakpoint. - public AD7BoundBreakpoint(AD7Engine engine, BP_REQUEST_INFO bpReqInfo, AD7PendingBreakpoint pendingBreakpoint) - { - if (bpReqInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) - { - string documentName; - - // Get Decument Position and File Name - IDebugDocumentPosition2 docPosition = (IDebugDocumentPosition2)(Marshal.GetObjectForIUnknown(bpReqInfo.bpLocation.unionmember2)); - docPosition.GetFileName(out documentName); - - // Need to shorten the path we send to GDB. - StringBuilder shortPath = new StringBuilder(1024); - GetShortPathName(documentName, shortPath, shortPath.Capacity); - - // Get the location in the document that the breakpoint is in. - TEXT_POSITION[] startPosition = new TEXT_POSITION[1]; - TEXT_POSITION[] endPosition = new TEXT_POSITION[1]; - docPosition.GetRange(startPosition, endPosition); - - m_engine = engine; - m_bpLocationType = (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE; - m_filename = shortPath.ToString(); - m_line = startPosition[0].dwLine + 1; - - m_pendingBreakpoint = pendingBreakpoint; - m_enabled = true; - m_deleted = false; - m_hitCount = 0; - m_remoteID = m_engine.BPMgr.RemoteAdd(this); - } - else if (bpReqInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) - { - string func; - - IDebugFunctionPosition2 funcPosition = (IDebugFunctionPosition2)(Marshal.GetObjectForIUnknown(bpReqInfo.bpLocation.unionmember2)); - funcPosition.GetFunctionName(out func); - - m_engine = engine; - m_func = func; - m_enabled = true; - m_deleted = false; - m_hitCount = 0; - m_bpLocationType = (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET; - m_pendingBreakpoint = pendingBreakpoint; - m_remoteID = m_engine.BPMgr.RemoteAdd(this); - } - -// if ((m_remoteID == 0) && (VSNDK.AddIn.VSNDKAddIn.isDebugEngineRunning == false)) - if (m_remoteID == 0) - { - return; - } - - // Set the hit count and condition - if (bpReqInfo.bpPassCount.stylePassCount != enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_NONE) - SetPassCount(bpReqInfo.bpPassCount); - if (bpReqInfo.bpCondition.styleCondition != enum_BP_COND_STYLE.BP_COND_NONE) - SetCondition(bpReqInfo.bpCondition); - - // Get the Line Position sent back from GDB - TEXT_POSITION tpos = new TEXT_POSITION(); - tpos.dwLine = m_GDB_linePos - 1; - - uint xAddress = UInt32.Parse(m_GDB_Address.Substring(2), System.Globalization.NumberStyles.HexNumber); - - AD7MemoryAddress codeContext = new AD7MemoryAddress(m_engine, xAddress); - AD7DocumentContext documentContext = new AD7DocumentContext(m_GDB_filename, tpos, tpos, codeContext); - - m_breakpointResolution = new AD7BreakpointResolution(m_engine, xAddress, documentContext); - - m_engine.Callback.OnBreakpointBound(this, 0); - } - - - /// - /// Sets the count and conditions upon which a breakpoint is fired. - /// (http://msdn.microsoft.com/en-us/library/bb161364.aspx) - /// - /// Describes the count and conditions upon which a conditional breakpoint is fired. - /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. - public int SetPassCount(BP_PASSCOUNT bpPassCount) - { - bool isRunning = false; - int result = VSConstants.S_FALSE; - while (!m_engine.eDispatcher.lockedBreakpoint(this, true, false)) - { - Thread.Sleep(0); - } - while (!m_engine.eDispatcher.enterCriticalRegion()) - { - Thread.Sleep(0); - } - if ((m_engine.m_state == AD7Engine.DE_STATE.RUN_MODE) && (EventDispatcher.m_GDBRunMode == true)) - { - isRunning = true; - m_engine.eDispatcher.prepareToModifyBreakpoint(); - } - m_bpPassCount = bpPassCount; - if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL_OR_GREATER) - { - m_isHitCountEqual = false; - m_hitCountMultiple = 0; - if (!m_breakWhenCondChanged) - { - if ((int)((bpPassCount.dwPassCount - m_hitCount)) >= 0) - { - if (m_engine.eDispatcher.ignoreHitCount(GDB_ID, (int)(bpPassCount.dwPassCount - m_hitCount))) - result = VSConstants.S_OK; - } - else - { - if (m_engine.eDispatcher.ignoreHitCount(GDB_ID, 1)) - result = VSConstants.S_OK; - } - - } - else - result = VSConstants.S_OK; - } - else if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL) - { - m_hitCountMultiple = 0; - m_isHitCountEqual = true; - if (!m_breakWhenCondChanged) - { - if (m_engine.eDispatcher.ignoreHitCount(GDB_ID, (int)(bpPassCount.dwPassCount - m_hitCount))) - result = VSConstants.S_OK; - } - else - result = VSConstants.S_OK; - } - else if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_MOD) - { - m_isHitCountEqual = false; - m_hitCountMultiple = bpPassCount.dwPassCount; - if (!m_breakWhenCondChanged) - { - if (m_engine.eDispatcher.ignoreHitCount(GDB_ID, (int)(m_hitCountMultiple - (m_hitCount % m_hitCountMultiple)))) - result = VSConstants.S_OK; - } - else - result = VSConstants.S_OK; - } - else if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_NONE) - { - m_isHitCountEqual = false; - m_hitCountMultiple = 0; - if (!m_breakWhenCondChanged) - { - if (m_engine.eDispatcher.ignoreHitCount(GDB_ID, 1)) // ignoreHitCount decrement by 1 automatically, so sending 1 means to stop ignoring (or ignore 0) - result = VSConstants.S_OK; - } - else - result = VSConstants.S_OK; - } - - if (isRunning) - { - isRunning = false; - m_engine.eDispatcher.resumeFromInterrupt(); - } - - m_engine.eDispatcher.leaveCriticalRegion(); - m_engine.eDispatcher.unlockBreakpoint(this, true, false); - return result; - } - - - /// - /// Sets the conditions under which a conditional breakpoint fires. (http://msdn.microsoft.com/en-us/library/bb146215.aspx) - /// - /// Describes the conditions under which a breakpoint fires. - /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. - public int SetCondition(BP_CONDITION bpCondition) - { - bool updatingCondBreak = this.m_engine.m_updatingConditionalBreakpoint.WaitOne(0); - bool isRunning = false; - bool verifyCondition = false; - int result = VSConstants.S_FALSE; - while (!m_engine.eDispatcher.lockedBreakpoint(this, false, true)) - { - Thread.Sleep(0); - } - - if (m_hitCount != 0) - { - m_engine.eDispatcher.resetHitCount(this, false); - } - - while (!m_engine.eDispatcher.enterCriticalRegion()) - { - Thread.Sleep(0); - } - - if ((m_engine.m_state == AD7Engine.DE_STATE.RUN_MODE) && (EventDispatcher.m_GDBRunMode == true)) - { - isRunning = true; - m_engine.eDispatcher.prepareToModifyBreakpoint(); - m_engine.m_state = AD7Engine.DE_STATE.BREAK_MODE; - } - - m_bpCondition = bpCondition; - - if (bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE) - { - if (m_breakWhenCondChanged) - { - m_breakWhenCondChanged = false; - verifyCondition = true; - } - else - m_breakWhenCondChanged = false; - - m_previousCondEvaluation = ""; - if (m_engine.eDispatcher.setBreakpointCondition(GDB_ID, bpCondition.bstrCondition)) - result = VSConstants.S_OK; - } - else if (bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_CHANGED) - { - m_breakWhenCondChanged = true; - m_previousCondEvaluation = bpCondition.bstrCondition; // just to initialize this variable - m_engine.eDispatcher.ignoreHitCount(GDB_ID, 1); // have to break always to evaluate this option because GDB doesn't support it. - m_engine.eDispatcher.setBreakpointCondition(GDB_ID, ""); - - result = VSConstants.S_OK; - } - else if (bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_NONE) - { - if (m_breakWhenCondChanged) - { - m_breakWhenCondChanged = false; - verifyCondition = true; - } - else - m_breakWhenCondChanged = false; - - m_previousCondEvaluation = ""; - if (m_engine.eDispatcher.setBreakpointCondition(GDB_ID, "")) - result = VSConstants.S_OK; - } - - m_engine.eDispatcher.leaveCriticalRegion(); - m_engine.eDispatcher.unlockBreakpoint(this, false, true); - - if (verifyCondition) - { - SetPassCount(m_bpPassCount); - verifyCondition = false; - } - - if (isRunning) - { - isRunning = false; - m_engine.m_state = AD7Engine.DE_STATE.RUN_MODE; - m_engine.eDispatcher.resumeFromInterrupt(); - } - - this.m_engine.m_updatingConditionalBreakpoint.Set(); - - return result; - } - - #region IDebugBoundBreakpoint2 Members - - - /// - /// Called when the breakpoint is being deleted by the user. (http://msdn.microsoft.com/en-us/library/bb146595.aspx) - /// - /// VSConstants.S_OK - int IDebugBoundBreakpoint2.Delete() - { - if (!m_deleted) - { - m_enabled = false; - m_deleted = true; - m_pendingBreakpoint.OnBoundBreakpointDeleted(this); - m_engine.BPMgr.RemoteDelete(this); - m_remoteID = -1; - } - return VSConstants.S_OK; - } - - - /// - /// Called by the debugger UI when the user is enabling or disabling a breakpoint. - /// (http://msdn.microsoft.com/en-us/library/bb145150.aspx) - /// - /// Equal to 0 if disabling; different than 0 if enabling. - /// VSConstants.S_OK - int IDebugBoundBreakpoint2.Enable(int fEnable) - { - bool xEnabled = fEnable != 0; - if (m_enabled != xEnabled) - { - if (xEnabled) - { - m_engine.BPMgr.RemoteEnable(this); - } - else - { - m_engine.BPMgr.RemoteDisable(this); - } - m_enabled = xEnabled; - } - return VSConstants.S_OK; - } - - - /// - /// Return the breakpoint resolution which describes how the breakpoint bound in the debuggee. - /// (http://msdn.microsoft.com/en-us/library/bb145891.aspx) - /// - /// Contains the information that describes a bound breakpoint. - /// VSConstants.S_OK - int IDebugBoundBreakpoint2.GetBreakpointResolution(out IDebugBreakpointResolution2 ppBPResolution) - { - ppBPResolution = m_breakpointResolution; - return VSConstants.S_OK; - } - - - /// - /// Return the pending breakpoint for this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb145337.aspx) - /// - /// Contains a breakpoint that is ready to bind to a code location. - /// VSConstants.S_OK - int IDebugBoundBreakpoint2.GetPendingBreakpoint(out IDebugPendingBreakpoint2 ppPendingBreakpoint) - { - ppPendingBreakpoint = m_pendingBreakpoint; - return VSConstants.S_OK; - } - - - /// - /// Gets the state of this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb161276.aspx) - /// - /// Describes the state of the breakpoint. - /// VSConstants.S_OK - int IDebugBoundBreakpoint2.GetState(enum_BP_STATE[] pState) - { - pState[0] = 0; - - if (m_deleted) - { - pState[0] = enum_BP_STATE.BPS_DELETED; - } - else if (m_enabled) - { - pState[0] = enum_BP_STATE.BPS_ENABLED; - } - else if (!m_enabled) - { - pState[0] = enum_BP_STATE.BPS_DISABLED; - } - - return VSConstants.S_OK; - } - - - /// - /// Gets the current hit count for this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb145340.aspx) - /// - /// Returns the hit count. - /// AD7_HRESULT.E_BP_DELETED if the breakpoint was deleted; or VSConstants.S_OK if not. - int IDebugBoundBreakpoint2.GetHitCount(out uint pdwHitCount) - { - if (m_deleted) - { - pdwHitCount = 0; - return AD7_HRESULT.E_BP_DELETED; - } - else - { - pdwHitCount = m_hitCount; - return VSConstants.S_OK; - } - } - - - /// - /// Sets or changes the condition associated with this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb146215.aspx) - /// - /// Describes the condition. - /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. - int IDebugBoundBreakpoint2.SetCondition(BP_CONDITION bpCondition) - { - return SetCondition(bpCondition); - } - - - /// - /// Sets the hit count for the bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb146736.aspx) - /// - /// The hit count to set. - /// AD7_HRESULT.E_BP_DELETED if the breakpoint was deleted; or VSConstants.S_OK if not. - int IDebugBoundBreakpoint2.SetHitCount(uint dwHitCount) - { - if (m_deleted) - { - return AD7_HRESULT.E_BP_DELETED; - } - else - { - if ((dwHitCount == 0) && (m_hitCount != 0)) - { - m_hitCount = dwHitCount; - m_engine.eDispatcher.resetHitCount(this, true); - } - else - m_hitCount = dwHitCount; - return VSConstants.S_OK; - } - } - - - /// - /// Sets or changes the pass count associated with this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb161364.aspx) - /// - /// Specifies the pass count. - /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. - int IDebugBoundBreakpoint2.SetPassCount(BP_PASSCOUNT bpPassCount) - { - return SetPassCount(bpPassCount); - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7BreakpointResolution.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7BreakpointResolution.cs deleted file mode 100644 index c4fc50d5..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7BreakpointResolution.cs +++ /dev/null @@ -1,155 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Runtime.InteropServices; - -// TODO: Change to take filename and line number instead of an address? - -namespace VSNDK.DebugEngine -{ - - /// - /// This class represents the information that describes a bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb145894.aspx) - /// - public class AD7BreakpointResolution : IDebugBreakpointResolution2 - { - /// - /// AD7 Engine. - /// - private AD7Engine m_engine; - - /// - /// GDB Address - /// - private uint m_address; - - /// - /// The document context to the debugger. A document context represents a location within a source file. - /// - private AD7DocumentContext m_documentContext; - - - /// - /// Constructor. - /// - /// AD7 Engine. - /// GDB Address. - /// The document context to the debugger. A document context represents a location within a - /// source file. - public AD7BreakpointResolution(AD7Engine engine, uint address, AD7DocumentContext documentContext) - { - m_engine = engine; - m_address = address; - m_documentContext = documentContext; - } - - #region IDebugBreakpointResolution2 Members - - - /// - /// Gets the type of the breakpoint represented by this resolution. (http://msdn.microsoft.com/en-us/library/bb145576.aspx) - /// - /// The type of this breakpoint. - /// VSConstants.S_OK. - int IDebugBreakpointResolution2.GetBreakpointType(enum_BP_TYPE[] pBPType) - { - // The VSNDK debug engine only supports code breakpoints. - pBPType[0] = enum_BP_TYPE.BPT_CODE; - return VSConstants.S_OK; - } - - - /// - /// Gets the breakpoint resolution information that describes this breakpoint. - /// (http://msdn.microsoft.com/en-us/library/bb146743.aspx) - /// - /// A combination of flags that determine which fields of the pBPResolutionInfo parameter are to be filled out. - /// The BP_RESOLUTION_INFO structure to be filled in with information about this breakpoint. - /// VSConstants.S_OK. - int IDebugBreakpointResolution2.GetResolutionInfo(enum_BPRESI_FIELDS dwFields, BP_RESOLUTION_INFO[] pBPResolutionInfo) - { - if ((dwFields & enum_BPRESI_FIELDS.BPRESI_BPRESLOCATION) != 0) - { - // The sample engine only supports code breakpoints. - BP_RESOLUTION_LOCATION location = new BP_RESOLUTION_LOCATION(); - location.bpType = (uint)enum_BP_TYPE.BPT_CODE; - - // The debugger will not QI the IDebugCodeContex2 interface returned here. We must pass the pointer - // to IDebugCodeContex2 and not IUnknown. - AD7MemoryAddress codeContext = new AD7MemoryAddress(m_engine, m_address); - codeContext.SetDocumentContext(m_documentContext); - location.unionmember1 = Marshal.GetComInterfaceForObject(codeContext, typeof(IDebugCodeContext2)); - pBPResolutionInfo[0].bpResLocation = location; - pBPResolutionInfo[0].dwFields |= enum_BPRESI_FIELDS.BPRESI_BPRESLOCATION; - - } - - if ((dwFields & enum_BPRESI_FIELDS.BPRESI_PROGRAM) != 0) - { - pBPResolutionInfo[0].pProgram = (IDebugProgram2)m_engine; - pBPResolutionInfo[0].dwFields |= enum_BPRESI_FIELDS.BPRESI_PROGRAM; - } - - return VSConstants.S_OK; - } - - #endregion - } - - /// - /// Represents the resolution of a breakpoint error. (http://msdn.microsoft.com/en-us/library/bb161341.aspx) - /// - class AD7ErrorBreakpointResolution : IDebugErrorBreakpointResolution2 - { - #region IDebugErrorBreakpointResolution2 Members - - - /// - /// Gets the breakpoint type. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145065.aspx) - /// - /// The type of this breakpoint. - /// Not implemented. - int IDebugErrorBreakpointResolution2.GetBreakpointType(enum_BP_TYPE[] pBPType) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Gets the breakpoint error resolution information. Not implemented. (http://msdn.microsoft.com/en-us/library/bb161960.aspx) - /// - /// A combination of flags that determine which fields of pErrorResolutionInfo are to be filled out. - /// The BP_ERROR_RESOLUTION_INFO structure that is filled in with the description of the - /// breakpoint resolution. - /// Not implemented. - int IDebugErrorBreakpointResolution2.GetResolutionInfo(enum_BPERESI_FIELDS dwFields, BP_ERROR_RESOLUTION_INFO[] pErrorResolutionInfo) - { - if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_BPRESLOCATION) != 0) { } - if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_PROGRAM) != 0) { } - if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_THREAD) != 0) { } - if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_MESSAGE) != 0) { } - if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_TYPE) != 0) { } - - throw new Exception("The method or operation is not implemented."); - } - - #endregion - } - -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7DocumentContext.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7DocumentContext.cs deleted file mode 100644 index aa78213a..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7DocumentContext.cs +++ /dev/null @@ -1,231 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace VSNDK.DebugEngine -{ - /// - /// This class represents a document context to the debugger. A document context represents a location within a source file. - /// (http://msdn.microsoft.com/en-us/library/bb145572.aspx) - /// - public class AD7DocumentContext : IDebugDocumentContext2 - { - /// - /// Long path file name - /// - string m_fileName; - - /// - /// Start position. In VSNDK debug engine, both begPos and endPos have the same value. - /// - TEXT_POSITION m_begPos; - - /// - /// End position. In VSNDK debug engine, both begPos and endPos have the same value. - /// - TEXT_POSITION m_endPos; - - /// - /// An address in a program's execution stream. - /// - AD7MemoryAddress m_codeContext; - - - /// GDB works with short path names only, which requires converting the path names to/from long ones. This function - /// returns the long path name for a given short one. - /// Short path name. - /// Returns this long path name. - /// Lenght of this long path name. - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern int GetLongPathName( - [MarshalAs(UnmanagedType.LPTStr)] - string path, - [MarshalAs(UnmanagedType.LPTStr)] - StringBuilder longPath, - int longPathLength - ); - - - /// - /// Constructor. - /// - /// Short path file name. - /// Start position. - /// End position. In VSNDK debug engine, both begPos and endPos have the same value. - /// An address in a program's execution stream. - public AD7DocumentContext(string fileName, TEXT_POSITION begPos, TEXT_POSITION endPos, AD7MemoryAddress codeContext) - { - // Need to lengthen the path used by Visual Studio. - StringBuilder documentNameSB = new StringBuilder(1024); - GetLongPathName(fileName, documentNameSB, documentNameSB.Capacity); - m_fileName = documentNameSB.ToString(); - - m_begPos = begPos; - m_endPos = endPos; - m_codeContext = codeContext; - } - - - #region IDebugDocumentContext2 Members - - - /// - /// Compares this document context to a given array of document contexts. (http://msdn.microsoft.com/en-us/library/bb145338.aspx) - /// - /// A value from the DOCCONTEXT_COMPARE enumeration that specifies the type of comparison. - /// An array of IDebugDocumentContext2 objects that represent the document contexts being compared to. - /// The length of the array of document contexts to compare. - /// Returns the index into the rgpDocContextSet array of the first document context that satisfies the comparison. - /// VSConstants.E_NOTIMPL. - int IDebugDocumentContext2.Compare(enum_DOCCONTEXT_COMPARE Compare, IDebugDocumentContext2[] rgpDocContextSet, uint dwDocContextSetLen, out uint pdwDocContext) - { - dwDocContextSetLen = 0; - pdwDocContext = 0; - - return VSConstants.E_NOTIMPL; - } - - - /// - /// Retrieves a list of all code contexts associated with this document context. The VSNDK Debug Engine only supports one code context per document - /// context and the code contexts are always memory addresses. (http://msdn.microsoft.com/en-us/library/bb146273.aspx) - /// - /// Returns an IEnumDebugCodeContexts2 object that contains a list of code contexts. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugDocumentContext2.EnumCodeContexts(out IEnumDebugCodeContexts2 ppEnumCodeCxts) - { - ppEnumCodeCxts = null; - try - { - AD7MemoryAddress[] codeContexts = new AD7MemoryAddress[1]; - codeContexts[0] = m_codeContext; - ppEnumCodeCxts = new AD7CodeContextEnum(codeContexts); - return VSConstants.S_OK; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Gets the document that contains this document context. This method is for those debug engines that supply documents directly - /// to the IDE. Since the VSNDK Debug Engine does not do this, this method returns E_FAIL. - /// (http://msdn.microsoft.com/en-us/library/bb161759.aspx) - /// - /// Returns an IDebugDocument2 object that represents the document that contains this document context. - /// E_FAIL. - int IDebugDocumentContext2.GetDocument(out IDebugDocument2 ppDocument) - { - ppDocument = null; - return VSConstants.E_FAIL; - } - - - /// - /// Gets the language associated with this document context. The language for this sample is always C++. - /// (http://msdn.microsoft.com/en-us/library/bb146340.aspx) - /// - /// Returns the name of the language that implements the code at this document context. - /// Returns the GUID of the language that implements the code at this document context. - /// VSConstants.S_OK. - int IDebugDocumentContext2.GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) - { - pbstrLanguage = "C++"; - pguidLanguage = AD7Guids.guidLanguageCpp; - return VSConstants.S_OK; - } - - - /// - /// Gets the displayable name of the document that contains this document context. - /// (http://msdn.microsoft.com/en-us/library/bb146162.aspx) - /// - /// A value from the GETNAME_TYPE enumeration that specifies the type of name to return. - /// Returns the name of the file. - /// VSConstants.S_OK. - int IDebugDocumentContext2.GetName(enum_GETNAME_TYPE gnType, out string pbstrFileName) - { - pbstrFileName = m_fileName; - return VSConstants.S_OK; - } - - - /// - /// Gets the source code range of this document context. A source range is the entire range of source code, from the current - /// statement back to just after the previous statement that contributed code. The source range is typically used for mixing - /// source statements, including comments, with code in the disassembly window. Since this engine does not support the - /// disassembly window, this is not implemented. (http://msdn.microsoft.com/en-us/library/bb146190.aspx) - /// - /// A TEXT_POSITION structure that is filled in with the starting position. Set to a null value if it is not needed. - /// A TEXT_POSITION structure that is filled in with the ending position. Set to a null value if it is not needed. - /// Not implemented. - int IDebugDocumentContext2.GetSourceRange(TEXT_POSITION[] pBegPosition, TEXT_POSITION[] pEndPosition) - { - throw new NotImplementedException("This method is not implemented"); - } - - - /// - /// Gets the file statement range of the document context. A statement range is the range of the lines that contributed the code - /// to which this document context refers. (http://msdn.microsoft.com/en-us/library/bb161669.aspx) - /// - /// A TEXT_POSITION structure that is filled in with the starting position. Set to a null value if it is not needed. - /// A TEXT_POSITION structure that is filled in with the ending position. Set to a null value if it is not needed. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugDocumentContext2.GetStatementRange(TEXT_POSITION[] pBegPosition, TEXT_POSITION[] pEndPosition) - { - try - { - pBegPosition[0].dwColumn = m_begPos.dwColumn; - pBegPosition[0].dwLine = m_begPos.dwLine; - - pEndPosition[0].dwColumn = m_endPos.dwColumn; - pEndPosition[0].dwLine = m_endPos.dwLine; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - - return VSConstants.S_OK; - } - - - /// - /// Moves the document context by a given number of statements or lines. This is used primarily to support the Autos window in - /// discovering the proximity statements around this document context. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb146603.aspx) - /// - /// The number of statements or lines to move ahead, depending on the document context. - /// Returns a new IDebugDocumentContext2 object with the new position. - /// Not implemented. - int IDebugDocumentContext2.Seek(int nCount, out IDebugDocumentContext2 ppDocContext) - { - ppDocContext = null; - return VSConstants.E_NOTIMPL; - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Engine.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Engine.cs deleted file mode 100644 index 457c4248..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Engine.cs +++ /dev/null @@ -1,1455 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; -using System.Threading; -using VSNDK.Parser; -//using VSNDK.AddIn; -using VSNDK.Package; - -using NameValueCollection = System.Collections.Specialized.NameValueCollection; -using NameValueCollectionHelper = VSNDK.Package.NameValueCollectionHelper; -using System.Collections; -using System.Windows.Forms; - -namespace VSNDK.DebugEngine -{ - - /// - /// AD7Engine is the primary entrypoint object for the sample engine. - /// - /// It implements: - /// - /// IDebugEngine2: This interface represents a debug engine (DE). It is used to manage various aspects of a debugging session, - /// from creating breakpoints to setting and clearing exceptions. (http://msdn.microsoft.com/en-us/library/bb145310.aspx). - /// - /// IDebugEngineLaunch2: Used by a debug engine (DE) to launch and terminate programs. - /// (http://msdn.microsoft.com/en-us/library/bb146230.aspx). - /// - /// IDebugProgram3: This interface represents a program that is running in a process. Since this engine only debugs one process at a time and each - /// process only contains one program, it is implemented on the engine. (http://msdn.microsoft.com/en-us/library/bb145884.aspx). - /// - /// IDebugEngineProgram2: This interface provides simultanious debugging of multiple threads in a debuggee. - /// (http://msdn.microsoft.com/en-us/library/bb145128.aspx). - /// - /// IDebugSymbolSettings100: (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugsymbolsettings100.aspx). - /// - /// Comments: - /// Process "Is a container for a set of programs". - /// "A debug engine (DE) attaches to a program, and not to a process or a thread". - /// Program "Is a container for both a set of threads and a set of modules.". - /// - [ComVisible(true)] - [Guid("904AA6E0-942C-4D11-9094-7BAAEB3EE4B9")] - public class AD7Engine : IDebugEngine2, IDebugEngineLaunch2, IDebugProgram3, IDebugEngineProgram2, IDebugSymbolSettings100 - { - - /// - /// Used to send events to the debugger. Some examples of these events are thread create, exception thrown, module load. - /// - EngineCallback m_engineCallback = null; - internal EngineCallback Callback - { - get { return m_engineCallback; } - } - - - /// - /// This object manages breakpoints in the sample engine. - /// - protected BreakpointManager m_breakpointManager = null; - public BreakpointManager BPMgr - { - get { return m_breakpointManager; } - } - - - /// - /// This object manages debug events in the engine. - /// - protected EventDispatcher m_eventDispatcher = null; - public EventDispatcher eDispatcher - { - get { return m_eventDispatcher; } - } - - - /// - /// A unique identifier for the program being debugged. - /// - Guid m_programGUID; - - /// - /// A module loaded in the debuggee process to the debugger. It is always null because the AD7Module class is - /// not implemented yet. - /// - internal AD7Module m_module = null; - - /// - /// A process running on a port. A process "Is a container for a set of programs". - /// - public AD7Process m_process = null; - - /// - /// A program that can be debugged. - /// - public AD7ProgramNode m_progNode = null; - - /// - /// A program that is running in a process. - /// - internal IDebugProgram2 m_program = null; - - /// - /// TRUE whenever a thread is created/ended, so the debug engine can update the m_threads data structure. - /// - public bool _updateThreads = false; - - /// - /// Array of threads of the program that is being debugged. - /// - private AD7Thread[] m_threads = null; - public AD7Thread[] thread - { - get { return m_threads; } - } - - /// - /// The position in the m_threads array that corresponds to the current thread. - /// - public int _currentThreadIndex = -1; - - - /// - /// Allows IDE to show current position in a source file - /// - public AD7DocumentContext m_docContext = null; - - - /// - /// Used to avoid race condition when there are conditional breakpoints and the user hit break all. Both events will pause - /// the Debug Engine, but the one related to conditional breakpoint can resume execution. If both events happens at the same - /// time, the Debug Engine could resume the execution instead of pausing it. - /// - public ManualResetEvent m_running = new ManualResetEvent(true); - - - /// - /// Used to avoid race condition when there are conditional breakpoints and a breakpoint is hit. This situation is similar to the above one. - /// - public ManualResetEvent m_updatingConditionalBreakpoint = new ManualResetEvent(true); - - - /// - /// This is the engine GUID of the VSNDK debug engine. It needs to be changed here and in the registration when creating a - /// new engine. - /// - public const string Id = "{E5A37609-2F43-4830-AA85-D94CFA035DD2}"; - - - /// - /// Keeps track of debug engine states - /// - public enum DE_STATE - { - DESIGN_MODE = 0, - RUN_MODE, - BREAK_MODE, - STEP_MODE, - DONE - } - public DE_STATE m_state = 0; - - - /// - /// Constructor. - /// - public AD7Engine() - { - m_breakpointManager = new BreakpointManager(this); - m_state = DE_STATE.DESIGN_MODE; - } - - - /// - /// Destructor. - /// - ~AD7Engine() - { - // Transition DE state - m_state = AD7Engine.DE_STATE.DONE; - } - - #region IDebugEngine2 Members - - - /// - /// Attach the debug engine to a program. (http://msdn.microsoft.com/en-us/library/bb145136.aspx) - /// - /// Represent programs to be attached to. These are port programs. - /// Represent program nodes, one for each program. The program nodes in this array represent - /// the same programs as in pProgram. The program nodes are given so that the DE can identify the programs to attach to. - /// Number of programs and/or program nodes in the pProgram and rgpProgramNodes arrays. - /// The IDebugEventCallback2 object to be used to send debug events to the SDM. - /// A value from the ATTACH_REASON enumeration that specifies the reason for attaching these programs. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint aCeltPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason) - { - - if (aCeltPrograms != 1) - { - System.Diagnostics.Debug.Fail("VSNDK Debugger only supports one debug target at a time."); - throw new ArgumentException(); - } - - try - { - EngineUtils.RequireOk(rgpPrograms[0].GetProgramId(out m_programGUID)); - - m_program = rgpPrograms[0]; - - // It is NULL when the user attached the debugger to a running process (by using Attach to Process UI). When that - // happens, some objects must be instantiated, as well as GDB must be launched. Those ones are instantiated/launched - // by LaunchSuspended and ResumeProcess methods when debugging an open project. - if (this.m_engineCallback == null) - { - VSNDK.Package.ControlDebugEngine.isDebugEngineRunning = true; - m_engineCallback = new EngineCallback(this, ad7Callback); - - AD7ProgramNodeAttach pnt = (AD7ProgramNodeAttach)m_program; - m_process = pnt.m_process; - AD7Port port = pnt.m_process._portAttach; - string publicKeyPath = Environment.GetEnvironmentVariable("AppData") + @"\BlackBerry\bbt_id_rsa.pub"; - string progName = pnt.m_programName.Substring(pnt.m_programName.LastIndexOf('/') + 1); - - string exePath = ""; - string processesPaths = ""; - System.IO.StreamReader readProcessesPathsFile = null; - // Read the file ProcessesPath.txt to try to get the file location of the executable file. - try - { - readProcessesPathsFile = new System.IO.StreamReader(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\ProcessesPath.txt"); - processesPaths = readProcessesPathsFile.ReadToEnd(); - readProcessesPathsFile.Close(); - } - catch (Exception e) - { - processesPaths = ""; - } - - string searchProgName = progName + "_" + port.m_isSimulator; - int begin = processesPaths.IndexOf(searchProgName + ":>"); - - if (begin != -1) - { - begin += searchProgName.Length + 2; - int end = processesPaths.IndexOf("\r\n", begin); - - exePath = processesPaths.Substring(begin, end - begin) + progName; - } - else - { - exePath = "CannotAttachToRunningProcess"; - } - - exePath = exePath.Replace("\\", "\\\\\\\\"); - - if (GDBParser.LaunchProcess(pnt.m_programID, exePath, port.m_IP, port.m_isSimulator, port.m_toolsPath, publicKeyPath, port.m_password)) - { - if (exePath == "CannotAttachToRunningProcess") - { - MessageBox.Show(progName + " is attached to the debugger. However, to be able to debug your application, you must build and deploy it from this computer first.", "No executable file with symbols found.", MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - m_eventDispatcher = new EventDispatcher(this); - m_module = new AD7Module(); - m_progNode = new AD7ProgramNode(m_process._processGUID, m_process._processID, exePath, new Guid(AD7Engine.Id)); - AddThreadsToProgram(); - } - else - { - GDBParser.exitGDB(); - VSNDK.Package.ControlDebugEngine.isDebugEngineRunning = false; - return VSConstants.E_FAIL; - } - } - AD7EngineCreateEvent.Send(this); - AD7ProgramCreateEvent.Send(this); - AD7ModuleLoadEvent.Send(this, m_module, true); - AD7LoadCompleteEvent.Send(this, currentThread()); - - // If the reason for attaching is ATTACH_REASON_LAUNCH, the DE needs to send the IDebugEntryPointEvent2 event. - // See http://msdn.microsoft.com/en-us/library/bb145136%28v=vs.100%29.aspx - if (dwReason == enum_ATTACH_REASON.ATTACH_REASON_LAUNCH) - { - AD7EntryPointEvent ad7Event = new AD7EntryPointEvent(); - Guid riidEvent = new Guid(AD7EntryPointEvent.IID); - uint attributes = (uint)enum_EVENTATTRIBUTES.EVENT_STOPPING | (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; - int rc = ad7Callback.Event(this, null, m_program, currentThread(), ad7Event, ref riidEvent, attributes); - Debug.Assert(rc == VSConstants.S_OK); - } - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - return VSConstants.S_OK; - } - - - /// - /// Requests that all programs being debugged by this DE stop execution the next time one of their threads attempts to run. - /// This is normally called in response to the user clicking on the pause button in the debugger. When the break is complete, - /// an AsyncBreakComplete event will be sent back to the debugger. (http://msdn.microsoft.com/en-us/library/bb145141.aspx) - /// - /// VSConstants.S_OK. - int IDebugEngine2.CauseBreak() - { - // If not already broken, send the interrupt - if (m_state != DE_STATE.DESIGN_MODE && m_state != DE_STATE.BREAK_MODE && m_state != DE_STATE.STEP_MODE) - { - bool signalReceived; - bool hitBreakAll; - if (EventDispatcher.m_GDBRunMode == true) - { - HandleProcessExecution.m_mre.Reset(); - hitBreakAll = m_running.WaitOne(); - - // Sends the GDB command that interrupts the background execution of the target. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand(@"-exec-interrupt"); - - // Ensure the process is interrupted before returning - signalReceived = HandleProcessExecution.m_mre.WaitOne(1000); - - m_running.Set(); - - if (VSNDK.Package.ControlDebugEngine.isDebugEngineRunning) - HandleProcessExecution.m_mre.Reset(); - } - } - - return VSConstants.S_OK; - } - - - /// - /// Called by the SDM to indicate that a synchronous debug event, previously sent by the DE to the SDM, - /// was received and processed. The only event the VSNDK Debug Engine sends in this fashion is Program Destroy. - /// It responds to that event by shutting down the engine. (http://msdn.microsoft.com/en-us/library/bb160915.aspx) - /// - /// Represents the previously sent synchronous event from which the debugger should now continue. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugEngine2.ContinueFromSynchronousEvent(IDebugEvent2 eventObject) - { - try - { - if (eventObject is AD7ProgramDestroyEvent) - { - resetStackFrames(); - m_process.Detach(); - m_process = null; - - m_program.Detach(); - m_program = null; - - m_engineCallback = null; - m_breakpointManager = null; - m_docContext = null; - m_eventDispatcher = null; - m_module = null; - m_progNode = null; - m_programGUID = Guid.Empty; - - m_threads = null; - GC.Collect(); - } - else - { - Debug.Fail("Unknown synchronous event"); - } - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - - if (m_eventDispatcher != null) - m_eventDispatcher.continueExecution(); - - return VSConstants.S_OK; - } - - - /// - /// Creates a pending breakpoint in the Debug Engine. A pending breakpoint is essentially a collection of all the information - /// needed to bind a breakpoint to code. (http://msdn.microsoft.com/en-us/library/bb147033.aspx) - /// - /// An IDebugBreakpointRequest2 object that describes the pending breakpoint to create. - /// Returns an IDebugPendingBreakpoint2 object that represents the pending breakpoint. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugEngine2.CreatePendingBreakpoint(IDebugBreakpointRequest2 pBPRequest, out IDebugPendingBreakpoint2 ppPendingBP) - { - Debug.Assert(m_breakpointManager != null); - ppPendingBP = null; - - try - { - m_breakpointManager.CreatePendingBreakpoint(pBPRequest, out ppPendingBP); - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - - return VSConstants.S_OK; - } - - - /// - /// Informs a DE that the program specified has been atypically terminated and that the DE should clean up all references - /// to the program and send a program destroy event. (http://msdn.microsoft.com/en-us/library/bb145073.aspx) - /// - /// An IDebugProgram2 object that represents the program that has been atypically terminated. - /// AD7_HRESULT.E_PROGRAM_DESTROY_PENDING. - int IDebugEngine2.DestroyProgram(IDebugProgram2 pProgram) - { - // Tell the SDM that the engine knows that the program is exiting, and that the - // engine will send a program destroy. We do this because the Win32 debug api will always - // tell us that the process exited, and otherwise we have a race condition. - - return (AD7_HRESULT.E_PROGRAM_DESTROY_PENDING); - } - - - /// - /// Gets the GUID of the DE. (http://msdn.microsoft.com/en-us/library/bb145079.aspx) - /// - /// Returns the GUID of the DE. - /// VSConstants.S_OK. - int IDebugEngine2.GetEngineId(out Guid guidEngine) - { - guidEngine = new Guid(Id); - return VSConstants.S_OK; - } - - - /// - /// Removes the list of exceptions the IDE has set for a particular run-time architecture or language. The VSNDK debug engine - /// does not support exceptions in the debuggee so this method is not actually implemented. - /// (http://msdn.microsoft.com/en-us/library/bb145134.aspx) - /// - /// Either the GUID for the language or the GUID for the debug engine that is specific to a run-time - /// architecture. - /// VSConstants.S_OK. - int IDebugEngine2.RemoveAllSetExceptions(ref Guid guidType) - { - return VSConstants.S_OK; - } - - - /// - /// Removes the specified exception so it is no longer handled by the debug engine. The VSNDK debug engine does not support - /// exceptions in the debuggee so this method is not actually implemented. (http://msdn.microsoft.com/en-us/library/bb161697.aspx) - /// - /// An EXCEPTION_INFO structure that describes the exception to be removed. - /// VSConstants.S_OK. - int IDebugEngine2.RemoveSetException(EXCEPTION_INFO[] pException) - { - // The VSNDK debug engine will always stop on all exceptions. - - return VSConstants.S_OK; - } - - - /// - /// Specifies how the DE should handle a given exception. The VSNDK debug engine does not support exceptions in the debuggee - /// so this method is not actually implemented. (http://msdn.microsoft.com/en-us/library/bb162170.aspx) - /// - /// An EXCEPTION_INFO structure that describes the exception and how to debug it. - /// VSConstants.S_OK. - int IDebugEngine2.SetException(EXCEPTION_INFO[] pException) - { - return VSConstants.S_OK; - } - - - /// - /// Sets the locale of the DE. This method is called by the session debug manager (SDM) to propagate the locale settings - /// of the IDE so that strings returned by the DE are properly localized. The sample engine is not localized so this is - /// not implemented. (http://msdn.microsoft.com/en-us/library/bb161784.aspx) - /// - /// Specifies the language locale. - /// VSConstants.S_OK. - int IDebugEngine2.SetLocale(ushort wLangID) - { - return VSConstants.S_OK; - } - - - /// - /// A metric is a registry value used to change a debug engine's behavior or to advertise supported functionality. - /// This method can forward the call to the appropriate form of the Debugging SDK Helpers function, SetMetric. - /// (http://msdn.microsoft.com/en-us/library/bb161968.aspx) - /// - /// The metric name. - /// Specifies the metric value. - /// VSConstants.S_OK. - int IDebugEngine2.SetMetric(string pszMetric, object varValue) - { - // The VSNDK debug engine does not need to understand any metric settings. - return VSConstants.S_OK; - } - - - /// - /// Sets the registry root currently in use by the DE. Different installations of Visual Studio can change where their - /// registry information is stored. This allows the debugger to tell the engine where that location is. - /// (http://msdn.microsoft.com/en-us/library/bb161800.aspx) - /// - /// The registry root to use. - /// VSConstants.S_OK. - int IDebugEngine2.SetRegistryRoot(string pszRegistryRoot) - { - // The VSNDK debug engine does not read settings from the registry. - return VSConstants.S_OK; - } - - #endregion - - #region IDebugEngineLaunch2 Members - - - /// - /// Determines if a process can be terminated. (http://msdn.microsoft.com/en-us/library/bb146673.aspx) - /// - /// An IDebugProcess2 object that represents the process to be terminated. - /// VSConstants.S_OK. - int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 process) - { - return VSConstants.S_OK; - } - - - /// - /// Launches a process by means of the debug engine. (http://msdn.microsoft.com/en-us/library/bb146223.aspx) - /// - /// The name of the machine in which to launch the process. Use a null value to specify the local - /// machine. Or it should be the name of the server? - /// The IDebugPort2 interface representing the port that the program will run in. - /// The name of the executable to be launched. - /// The arguments to pass to the executable. May be a null value if there are no arguments. - /// The name of the working directory used by the executable. May be a null value if no working directory is - /// required. - /// Environment block of NULL-terminated strings, followed by an additional NULL terminator. - /// The options for the executable. - /// Specifies the LAUNCH_FLAGS for a session. - /// Handle to an alternate input stream. May be 0 if redirection is not required. - /// Handle to an alternate output stream. May be 0 if redirection is not required. - /// Handle to an alternate error output stream. May be 0 if redirection is not required. - /// The IDebugEventCallback2 object that receives debugger events. - /// Returns the resulting IDebugProcess2 object that represents the launched process. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) - { - Debug.Assert(m_programGUID == Guid.Empty); - - process = null; - - try - { - VSNDK.Package.ControlDebugEngine.isDebugEngineRunning = true; - m_engineCallback = new EngineCallback(this, ad7Callback); - - // Read arguments back from the args string - var nvc = new NameValueCollection(); - NameValueCollectionHelper.LoadFromString(nvc, args); - - string pid = nvc.GetValues("pid")[0]; - string exePath = exe; - string targetIP = nvc.GetValues("targetIP")[0]; - bool isSimulator = Convert.ToBoolean(nvc.GetValues("isSimulator")[0]); - string toolsPath = nvc.GetValues("ToolsPath")[0]; - string publicKeyPath = nvc.GetValues("PublicKeyPath")[0]; - - string password = null; - string[] passwordArray = nvc.GetValues("Password"); - if (passwordArray != null) - password = passwordArray[0]; - - if (GDBParser.LaunchProcess(pid, exePath, targetIP, isSimulator, toolsPath, publicKeyPath, password)) - { - process = m_process = new AD7Process(this, port); - m_eventDispatcher = new EventDispatcher(this); - m_programGUID = m_process._processGUID; - m_module = new AD7Module(); -// m_progNode = new AD7ProgramNode(m_process.PhysID, pid, exePath, new Guid(AD7Engine.Id)); - m_progNode = new AD7ProgramNode(m_process._processGUID, pid, exePath, new Guid(AD7Engine.Id)); - AddThreadsToProgram(); - - AD7EngineCreateEvent.Send(this); - - return VSConstants.S_OK; - } - else - { - GDBParser.exitGDB(); - VSNDK.Package.ControlDebugEngine.isDebugEngineRunning = false; - return VSConstants.E_FAIL; - } - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Resume a process launched by IDebugEngineLaunch2.LaunchSuspended. (http://msdn.microsoft.com/en-us/library/bb146261.aspx) - /// - /// An IDebugProcess2 object that represents the process to be resumed. - /// An IDebugProcess2 object that represents the process to be resumed. - int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process) - { - Debug.Assert(m_engineCallback != null); - - try - { - var xProcess = process as AD7Process; - if (xProcess == null) - { - return VSConstants.E_INVALIDARG; - } - - // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach - // which will complete the hookup with AD7 - IDebugPort2 port = null; - EngineUtils.RequireOk(process.GetPort(out port)); - - IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port; - - IDebugPortNotify2 portNotify = null; - EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify)); - - EngineUtils.RequireOk(portNotify.AddProgramNode(m_progNode)); - - Callback.OnModuleLoad(m_module); - - Callback.OnThreadStart(currentThread()); - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - return VSConstants.S_OK; - } - - - /// - /// This function is used to terminate a process. (http://msdn.microsoft.com/en-us/library/bb162314.aspx) - /// The debugger will call IDebugEngineLaunch2::CanTerminateProcess before calling this method. - /// - /// An IDebugProcess2 object that represents the process to be terminated. - /// VSConstants.S_OK. - int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 process) - { - CauseBreak(); - if (eDispatcher != null) - { - eDispatcher.killProcess(); - eDispatcher.endDebugSession(0); - } - - return VSConstants.S_OK; - } - - #endregion - - #region IDebugProgram2 Members - - - /// - /// Determines if a debug engine (DE) can detach from the program. (http://msdn.microsoft.com/en-us/library/bb161967.aspx) - /// - /// VSConstants.S_OK. - public int CanDetach() - { - // The VSNDK debug engine always supports detach - return VSConstants.S_OK; - } - - - /// - /// Requests that the program stop execution the next time one of its threads attempts to run. The debugger calls CauseBreak - /// when the user clicks on the pause button in VS. The debugger should respond by entering breakmode. - /// (http://msdn.microsoft.com/en-us/library/bb145018.aspx) - /// - /// VSConstants.S_OK. - public int CauseBreak() - { - return ((IDebugEngine2)this).CauseBreak(); - } - - - /// - /// Continues running this program from a stopped state. Any previous execution state (such as a step) is preserved, and - /// the program starts executing again. (http://msdn.microsoft.com/en-us/library/bb162148.aspx) - /// - /// An IDebugThread2 object that represents the thread. - /// VSConstants.S_OK. - public int Continue(IDebugThread2 pThread) - { - m_eventDispatcher.continueExecution(); - - return VSConstants.S_OK; - } - - - /// - /// Detaches a debug engine from the program. (http://msdn.microsoft.com/en-us/library/bb146228.aspx) - /// - /// VSConstants.S_OK. - public int Detach() - { - CauseBreak(); - if (m_breakpointManager != null) - m_breakpointManager.ClearBoundBreakpoints(); // TODO: Check if active bound BP list needs to be updated too? - - if (eDispatcher != null) - eDispatcher.endDebugSession(0); - - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of the code contexts for a given position in a source file. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb145902.aspx) - /// - /// An object representing an abstract position in a source file known to the IDE. - /// Returns an IEnumDebugCodeContexts2 object that contains a list of the code contexts. - /// Not implemented. - public int EnumCodeContexts(IDebugDocumentPosition2 pDocPos, out IEnumDebugCodeContexts2 ppEnum) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Retrieves a list of the code paths for a given position in a source file. EnumCodePaths is used for the step-into specific - /// feature -- right click on the current statement and decide which function to step into. This is not something that the - /// VSNDK debug engine supports. (http://msdn.microsoft.com/en-us/library/bb162326.aspx) - /// - /// The word under the cursor in the Source or Disassembly view in the IDE. - /// An IDebugCodeContext2 object representing the current code context. - /// An IDebugStackFrame2 object representing the stack frame associated with the current breakpoint. - /// Nonzero (TRUE) if in the Source view, or zero (FALSE) if in the Disassembly view. - /// Returns an IEnumCodePaths2 object containing a list of the code paths. - /// Returns an IDebugCodeContext2 object representing an additional code context to be set as a - /// breakpoint in case the chosen code path is skipped. This can happen in the case of a short-circuited Boolean expression, - /// for example. - /// VSConstants.E_NOTIMPL. - public int EnumCodePaths(string hint, IDebugCodeContext2 start, IDebugStackFrame2 frame, int fSource, out IEnumCodePaths2 pathEnum, out IDebugCodeContext2 safetyContext) - { - pathEnum = null; - safetyContext = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Retrieves a list of the modules that this program has loaded and is executing. - /// (http://msdn.microsoft.com/en-us/library/bb146980.aspx) - /// - /// Returns an IEnumDebugModules2 object that contains a list of the modules. - /// VSConstants.S_OK. - public int EnumModules(out IEnumDebugModules2 ppEnum) - { - ppEnum = new AD7ModuleEnum(new[] { m_module }); - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of the threads that are running in the program. (http://msdn.microsoft.com/en-us/library/bb145110.aspx) - /// - /// Returns an IEnumDebugThreads2 object that contains a list of the threads. - /// If successful, returns S_OK; otherwise, returns an error code. - public int EnumThreads(out IEnumDebugThreads2 ppEnum) - { - AD7Thread[] listThreads = null; - int currentThread = GetListOfThreads(out listThreads); - - // the following code seems to be weird but I had to update each field of this.m_process._threads because, when using - // "this.m_process._threads = listThreads;" without having a new thread, VS starts to duplicate the existing threads - // and, as a consequence, the call stack entries too. - - if ((currentThread == -1) || (listThreads == null)) - { - ppEnum = null; - return VSConstants.S_FALSE; - } - - if (listThreads.Length != this.m_threads.Length) - { - foreach (AD7Thread t in this.m_threads) - { - AD7ThreadDestroyEvent.Send(this, 0, t); - } - this.m_threads = null; - this.m_threads = new AD7Thread[listThreads.Length]; - this.m_threads = listThreads; - this._currentThreadIndex = currentThread; - foreach (AD7Thread t in this.m_threads) - { - m_engineCallback.OnThreadStart(t); - } - ppEnum = new AD7ThreadEnum(this.m_threads); - } - else - { - if (this._currentThreadIndex != currentThread) - { - this._currentThreadIndex = currentThread; - } - - for (int i = 0; i < listThreads.Length; i++) - { - if (this.m_threads[i]._engine != listThreads[i]._engine) - { - this.m_threads[i]._engine = listThreads[i]._engine; - } - if (this.m_threads[i]._threadDisplayName != listThreads[i]._threadDisplayName) - { - this.m_threads[i]._threadDisplayName = listThreads[i]._threadDisplayName; - } - if (this.m_threads[i]._id != listThreads[i]._id) - { - this.m_threads[i]._id = listThreads[i]._id; - } - if (this.m_threads[i]._state != listThreads[i]._state) - { - this.m_threads[i]._state = listThreads[i]._state; - } - if (this.m_threads[i]._targetID != listThreads[i]._targetID) - { - this.m_threads[i]._targetID = listThreads[i]._targetID; - } - if (this.m_threads[i]._priority != listThreads[i]._priority) - { - this.m_threads[i]._priority = listThreads[i]._priority; - } - if (this.m_threads[i]._line != listThreads[i]._line) - { - this.m_threads[i]._line = listThreads[i]._line; - } - if (this.m_threads[i]._filename != listThreads[i]._filename) - { - if (listThreads[i]._filename == "") - this.m_threads[i]._filename = ""; - else - this.m_threads[i]._filename = listThreads[i]._filename; - } - } - - ppEnum = new AD7ThreadEnum(this.m_threads); - } - return VSConstants.S_OK; - } - - - /// - /// Gets the program's properties. The VSNDK debug engine does not support this. - /// (http://msdn.microsoft.com/en-us/library/bb161801.aspx) - /// - /// Returns an IDebugProperty2 object that represents the program's properties. - /// Not implemented. - public int GetDebugProperty(out IDebugProperty2 ppProperty) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Gets the disassembly stream for this program or a part of this program. - /// The sample engine does not support dissassembly so it returns E_NOTIMPL - /// - /// Specifies a value from the DISASSEMBLY_STREAM_SCOPE enumeration that defines the scope of the - /// disassembly stream. - /// An object that represents the position of where to start the disassembly stream. - /// Returns an IDebugDisassemblyStream2 object that represents the disassembly stream. - /// VSConstants.E_NOTIMPL. - public int GetDisassemblyStream(enum_DISASSEMBLY_STREAM_SCOPE dwScope, IDebugCodeContext2 codeContext, out IDebugDisassemblyStream2 disassemblyStream) - { - disassemblyStream = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// This method gets the Edit and Continue (ENC) update for this program. A custom debug engine always returns E_NOTIMPL - /// - /// Returns an internal interface that can be used to update this program. - /// VSConstants.S_OK. - public int GetENCUpdate(out object update) - { - // The VSNDK debug engine does not participate in managed edit & continue. - update = null; - return VSConstants.S_OK; - } - - - /// - /// Gets the name and GUID of the debug engine running this program. (http://msdn.microsoft.com/en-us/library/bb145854.aspx) - /// - /// Returns the name of the DE running this program. - /// Returns the GUID of the DE running this program. - /// VSConstants.S_OK. - public int GetEngineInfo(out string engineName, out Guid engineGuid) - { - engineName = "VSNDK Debug Engine"; - engineGuid = new Guid(AD7Engine.Id); - - return VSConstants.S_OK; - } - - - /// - /// Retrieves the memory bytes occupied by the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145291.aspx) - /// - /// Returns an IDebugMemoryBytes2 object that represents the memory bytes of the program. - /// Not implemented. - public int GetMemoryBytes(out IDebugMemoryBytes2 ppMemoryBytes) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Gets the name of the program. The name returned by this method is always a friendly, user-displayable name that describes - /// the program. (http://msdn.microsoft.com/en-us/library/bb161279.aspx) - /// - /// Returns the name of the program. - /// VSConstants.S_OK. - public int GetName(out string programName) - { - if (this.m_progNode != null) - programName = this.m_progNode.m_programName; - else - programName = null; - return VSConstants.S_OK; - } - - - /// - /// Gets a GUID for this program. A debug engine (DE) must return the program identifier originally passed to the - /// IDebugProgramNodeAttach2::OnAttach or IDebugEngine2::Attach methods. This allows identification of the program - /// across debugger components. (http://msdn.microsoft.com/en-us/library/bb145581.aspx) - /// - /// Returns the GUID for this program. - /// VSConstants.S_OK. - public int GetProgramId(out Guid guidProgramId) - { - if (m_programGUID != null) - guidProgramId = m_programGUID; - else - guidProgramId = m_process._processGUID; - - return VSConstants.S_OK; - } - - - /// - /// Performs a step. This method is deprecated. Use the IDebugProcess3::Step method instead. - /// (http://msdn.microsoft.com/en-us/library/bb162134.aspx) - /// - /// An IDebugThread2 object that represents the thread being stepped. - /// A value from the STEPKIND enumeration that specifies the kind of step. - /// A value from the STEPUNIT enumeration that specifies the unit of step. - /// If successful, returns S_OK; otherwise, returns an error code. - public int Step(IDebugThread2 pThread, enum_STEPKIND sk, enum_STEPUNIT Step) - { - // Don't allow stepping through unknown code because it can lead to future problems with stepping and break-all. - if (VSNDK.DebugEngine.EventDispatcher.m_unknownCode) - { - m_state = AD7Engine.DE_STATE.STEP_MODE; - m_eventDispatcher.continueExecution(); - - return VSConstants.S_OK; - } - - if (sk == enum_STEPKIND.STEP_INTO) - { - // Equivalent to F11 hotkey. - // Sends the GDB command that resumes the execution of the inferior program, stopping at the next instruction, diving - // into function if it is a function call. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand("-exec-step --thread " + this.m_threads[this._currentThreadIndex]._id); - } - else if (sk == enum_STEPKIND.STEP_OVER) - { - // Equivalent to F10 hotkey. - // Sends the GDB command that resumes the execution of the inferior program, stopping at the next instruction, but - // without diving into functions. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand("-exec-next --thread " + this.m_threads[this._currentThreadIndex]._id); - } - else if (sk == enum_STEPKIND.STEP_OUT) - { - // Equivalent to Shift-F11 hotkey. - if (eDispatcher.getStackDepth(this.m_threads[this._currentThreadIndex]._id) > 1) - { - // Sends the GDB command that resumes the execution of the inferior program until the current function is exited. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand("-exec-finish --thread " + this.m_threads[this._currentThreadIndex]._id + " --frame 0"); - } - else - { - // If this the only frame left, do a step-over. - // Sends the GDB command that resumes the execution of the inferior program, stopping at the next instruction, but - // without diving into functions. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand("-exec-next --thread " + this.m_threads[this._currentThreadIndex]._id); - } - } - else if (sk == enum_STEPKIND.STEP_BACKWARDS) - { - return VSConstants.E_NOTIMPL; - } - else - { - m_engineCallback.OnStepComplete(); // Have to call this otherwise VS gets "stuck" - } - - // Transition DE state - m_state = AD7Engine.DE_STATE.STEP_MODE; - - return VSConstants.S_OK; - } - - - /// - /// Terminates the program. (http://msdn.microsoft.com/en-us/library/bb145919.aspx) - /// - /// VSConstants.S_OK. - public int Terminate() - { - return VSConstants.S_OK; - } - - - /// - /// Writes a dump to a file. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145827.aspx) - /// - /// A value from the DUMPTYPE enumeration that specifies the type of dump, for example, short or - /// long. - /// The URL to write the dump to. Typically, this is in the form of file://c:\path\filename.ext, - /// but may be any valid URL. - /// VSConstants.E_NOTIMPL. - public int WriteDump(enum_DUMPTYPE DUMPTYPE, string pszDumpUrl) - { - // The VSNDK debugger does not support creating or reading mini-dumps. - return VSConstants.E_NOTIMPL; - } - - #endregion - - #region IDebugProgram3 Members - - - /// - /// Executes the debugger program. The thread is returned to give the debugger information on which thread the user is - /// viewing when executing the program. ExecuteOnThread is called when the SDM wants execution to continue and have - /// stepping state cleared. (http://msdn.microsoft.com/en-us/library/bb145596.aspx) - /// - /// An IDebugThread2 object. - /// VSConstants.S_OK. - public int ExecuteOnThread(IDebugThread2 pThread) - { - m_eventDispatcher.continueExecution(); - - return VSConstants.S_OK; - } - - #endregion - - #region IDebugEngineProgram2 Members - - - /// - /// Stops all threads running in this program. This method is called when this program is being debugged in a multi-program - /// environment. When a stopping event from some other program is received, this method is called on this program. The - /// implementation of this method should be asynchronous; that is, not all threads should be required to be stopped before - /// this method returns. The implementation of this method may be as simple as calling the IDebugProgram2::CauseBreak method - /// on this program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb146567.aspx) - /// - /// The VSNDK debug engine only supports debugging native applications and therefore only has one program per-process - /// - /// VSConstants.E_NOTIMPL. - public int Stop() - { - return VSConstants.E_NOTIMPL; - } - - - /// - /// Allows (or disallows) expression evaluation to occur on the given thread, even if the program has stopped. - /// WatchForExpressionEvaluationOnThread is used to cooperate between two different engines debugging the same process. - /// The VSNDK debug engine doesn't cooperate with other engines, so it has nothing to do here. - /// (http://msdn.microsoft.com/en-us/library/bb144913.aspx) - /// - /// An IDebugProgram2 object representing the program that is evaluating an expression. - /// Specifies the identifier of the thread. - /// A combination of flags from the EVALFLAGS enumeration that specify how the evaluation is to be - /// performed. - /// An IDebugEventCallback2 object to be used to send debug events that occur during expression - /// evaluation. - /// If non-zero (TRUE), allows expression evaluation on the thread identified by dwTid; otherwise, zero - /// (FALSE) disallows expression evaluation on that thread. - /// VSConstants.S_OK. - public int WatchForExpressionEvaluationOnThread(IDebugProgram2 pOriginatingProgram, uint dwTid, uint dwEvalFlags, IDebugEventCallback2 pExprCallback, int fWatch) - { - return VSConstants.S_OK; - } - - - /// - /// Watches for execution (or stops watching for execution) to occur on the given thread. WatchForThreadStep is used to - /// cooperate between two different engines debugging the same process. The VSNDK debug engine doesn't cooperate with other - /// engines, so it has nothing to do here. (http://msdn.microsoft.com/en-us/library/bb161406.aspx) - /// - /// An IDebugProgram2 object representing the program being stepped. - /// Specifies the identifier of the thread to watch. - /// Non-zero (TRUE) means start watching for execution on the thread identified by dwTid; otherwise, - /// zero (FALSE) means stop watching for execution on dwTid. - /// Specifies a frame index that controls the step type. - /// VSConstants.S_OK. - public int WatchForThreadStep(IDebugProgram2 pOriginatingProgram, uint dwTid, int fWatch, uint dwFrame) - { - return VSConstants.S_OK; - } - - #endregion - - #region IDebugSymbolSettings100 members - - - /// - /// The SDM will call this method on the debug engine when it is created, to notify it of the user's - /// symbol settings in Tools->Options->Debugging->Symbols. (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugsymbolsettings100.setsymbolloadstate.aspx) - /// - /// true if 'Automatically load symbols: Only for specified modules' is checked. - /// true if 'Specify modules'->'Always load symbols next to the modules' is checked. - /// semicolon-delimited list of modules when automatically loading 'Only specified modules' - /// semicolon-delimited list of modules when automatically loading 'All modules, unless excluded' - /// VSConstants.S_OK. - public int SetSymbolLoadState(int bIsManual, int bLoadAdjacent, string strIncludeList, string strExcludeList) - { - return VSConstants.S_OK; - } - #endregion - - #region Thread methods - - - /// - /// Verify if the stack frame information specified by "flags" were already evaluated. - /// - /// Thread ID. - /// Specifies the information to verify about a stack frame object. - /// If successful, returns TRUE; otherwise, returns FALSE. - public bool evaluatedTheseFlags(string threadId, enum_FRAMEINFO_FLAGS flags) - { - if (this.thread != null) - { - int currentFlags = Convert.ToInt32(flags); - int i = 0; - // looking for the "threadId" thread. - for (; i < this.thread.Length; i++) - { - if (this.thread[i]._id == threadId) - break; - } - if (i < this.thread.Length) - { - if (this.thread[i]._alreadyEvaluated == currentFlags) - { - // This stack frame information were already evaluated. - return true; - } - else - { - // This stack frame information were not evaluated before. Modifying the _alreadyEvaluated flag. - this.thread[i]._alreadyEvaluated = currentFlags; - } - } - } - return false; - } - - - /// - /// Clean the "flags" data (_alreadyEvaluated) that are stored in each thread without resetting the stack frames. This operation - /// must be done whenever the stack frames for a given thread have to be evaluated, like when the user changes the current frame - /// or when he wants to investigate different threads in break mode, for example. - /// - public void cleanEvaluatedThreads() - { - if (this.thread != null) - { - for (int i = 0; i < this.thread.Length; i++) - { - this.thread[i]._alreadyEvaluated = 0; - } - } - } - - - /// - /// Reset stack frames for each thread. This operation must be performed before changing the state to break mode, like when a - /// breakpoint is hit, for example. - /// - public void resetStackFrames() - { - foreach (AD7Thread t in m_threads) - { - if (t.__stackFrames != null) - { - t.__stackFrames.Clear(); - t.__stackFrames = null; - } - } - } - - - /// - /// Update the list of threads. This operation must be performed whenever the list of threads changes (a thread exits or is - /// created) and before entering in break mode. - /// - public void UpdateListOfThreads() - { - foreach (AD7Thread t in this.m_threads) - { - // Send events to VS to destroy its current debugged threads. - AD7ThreadDestroyEvent.Send(this, 0, t); - } - - this.m_threads = null; - // Get the current list of threads and store them into a temporary variable listThreads. - this._currentThreadIndex = GetListOfThreads(out this.m_threads); - - if ((this._currentThreadIndex == -1) || (this.m_threads == null)) - return; - - // Send events to VS to add this list of debugged threads. - foreach (AD7Thread t in this.m_threads) - { - m_engineCallback.OnThreadStart(t); - } - - this._updateThreads = false; - } - - - /// - /// Get the list of threads being debugged, also returning the index of the current thread (or -1 in case of error) - /// - /// Returns the current list of threads that are being debugged. - /// Returns the index of the current thread in the list of threads (or -1 in case of error) - public int GetListOfThreads(out AD7Thread[] threadObjects) - { - // Gets the parsed response for the GDB/MI command that ask for information about all threads. - // (http://www.sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html) - string threadResponse = GDBParser.parseCommand(@"-thread-info", 22); - string[] threadStrings = threadResponse.Split('#'); - cleanEvaluatedThreads(); - - // Query the threads depth without inquiring GDB. - int numThreads = threadStrings.Length - 1; // the last item in threadStrings is not a thread but the current thread ID. - string currentThread = threadStrings[threadStrings.Length - 1]; - if (numThreads < 1) - { - threadObjects = null; - return -1; - } - - try - { - threadObjects = new AD7Thread[numThreads]; - int currentThreadIndex = -1; - - for (int i = 0; i < numThreads; i++) - { - string[] threadInfo = threadStrings[i].Split(';'); - - // Setting the current thread index. - if (currentThread == threadInfo[0]) - { - currentThreadIndex = i; - } - - // Each threadInfo has one of these two formats: - // with 5 elements: ID; State; targetID; details (not used); name -> this format is normally used for external code. - // with 7 elements: ID; State; targetID; details (not used); full short-path filename; line; name - if (threadInfo.Length > 5) - threadObjects[i] = new AD7Thread(this, threadInfo[0], threadInfo[2], threadInfo[1], "Normal", threadInfo[6], threadInfo[4], threadInfo[5]); - else - threadObjects[i] = new AD7Thread(this, threadInfo[0], threadInfo[2], threadInfo[1], "Normal", threadInfo[4], "", ""); - } - return currentThreadIndex; - } - catch (ComponentException e) - { - threadObjects = null; - return -1; - } - catch (Exception e) - { - threadObjects = null; - return -1; - } - } - - - /// - /// Returns the current thread. - /// - /// If successful, returns the current thread; otherwise, returns NULL. - public AD7Thread currentThread() - { - if (_currentThreadIndex != -1) - return m_threads[_currentThreadIndex]; - return null; - } - - - /// - /// Returns the thread data structure with a given ID. - /// - /// The ID of the thread to search for. - /// If successful, returns the selected thread; otherwise, returns NULL. - public AD7Thread selectThread(string id) - { - for (int i = 0; i < this.m_threads.Length; i++) - { - if (this.m_threads[i]._id == id) - return (m_threads[i]); - } - return null; - } - - - /// - /// Set a given thread as the current one. - /// - /// The ID of the thread. - public void setAsCurrentThread(string id) - { - for (int i = 0; i < this.m_threads.Length; i++) - { - if (this.m_threads[i]._id == id) - { - this._currentThreadIndex = i; - break; - } - } - } - - - /// - /// Add threads for a program when lauching it and the debugger (IDebugEngineLaunch2.LaunchSuspended). - /// - /// VSConstants.S_OK. - public int AddThreadsToProgram() - { - m_threads = null; - _currentThreadIndex = GetListOfThreads(out m_threads); - if (_currentThreadIndex != -1) - { - foreach (AD7Thread t in m_threads) - { - m_engineCallback.OnThreadStart(t); - } - } - else - m_engineCallback.OnThreadStart(null); - return VSConstants.S_OK; - } - - #endregion - - #region Deprecated interface methods - // These methods are not called by the Visual Studio debugger, so they don't need to be implemented - - - /// - /// Retrieves a list of all programs being debugged by a debug engine (DE). Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb146175.aspx) - /// - /// Returns an object that contains a list of all programs being debugged by a DE. - /// VSConstants.E_NOTIMPL. - int IDebugEngine2.EnumPrograms(out IEnumDebugPrograms2 programs) - { - Debug.Fail("This function is not called by the debugger"); - - programs = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Attaches to the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb161973.aspx) - /// - /// An IDebugEventCallback2 object to be used for debug event notification. - /// VSConstants.E_NOTIMPL. - public int Attach(IDebugEventCallback2 pCallback) - { - Debug.Fail("This function is not called by the debugger"); - - return VSConstants.E_NOTIMPL; - } - - - /// - /// Get the process that this program is running in. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145293.aspx) - /// - /// Returns the IDebugProcess2 interface that represents the process. - /// VSConstants.E_NOTIMPL. - public int GetProcess(out IDebugProcess2 process) - { - Debug.Fail("This function is not called by the debugger"); - - process = null; - return VSConstants.E_NOTIMPL; - } - - - /// TODO: Verify if this method is called or not by VS. - /// Continues running this program from a stopped state. Any previous execution state (such as a step) is cleared, and the - /// program starts executing again. (http://msdn.microsoft.com/en-us/library/bb162315.aspx) - /// - /// VSConstants.S_OK. - public int Execute() - { - m_eventDispatcher.continueExecution(); - return VSConstants.S_OK; - } - - #endregion - } -} - diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Enums.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Enums.cs deleted file mode 100644 index c41da31b..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Enums.cs +++ /dev/null @@ -1,438 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; - - -namespace VSNDK.DebugEngine -{ - #region Base Class - - - /// - /// These classes use a generic enumerator implementation to create the various enumerators required by the engine. - /// They allow the enumeration of everything from programs to breakpoints. - /// - /// Array of T elements. - /// Enumerator interface. - class AD7Enum where I: class - { - readonly T[] m_data; - uint m_position; - - - /// - /// Constructor. - /// - /// Array of T elements. - public AD7Enum(T[] data) - { - m_data = data; - m_position = 0; - } - - - /// - /// Returns a copy of the current enumeration as a separate object. Not implemented. - /// - /// Returns a copy of this enumeration as a separate object. - /// Not implemented. - public int Clone(out I ppEnum) - { - ppEnum = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Returns the number of elements in the enumeration. - /// - /// Returns the number of elements in the enumeration. - /// VSConstants.S_OK. - public int GetCount(out uint pcelt) - { - pcelt = (uint)m_data.Length; - return VSConstants.S_OK; - } - - - /// - /// Returns the next set of elements from the enumeration. - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of T elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, T[] rgelt, out uint celtFetched) - { - return Move(celt, rgelt, out celtFetched); - } - - - /// - /// Resets the enumeration to the first element. - /// - /// VSConstants.S_OK. - public int Reset() - { - lock (this) - { - m_position = 0; - - return VSConstants.S_OK; - } - } - - - /// - /// Skips over the specified number of elements. - /// - /// Number of elements to skip. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Skip(uint celt) - { - uint celtFetched; - - return Move(celt, null, out celtFetched); - } - - - /// - /// Returns/Skips over the specified number of elements. - /// - /// Number of elements to retrieve/skip. - /// Array of T elements to be filled in. - /// Returns the number of elements actually returned/skipped in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - private int Move(uint celt, T[] rgelt, out uint celtFetched) - { - lock (this) - { - int hr = VSConstants.S_OK; - celtFetched = (uint)m_data.Length - m_position; - - if (celt > celtFetched) - { - hr = VSConstants.S_FALSE; - } - else if (celt < celtFetched) - { - celtFetched = celt; - } - - if (rgelt != null) - { - for (int c = 0; c < celtFetched; c++) - { - rgelt[c] = m_data[m_position + c]; - } - } - - m_position += celtFetched; - - return hr; - } - } - } - #endregion Base Class - - - - - /// - /// This class enumerates the processes running on a debug port. (http://msdn.microsoft.com/en-ca/library/bb145005.aspx) - /// - class AD7ProcessEnum : AD7Enum, IEnumDebugProcesses2 - { - - /// - /// Constructor. - /// - /// Array of IDebugProcess2 elements. - public AD7ProcessEnum(IDebugProcess2[] data) - : base(data) - { - } - - - /// - /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb147027.aspx) - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of IDebugProcess2 elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, IDebugProcess2[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - - - /// - /// This class enumerates the ports of a machine or port supplier. (http://msdn.microsoft.com/en-ca/library/bb145137.aspx) - /// - class AD7PortEnum : AD7Enum, IEnumDebugPorts2 - { - - /// - /// Constructor. - /// - /// Array of IDebugPort2 elements. - public AD7PortEnum(IDebugPort2[] data) - : base(data) - { - } - - - /// - /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb147027.aspx) - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of IDebugPort2 elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, IDebugPort2[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - - - - - /// - /// This class enumerates the programs running in the current debug session. (http://msdn.microsoft.com/en-ca/library/bb146727.aspx) - /// - class AD7ProgramEnum : AD7Enum, IEnumDebugPrograms2 - { - - /// - /// Constructor. - /// - /// Array of IDebugProgram2 elements. - public AD7ProgramEnum(IDebugProgram2[] data) : base(data) - { - } - - - /// - /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb147027.aspx) - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of IDebugProgram2 elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, IDebugProgram2[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - - - /// - /// This class enumerates FRAMEINFO structures. (http://msdn.microsoft.com/en-us/library/bb147119.aspx) - /// - class AD7FrameInfoEnum : AD7Enum, IEnumDebugFrameInfo2 - { - - /// - /// Constructor. - /// - /// Array of FRAMEINFO elements. - public AD7FrameInfoEnum(FRAMEINFO[] data) - : base(data) - { - } - - - /// - /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-us/library/bb146293.aspx) - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of FRAMEINFO elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, FRAMEINFO[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - - - /// - /// This class enumerates DEBUG_PROPERTY_INFO structures. (http://msdn.microsoft.com/en-ca/library/bb162336.aspx) - /// - class AD7PropertyInfoEnum : AD7Enum, IEnumDebugPropertyInfo2 - { - - /// - /// Constructor. - /// - /// Array of DEBUG_PROPERTY_INFO elements. - public AD7PropertyInfoEnum(DEBUG_PROPERTY_INFO[] data) - : base(data) - { - } - } - - - /// - /// This class enumerates the threads running in the current debug session. (http://msdn.microsoft.com/en-ca/library/bb145142.aspx) - /// - class AD7ThreadEnum : AD7Enum, IEnumDebugThreads2 - { - - /// - /// Constructor. - /// - /// Array of IDebugThread2 elements. - public AD7ThreadEnum(IDebugThread2[] threads) - : base(threads) - { - - } - - - /// - /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb161679.aspx) - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of IDebugThread2 elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, IDebugThread2[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - - - /// - /// This class enumerates a list of modules. (http://msdn.microsoft.com/en-ca/library/bb145925.aspx) - /// - class AD7ModuleEnum : AD7Enum, IEnumDebugModules2 - { - - /// - /// Constructor. - /// - /// Array of IDebugModule2 elements. - public AD7ModuleEnum(IDebugModule2[] modules) - : base(modules) - { - - } - - - /// - /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb145898.aspx) - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of IDebugModule2 elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, IDebugModule2[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - - - /// - /// This class enumerates DEBUG_PROPERTY_INFO structures. (http://msdn.microsoft.com/en-ca/library/bb162336.aspx) - /// - class AD7PropertyEnum : AD7Enum, IEnumDebugPropertyInfo2 - { - - /// - /// Constructor. - /// - /// Array of DEBUG_PROPERTY_INFO elements. - public AD7PropertyEnum(DEBUG_PROPERTY_INFO[] properties) - : base(properties) - { - - } - } - - - /// - /// This class enumerates the code contexts associated with the debug session, or with a particular program or document. - /// (http://msdn.microsoft.com/en-us/library/bb146612.aspx) - /// - class AD7CodeContextEnum : AD7Enum, IEnumDebugCodeContexts2 - { - - /// - /// Constructor. - /// - /// Array of IDebugCodeContext2 elements. - public AD7CodeContextEnum(IDebugCodeContext2[] codeContexts) - : base(codeContexts) - { - - } - - - /// - /// Returns the next set of elements from the enumeration. ()http://msdn.microsoft.com/en-us/library/bb145085.aspx - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of IDebugCodeContext2 elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, IDebugCodeContext2[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - - - /// - /// This class enumerates the bound breakpoints associated with a pending breakpoint or breakpoint bound event. - /// (http://msdn.microsoft.com/en-ca/library/bb162182.aspx) - /// - class AD7BoundBreakpointsEnum : AD7Enum, IEnumDebugBoundBreakpoints2 - { - - /// - /// Constructor. - /// - /// Array of IDebugBoundBreakpoint2 elements. - public AD7BoundBreakpointsEnum(IDebugBoundBreakpoint2[] breakpoints) - : base(breakpoints) - { - - } - - - /// - /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb161772.aspx) - /// - /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. - /// Array of IDebugBoundBreakpoint2 elements to be filled in. - /// Returns the number of elements actually returned in rgelt. - /// If successful, returns S_OK. If not, returns S_FALSE. - public int Next(uint celt, IDebugBoundBreakpoint2[] rgelt, ref uint celtFetched) - { - return Next(celt, rgelt, out celtFetched); - } - } - -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Events.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Events.cs deleted file mode 100644 index 7588337b..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Events.cs +++ /dev/null @@ -1,767 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; - -// This file contains the various event objects that are sent to the debugger from the VSNDK debug engine via IDebugEventCallback2::Event. -// These are used in EngineCallback.cs. -// The events are how the engine tells the debugger about what is happening in the debuggee process. -// There are four base classes the other events derive from: AD7AsynchronousEvent, AD7StoppingEvent, AD7SynchronousEvent and -// AD7SynchronousStoppingEvent. Each of them implements the IDebugEvent2.GetAttributes method for the type of event they represent. -// Most events sent by the debugger are asynchronous ones. - -namespace VSNDK.DebugEngine -{ - #region Event base classes - - - /// - /// Used to communicate both critical debug information and non-critical information. - /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) - /// - class AD7AsynchronousEvent : IDebugEvent2 - { - public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS; - - - /// - /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) - /// - /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. - /// VSConstants.S_OK. - int IDebugEvent2.GetAttributes(out uint eventAttributes) - { - eventAttributes = Attributes; - return VSConstants.S_OK; - } - } - - - /// - /// Used to communicate both critical debug information and non-critical information. - /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) - /// - class AD7StoppingEvent : IDebugEvent2 - { - public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_ASYNC_STOP; - - - /// - /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) - /// - /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. - /// VSConstants.S_OK. - int IDebugEvent2.GetAttributes(out uint eventAttributes) - { - eventAttributes = Attributes; - return VSConstants.S_OK; - } - } - - - /// - /// Used to communicate both critical debug information and non-critical information. - /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) - /// - class AD7SynchronousEvent : IDebugEvent2 - { - public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; - - - /// - /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) - /// - /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. - /// VSConstants.S_OK. - int IDebugEvent2.GetAttributes(out uint eventAttributes) - { - eventAttributes = Attributes; - return VSConstants.S_OK; - } - } - - - /// - /// Used to communicate both critical debug information and non-critical information. - /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) - /// - class AD7SynchronousStoppingEvent : IDebugEvent2 - { - public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_STOPPING | (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; - - - /// - /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) - /// - /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. - /// VSConstants.S_OK. - int IDebugEvent2.GetAttributes(out uint eventAttributes) - { - eventAttributes = Attributes; - return VSConstants.S_OK; - } - } - - #endregion - - - /// - /// The debug engine (DE) sends this interface to the session debug manager (SDM) when an instance of the DE is created. - /// (http://msdn.microsoft.com/en-us/library/bb145830.aspx) - /// - sealed class AD7EngineCreateEvent : AD7AsynchronousEvent, IDebugEngineCreateEvent2 - { - public const string IID = "FE5B734C-759D-4E59-AB04-F103343BDD06"; - private IDebugEngine2 m_engine; - - - /// - /// Constructor. - /// - /// The AD7Engine object that represents the DE. - AD7EngineCreateEvent(AD7Engine engine) - { - m_engine = engine; - } - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - public static void Send(AD7Engine engine) - { - AD7EngineCreateEvent eventObject = new AD7EngineCreateEvent(engine); - engine.Callback.Send(eventObject, IID, null, null); - } - - - /// - /// Retrieves the object that represents the newly created debug engine (DE). - /// (http://msdn.microsoft.com/en-us/library/bb145143.aspx) - /// - /// Returns an AD7Engine object that represents the newly created DE. - /// VSConstants.S_OK. - int IDebugEngineCreateEvent2.GetEngine(out IDebugEngine2 engine) - { - engine = m_engine; - - return VSConstants.S_OK; - } - } - - - /// - /// This interface is sent when a process is launched. (http://msdn.microsoft.com/en-ca/library/bb161755.aspx) - /// - class AD7ProcessCreateEvent : IDebugEvent2, IDebugProcessCreateEvent2 - { - private Guid IID = new Guid("9020DEE3-362D-4FF2-8CA9-8F6791F0EC85"); - public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_IMMEDIATE; - - /// - /// Gets the GUID of this event. - /// - /// Returns the GUID of this event. - public Guid getGuid() - { - return IID; - } - - /// - /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) - /// - /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. - /// VSConstants.S_OK. - int IDebugEvent2.GetAttributes(out uint eventAttributes) - { - eventAttributes = Attributes; - return VSConstants.S_OK; - } - } - - - /// - /// This interface is sent when a process is terminated, exits atypically, or is detached from. - /// (http://msdn.microsoft.com/en-us/library/bb145152.aspx) - /// - class AD7ProcessDestroyEvent : IDebugEvent2, IDebugProcessDestroyEvent2 - { - private Guid IID = new Guid("29DAA0AC-C718-4F93-A11E-6D15681476C7"); - public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_IMMEDIATE; - - /// - /// Gets the GUID of this event. - /// - /// Returns the GUID of this event. - public Guid getGuid() - { - return IID; - } - - /// - /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) - /// - /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. - /// VSConstants.S_OK. - int IDebugEvent2.GetAttributes(out uint eventAttributes) - { - eventAttributes = Attributes; - return VSConstants.S_OK; - } - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program is attached to. - /// (http://msdn.microsoft.com/en-ca/library/bb161345.aspx) - /// - sealed class AD7ProgramCreateEvent : AD7AsynchronousEvent, IDebugProgramCreateEvent2 - { - public const string IID = "96CD11EE-ECD4-4E89-957E-B5D496FC4139"; - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - internal static void Send(AD7Engine engine) - { - AD7ProgramCreateEvent eventObject = new AD7ProgramCreateEvent(); - engine.Callback.Send(eventObject, IID, null); - } - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when asynchronous expression evaluation - /// is complete. (http://msdn.microsoft.com/en-ca/library/bb161810.aspx) - /// - sealed class AD7ExpressionEvaluationCompleteEvent : AD7AsynchronousEvent, IDebugExpressionEvaluationCompleteEvent2 - { - public const string IID = "C0E13A85-238A-4800-8315-D947C960A843"; - private readonly IDebugExpression2 m_expression; - private readonly IDebugProperty2 m_property; - - - /// - /// Constructor. - /// - /// The IDebugExpression2 object that represents the expression. - /// The IDebugProperty2 object that represents the result of the expression evaluation. - public AD7ExpressionEvaluationCompleteEvent(IDebugExpression2 expression, IDebugProperty2 property) - { - this.m_expression = expression; - this.m_property = property; - } - - - /// - /// Gets the original expression. (http://msdn.microsoft.com/en-ca/library/bb162323.aspx) - /// - /// Returns an IDebugExpression2 object that represents the expression that was parsed. - /// VSConstants.S_OK. - public int GetExpression(out IDebugExpression2 ppExpr) - { - ppExpr = m_expression; - return VSConstants.S_OK; - } - - - /// - /// Gets the result of expression evaluation. (http://msdn.microsoft.com/en-ca/library/bb161962.aspx) - /// - /// Returns an IDebugProperty2 object that represents the result of the expression evaluation. - /// VSConstants.S_OK. - public int GetResult(out IDebugProperty2 ppResult) - { - ppResult = m_property; - return VSConstants.S_OK; - } - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a module is loaded or unloaded. - /// (http://msdn.microsoft.com/en-ca/library/bb146706.aspx) - /// - sealed class AD7ModuleLoadEvent : AD7AsynchronousEvent, IDebugModuleLoadEvent2 - { - public const string IID = "989DB083-0D7C-40D1-A9D9-921BF611A4B2"; - - readonly AD7Module m_module; - readonly bool m_fLoad; - - - /// - /// Constructor. - /// - /// The IDebugModule2 object that represents the module which is loading or unloading. - /// onzero (TRUE) if the module is loading and zero (FALSE) if the module is unloading. - public AD7ModuleLoadEvent(AD7Module module, bool fLoad) - { - m_module = module; - m_fLoad = fLoad; - } - - - /// - /// Gets the module that is being loaded or unloaded. (http://msdn.microsoft.com/en-ca/library/bb161763.aspx) - /// - /// Returns an IDebugModule2 object that represents the module which is loading or unloading. - /// Returns an optional message describing this event. If this parameter is a null value, no message - /// is requested. - /// Nonzero (TRUE) if the module is loading and zero (FALSE) if the module is unloading. If this - /// parameter is a null value, no status is requested. - /// VSConstants.S_OK. - int IDebugModuleLoadEvent2.GetModule(out IDebugModule2 module, ref string debugMessage, ref int fIsLoad) - { - module = m_module; - - if (m_fLoad) - { - fIsLoad = 1; - } - else - { - fIsLoad = 0; - } - - return VSConstants.S_OK; - } - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - /// The IDebugModule2 object that represents the module which is loading or unloading. - /// onzero (TRUE) if the module is loading and zero (FALSE) if the module is unloading. - internal static void Send(AD7Engine engine, AD7Module aModule, bool fLoad) - { - var eventObject = new AD7ModuleLoadEvent(aModule, fLoad); - engine.Callback.Send(eventObject, IID, null); - } - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program has run to completion - /// or is otherwise destroyed. (http://msdn.microsoft.com/en-ca/library/bb161972.aspx) - /// - sealed class AD7ProgramDestroyEvent : AD7SynchronousEvent, IDebugProgramDestroyEvent2 - { - public const string IID = "E147E9E3-6440-4073-A7B7-A65592C714B5"; - - readonly uint m_exitCode; - - - /// - /// Constructor. - /// - /// The program's exit code. - public AD7ProgramDestroyEvent(uint exitCode) - { - m_exitCode = exitCode; - } - - #region IDebugProgramDestroyEvent2 Members - - - /// - /// Gets the program's exit code. (http://msdn.microsoft.com/en-ca/library/bb146724.aspx) - /// - /// Returns the program's exit code. - /// VSConstants.S_OK. - int IDebugProgramDestroyEvent2.GetExitCode(out uint exitCode) - { - exitCode = m_exitCode; - return VSConstants.S_OK; - } - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - /// The program's exit code. - internal static void Send(AD7Engine engine, uint exitCode) - { - var eventObject = new AD7ProgramDestroyEvent(exitCode); - engine.Callback.Send(eventObject, IID, null); - } - - #endregion - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a thread is created in a program - /// being debugged. (http://msdn.microsoft.com/en-ca/library/bb161327.aspx) - /// - sealed class AD7ThreadCreateEvent : AD7AsynchronousEvent, IDebugThreadCreateEvent2 - { - public const string IID = "2090CCFC-70C5-491D-A5E8-BAD2DD9EE3EA"; - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a thread has run to completion. - /// (http://msdn.microsoft.com/en-ca/library/bb162330.aspx) - /// - sealed class AD7ThreadDestroyEvent : AD7AsynchronousEvent, IDebugThreadDestroyEvent2 - { - public const string IID = "2C3B7532-A36F-4A6E-9072-49BE649B8541"; - - readonly uint m_exitCode; - - - /// - /// Constructor. - /// - /// The thread's exit code. - public AD7ThreadDestroyEvent(uint exitCode) - { - m_exitCode = exitCode; - } - - #region IDebugThreadDestroyEvent2 Members - - - /// - /// Gets the exit code for a thread. (http://msdn.microsoft.com/en-ca/library/bb146996.aspx) - /// - /// Returns the thread's exit code. - /// VSConstants.S_OK. - int IDebugThreadDestroyEvent2.GetExitCode(out uint exitCode) - { - exitCode = m_exitCode; - - return VSConstants.S_OK; - } - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - /// The thread's exit code. - /// The AD7Thread object that represents the thread. - internal static void Send(AD7Engine engine, uint exitCode, AD7Thread thread) - { - var eventObject = new AD7ThreadDestroyEvent(exitCode); - if (thread == null) - { - foreach (AD7Thread t in engine.thread) - { - engine.Callback.Send(eventObject, IID, t); - } - engine._currentThreadIndex = -1; - } - else - { - engine.Callback.Send(eventObject, IID, thread); - } - } - - #endregion - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program is loaded, but before - /// any code is executed. (http://msdn.microsoft.com/en-ca/library/bb145834.aspx) - /// - sealed class AD7LoadCompleteEvent : AD7StoppingEvent, IDebugLoadCompleteEvent2 - { - public const string IID = "B1844850-1349-45D4-9F12-495212F5EB0B"; - - - /// - /// Constructor. - /// - public AD7LoadCompleteEvent() - { - } - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - /// The AD7Thread object that represents the thread. - internal static void Send(AD7Engine aEngine, AD7Thread aThread) - { - var xMessage = new AD7LoadCompleteEvent(); - aEngine.Callback.Send(xMessage, IID, aThread); - } - } - - - /// - /// This interface tells the session debug manager (SDM) that an asynchronous break has been successfully completed. - /// (http://msdn.microsoft.com/en-ca/library/bb146180.aspx) - /// - sealed class AD7AsyncBreakCompleteEvent : AD7StoppingEvent, IDebugBreakEvent2 - { - public const string IID = "c7405d1d-e24b-44e0-b707-d8a5a4e1641b"; - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) to output a string. - /// (http://msdn.microsoft.com/en-ca/library/bb146756.aspx) - /// - sealed class AD7OutputDebugStringEvent : AD7AsynchronousEvent, IDebugOutputStringEvent2 - { - public const string IID = "569c4bb1-7b82-46fc-ae28-4536ddad753e"; - - private string m_str; - - - /// - /// Constructor. - /// - /// The displayable message. - public AD7OutputDebugStringEvent(string str) - { - m_str = str; - } - - #region IDebugOutputStringEvent2 Members - - /// - /// Gets the displayable message. (http://msdn.microsoft.com/en-ca/library/bb162293.aspx) - /// - /// Returns the displayable message. - /// VSConstants.S_OK. - int IDebugOutputStringEvent2.GetString(out string pbstrString) - { - pbstrString = m_str; - return VSConstants.S_OK; - } - - #endregion - } - - - /// - /// This interface is sent by the debug engine (DE) to indicate that the debugging symbols for a module being debugged have - /// been loaded. (http://msdn.microsoft.com/en-ca/library/bb160924.aspx) - /// - sealed class AD7SymbolSearchEvent : AD7AsynchronousEvent, IDebugSymbolSearchEvent2 - { - public const string IID = "638F7C54-C160-4c7b-B2D0-E0337BC61F8C"; - - private AD7Module m_module; - private string m_searchInfo; - private uint m_symbolFlags; - - - /// - /// Constructor. - /// - /// The AD7Module object representing the module for which the symbols were loaded. - /// The string containing any error messages from the module. - /// A combination of flags from the MODULE_INFO_FLAGS enumeration indicating whether any - /// symbols were loaded. - public AD7SymbolSearchEvent(AD7Module module, string searchInfo, uint symbolFlags) - { - m_module = module; - m_searchInfo = searchInfo; - m_symbolFlags = symbolFlags; - } - - #region IDebugSymbolSearchEvent2 Members - - /// - /// Called by an event handler to retrieve results about a symbol load process. - /// (http://msdn.microsoft.com/en-ca/library/bb161324.aspx) - /// - /// An IDebugModule3 object representing the module for which the symbols were loaded. - /// Returns a string containing any error messages from the module. If there is no error, - /// then this string will just contain the module's name but it is never empty. - /// A combination of flags from the MODULE_INFO_FLAGS enumeration indicating whether any - /// symbols were loaded. - /// VSConstants.S_OK. - int IDebugSymbolSearchEvent2.GetSymbolSearchInfo(out IDebugModule3 pModule, ref string pbstrDebugMessage, enum_MODULE_INFO_FLAGS[] pdwModuleInfoFlags) - { - pModule = m_module; - pbstrDebugMessage = m_searchInfo; - pdwModuleInfoFlags[0] = (enum_MODULE_INFO_FLAGS)m_symbolFlags; - - return VSConstants.S_OK; - } - - #endregion - } - - - /// - /// This interface tells the session debug manager (SDM) that a pending breakpoint has been successfully bound to a loaded program. - /// (http://msdn.microsoft.com/en-us/library/bb145356.aspx) - /// - sealed class AD7BreakpointBoundEvent : AD7AsynchronousEvent, IDebugBreakpointBoundEvent2 - { - public const string IID = "1dddb704-cf99-4b8a-b746-dabb01dd13a0"; - - private AD7PendingBreakpoint m_pendingBreakpoint; - private AD7BoundBreakpoint m_boundBreakpoint; - - - /// - /// Constructor. - /// - /// The AD7PendingBreakpoint object that represents the pending breakpoint being bound. - /// The AD7BoundBreakpoint object that represents the breakpoint being bound. - public AD7BreakpointBoundEvent(AD7PendingBreakpoint pendingBreakpoint, AD7BoundBreakpoint boundBreakpoint) - { - m_pendingBreakpoint = pendingBreakpoint; - m_boundBreakpoint = boundBreakpoint; - } - - #region IDebugBreakpointBoundEvent2 Members - - /// - /// Creates an enumerator of breakpoints that were bound on this event. (http://msdn.microsoft.com/en-us/library/bb145322.aspx) - /// - /// Returns an IEnumDebugBoundBreakpoints2 object that enumerates all the breakpoints bound from - /// this event. - /// VSConstants.S_OK. - int IDebugBreakpointBoundEvent2.EnumBoundBreakpoints(out IEnumDebugBoundBreakpoints2 ppEnum) - { - IDebugBoundBreakpoint2[] boundBreakpoints = new IDebugBoundBreakpoint2[1]; - boundBreakpoints[0] = m_boundBreakpoint; - ppEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); - return VSConstants.S_OK; - } - - - /// - /// Gets the pending breakpoint that is being bound. (http://msdn.microsoft.com/en-us/library/bb146558.aspx) - /// - /// Returns the IDebugPendingBreakpoint2 object that represents the pending breakpoint being - /// bound. - /// VSConstants.S_OK. - int IDebugBreakpointBoundEvent2.GetPendingBreakpoint(out IDebugPendingBreakpoint2 ppPendingBP) - { - ppPendingBP = m_pendingBreakpoint; - return VSConstants.S_OK; - } - - #endregion - } - - - /// - /// The debug engine (DE) sends this interface to the session debug manager (SDM) when a program stops at a breakpoint. - /// (http://msdn.microsoft.com/en-us/library/bb145927.aspx) - /// - sealed class AD7BreakpointEvent : AD7StoppingEvent, IDebugBreakpointEvent2 - { - public const string IID = "501C1E21-C557-48B8-BA30-A1EAB0BC4A74"; - - IEnumDebugBoundBreakpoints2 m_boundBreakpoints; - - - /// - /// Constructor. - /// - /// The IEnumDebugBoundBreakpoints2 object that enumerates all the breakpoints associated with - /// the current code location. - public AD7BreakpointEvent(IEnumDebugBoundBreakpoints2 boundBreakpoints) - { - m_boundBreakpoints = boundBreakpoints; - } - - #region IDebugBreakpointEvent2 Members - - /// - /// Creates an enumerator for all the breakpoints that fired at the current code location. - /// (http://msdn.microsoft.com/en-us/library/bb146247.aspx) - /// - /// Returns an IEnumDebugBoundBreakpoints2 object that enumerates all the breakpoints associated with - /// the current code location. - /// VSConstants.S_OK. - int IDebugBreakpointEvent2.EnumBreakpoints(out IEnumDebugBoundBreakpoints2 ppEnum) - { - ppEnum = m_boundBreakpoints; - return VSConstants.S_OK; - } - - #endregion - } - - - /// - /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when the program being debugged completes - /// a step into, a step over, or a step out of a line of source code or statement or instruction. - /// (http://msdn.microsoft.com/en-us/library/bb162189.aspx) - /// - sealed class AD7StepCompletedEvent : IDebugEvent2, IDebugStepCompleteEvent2 - { - public const string IID = "0F7F24C1-74D9-4EA6-A3EA-7EDB2D81441D"; - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - public static void Send(AD7Engine engine) - { - var xEvent = new AD7StepCompletedEvent(); - engine.Callback.Send(xEvent, IID, engine.currentThread()); - } - - #region IDebugEvent2 Members - - /// - /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) - /// - /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. - /// VSConstants.S_OK. - public int GetAttributes(out uint pdwAttrib) - { - pdwAttrib = (uint)(enum_EVENTATTRIBUTES.EVENT_ASYNC_STOP); - return VSConstants.S_OK; - } - - #endregion - } - - - /// - /// The debug engine (DE) sends this interface to the session debug manager (SDM) when the program is about to execute its - /// first instruction of user code. (http://msdn.microsoft.com/en-us/library/bb161265.aspx) - /// - sealed class AD7EntryPointEvent : AD7SynchronousStoppingEvent, IDebugEntryPointEvent2 - { - public const string IID = "86D5A99E-C721-4625-A401-4D052DF38475"; - - - /// - /// Sends the event. - /// - /// The AD7Engine object that represents the DE. - public static void Send(AD7Engine engine) - { - var xEvent = new AD7EntryPointEvent(); - engine.Callback.Send(xEvent, IID, engine.currentThread()); - } - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Expression.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Expression.cs deleted file mode 100644 index d7357909..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Expression.cs +++ /dev/null @@ -1,126 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using VSNDK.Parser; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Collections; -using System.Threading; - -namespace VSNDK.DebugEngine -{ - /// - /// This class represents a parsed expression ready for binding and evaluating. - /// It is returned as a result of a successful call to IDebugExpressionContext2.ParseText - /// It allows the debugger to obtain the values of an expression in the debuggee. - /// (http://msdn.microsoft.com/en-ca/library/bb162308.aspx) - /// - public class AD7Expression : IDebugExpression2 - { - /// - /// The expression to be evaluated. - /// - private string exp; - - /// - /// The class that manages debug events for the debug engine. - /// - private EventDispatcher m_eventDispatcher; - - /// - /// Current stack frame. - /// - private AD7StackFrame m_frame; - - - /// - /// Constructor. - /// - /// The expression to be evaluated. - /// Current stack frame. - /// Represents the class that manages debug events for the debug engine. - public AD7Expression(string exp, AD7StackFrame frame, EventDispatcher dispatcher) - { - this.exp = exp; - this.m_eventDispatcher = dispatcher; - this.m_frame = frame; - } - - #region IDebugExpression2 Members - - - /// - /// This method cancels asynchronous expression evaluation as started by a call to the IDebugExpression2::EvaluateAsync method. - /// Not implemented yet because it was not needed till now. (http://msdn.microsoft.com/en-ca/library/bb145924.aspx) - /// - /// Not implemented. - int IDebugExpression2.Abort() - { - throw new NotImplementedException(); - } - - - /// - /// Thread responsible for evaluating expressions asynchronously. - /// - public void evaluatingAsync() - { - VariableInfo vi = VariableInfo.get(exp, m_eventDispatcher, m_frame); - AD7Property ppResult = new AD7Property(vi); - - m_frame.m_engine.Callback.Send(new AD7ExpressionEvaluationCompleteEvent(this, ppResult), AD7ExpressionEvaluationCompleteEvent.IID, m_frame.m_engine, m_frame.m_thread); - } - - - /// - /// This method evaluates the expression asynchronously. - /// This is primarily used for the immediate window. (http://msdn.microsoft.com/en-ca/library/bb146752.aspx) - /// - /// A combination of flags from the EVALFLAGS enumeration that control expression evaluation. - /// This parameter is always a null value. - /// VSConstants.S_OK. - int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback) - { - // Creating a thread to evaluate the expression asynchronously. - Thread m_processingThread; - m_processingThread = new Thread(evaluatingAsync); - m_processingThread.Start(); - - return VSConstants.S_OK; - } - - - /// - /// This method evaluates the expression synchronously. (http://msdn.microsoft.com/en-ca/library/bb146982.aspx) - /// - /// A combination of flags from the EVALFLAGS enumeration that control expression evaluation. - /// Maximum time, in milliseconds, to wait before returning from this method. Use INFINITE to wait - /// indefinitely. - /// This parameter is always a null value. - /// Returns the IDebugProperty2 object that contains the result of the expression evaluation. - /// VSConstants.S_OK. - int IDebugExpression2.EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult) - { - VariableInfo vi = VariableInfo.get(exp, m_eventDispatcher, m_frame); - ppResult = new AD7Property(vi); - m_frame._lastEvaluatedExpression = vi; - return VSConstants.S_OK; - } - - #endregion - } -} \ No newline at end of file diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7MemoryAddress.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7MemoryAddress.cs deleted file mode 100644 index c572ed54..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7MemoryAddress.cs +++ /dev/null @@ -1,269 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; - -namespace VSNDK.DebugEngine -{ - /// - /// And implementation of IDebugCodeContext2 and IDebugMemoryContext2. - /// IDebugMemoryContext2 represents a position in the address space of the machine running the program being debugged. - /// IDebugCodeContext2 represents the starting position of a code instruction. For most run-time architectures today, a code - /// context can be thought of as an address in a program's execution stream. - /// - public class AD7MemoryAddress : IDebugCodeContext2, IDebugCodeContext100 - { - /// - /// The AD7Engine object that represents the DE. - /// - readonly AD7Engine m_engine; - - /// - /// The current context's address. - /// - readonly uint m_address; - - /// - /// The IDebugDocumentContext2 object that corresponds to the code context. - /// - IDebugDocumentContext2 m_documentContext; - - - /// - /// Constructor. - /// - /// The AD7Engine object that represents the DE. - /// The current context's address. - public AD7MemoryAddress(AD7Engine engine, uint address) - { - m_engine = engine; - m_address = address; - } - - - /// - /// Sets the document context. - /// - /// The IDebugDocumentContext2 object that corresponds to the code context. - public void SetDocumentContext(IDebugDocumentContext2 docContext) - { - m_documentContext = docContext; - } - - #region IDebugMemoryContext2 Members - - - /// - /// Adds a specified value to the current context's address to create a new context. - /// (http://msdn.microsoft.com/en-ca/library/bb145861.aspx) - /// - /// The value to add to the current context. - /// Returns a new IDebugMemoryContext2 object. - /// VSConstants.S_OK. - public int Add(ulong dwCount, out IDebugMemoryContext2 newAddress) - { - newAddress = new AD7MemoryAddress(m_engine, (uint)dwCount + m_address); - return VSConstants.S_OK; - } - - - /// - /// Compares the memory context to each context in the given array in the manner indicated by compare flags, - /// returning an index of the first context that matches. (http://msdn.microsoft.com/en-ca/library/bb161750.aspx) - /// - /// A value from the CONTEXT_COMPARE enumeration that determines the type of comparison. - /// An array of references to the IDebugMemoryContext2 objects to compare against. - /// The number of contexts in the compareToItems array. - /// Returns the index of the first memory context that satisfies the comparison. - /// If successful, returns S_OK; otherwise, returns an error code. - public int Compare(enum_CONTEXT_COMPARE uContextCompare, IDebugMemoryContext2[] compareToItems, uint compareToLength, out uint foundIndex) - { - foundIndex = uint.MaxValue; - - try - { - enum_CONTEXT_COMPARE contextCompare = (enum_CONTEXT_COMPARE)uContextCompare; - - for (uint c = 0; c < compareToLength; c++) - { - AD7MemoryAddress compareTo = compareToItems[c] as AD7MemoryAddress; - if (compareTo == null) - { - continue; - } - - if (!AD7Engine.ReferenceEquals(this.m_engine, compareTo.m_engine)) - { - continue; - } - - bool result; - - switch (contextCompare) - { - case enum_CONTEXT_COMPARE.CONTEXT_EQUAL: - result = (this.m_address == compareTo.m_address); - break; - - case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN: - result = (this.m_address < compareTo.m_address); - break; - - case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN: - result = (this.m_address > compareTo.m_address); - break; - - case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL: - result = (this.m_address <= compareTo.m_address); - break; - - case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL: - result = (this.m_address >= compareTo.m_address); - break; - - // The VSNDK debug engine doesn't understand scopes or functions - case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE: - case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION: - result = (this.m_address == compareTo.m_address); - break; - - case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE: - result = (this.m_address == compareTo.m_address); - break; - - case enum_CONTEXT_COMPARE.CONTEXT_SAME_PROCESS: - result = true; - break; - - default: - // A new comparison was invented that we don't support - return VSConstants.E_NOTIMPL; - } - - if (result) - { - foundIndex = c; - return VSConstants.S_OK; - } - } - - return VSConstants.S_FALSE; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Gets information that describes this context. Not implemented. (http://msdn.microsoft.com/en-ca/library/bb145034.aspx) - /// - /// A combination of flags from the CONTEXT_INFO_FIELDS enumeration that indicate which fields of the - /// CONTEXT_INFO structure are to be fill in. - /// The CONTEXT_INFO structure that is filled in. - /// Not implemented. - public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) - { - return VSConstants.E_NOTIMPL; - } - - - /// - /// Gets the user-displayable name for this context. This is not supported by the VSNDK debug engine. - /// (http://msdn.microsoft.com/en-ca/library/bb146997.aspx) - /// - /// Returns the name of the memory context. - /// Not implemented. - public int GetName(out string pbstrName) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Subtracts a specified value from the current context's address to create a new context. - /// (http://msdn.microsoft.com/en-ca/library/bb146285.aspx) - /// - /// The number of memory bytes to decrement. - /// Returns a new IDebugMemoryContext2 object. - /// VSConstants.S_OK. - public int Subtract(ulong dwCount, out IDebugMemoryContext2 ppMemCxt) - { - ppMemCxt = new AD7MemoryAddress(m_engine, (uint)dwCount - m_address); - return VSConstants.S_OK; - } - - #endregion - - #region IDebugCodeContext2 Members - - - /// - /// Gets the document context that corresponds to this code context. The document context represents a position in the source file - /// that corresponds to the source code that generated this instruction. (http://msdn.microsoft.com/en-ca/library/bb161811.aspx) - /// - /// Returns the IDebugDocumentContext2 object that corresponds to the code context. - /// VSConstants.S_OK. - public int GetDocumentContext(out IDebugDocumentContext2 ppSrcCxt) - { - ppSrcCxt = m_documentContext; - return VSConstants.S_OK; - } - - - /// - /// Gets the language information for this code context. (http://msdn.microsoft.com/en-ca/library/bb144925.aspx) - /// - /// Returns a string that contains the name of the language, such as "C++.". - /// Returns the GUID for the language of the code context, for example, guidCPPLang. - /// If successful, returns S_OK; otherwise, returns S_FALSE. - public int GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) - { - if (m_documentContext != null) - { - m_documentContext.GetLanguageInfo(ref pbstrLanguage, ref pguidLanguage); - return VSConstants.S_OK; - } - else - { - return VSConstants.S_FALSE; - } - } - - #endregion - - #region IDebugCodeContext100 Members - - - /// - /// Returns the program being debugged. In the case of this VSNDK debug debug engine, AD7Engine implements IDebugProgram2 which - /// represents the program being debugged. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugcodecontext100.getprogram.aspx) - /// - /// Returns the program being debugged. - /// VSConstants.S_OK. - int IDebugCodeContext100.GetProgram(out IDebugProgram2 pProgram) - { - pProgram = m_engine; - return VSConstants.S_OK; - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Module.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Module.cs deleted file mode 100644 index e3b53f35..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Module.cs +++ /dev/null @@ -1,232 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; -using System.Threading; - -namespace VSNDK.DebugEngine -{ - - /// - /// This class represents a module loaded in the debuggee process to the debugger. Not implemented, yet. - /// - /// It implements: - /// - /// IDebugModule2: This interface represents a modulethat is, an executable unit of a programsuch as a DLL. - /// (http://msdn.microsoft.com/en-ca/library/bb145360.aspx) - /// - /// IDebugModule3: This interface represents a module that supports alternate locations of symbols and JustMyCode states. - /// (http://msdn.microsoft.com/en-ca/library/bb145893.aspx) - /// - public class AD7Module : IDebugModule2, IDebugModule3 - { - - /// - /// Constructor. Not implemented, yet. - /// - public AD7Module() - { - } - - - /// - /// Gets information about this module. (http://msdn.microsoft.com/en-ca/library/bb161975.aspx) - /// - /// A combination of flags from the MODULE_INFO_FIELDS enumeration that specify which fields of pInfo - /// are to be filled out. - /// A MODULE_INFO structure that is filled in with a description of the module. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugModule2.GetInfo(enum_MODULE_INFO_FIELDS dwFields, MODULE_INFO[] infoArray) - { - try - { - MODULE_INFO info = new MODULE_INFO(); - - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_NAME)) - { - info.m_bstrName = ""; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_NAME; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_URL)) - { - info.m_bstrUrl = ""; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_URL; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS)) - { - info.m_addrLoadAddress = 0; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS)) - { - // A debugger that actually supports showing the preferred base should crack the PE header and get - // that field. This debugger does not do that, so assume the module loaded where it was suppose to. - info.m_addrPreferredLoadAddress = 0; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_SIZE)) - { - info.m_dwSize = 0; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_SIZE; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_LOADORDER)) - { - info.m_dwLoadOrder = 0; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_LOADORDER; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION)) - { - info.m_bstrUrlSymbolLocation = ""; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_FLAGS)) - { - info.m_dwModuleFlags = 0; - info.m_dwModuleFlags |= (enum_MODULE_FLAGS.MODULE_FLAG_SYMBOLS); - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_FLAGS; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_VERSION)) - { - info.m_bstrVersion = ""; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_VERSION; - } - if (dwFields.HasFlag(enum_MODULE_INFO_FIELDS.MIF_DEBUGMESSAGE)) - { - info.m_bstrDebugMessage = ""; - info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_DEBUGMESSAGE; - } - - infoArray[0] = info; - - return VSConstants.S_OK; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - #region Deprecated interface methods - // These methods are not called by the Visual Studio debugger, so they don't need to be implemented - - - /// - /// OBSOLETE. DO NOT USE. Reloads the symbols for this module. (http://msdn.microsoft.com/en-ca/library/bb145113.aspx) - /// - /// The path to the symbol store. - /// Returns an informational message, such as a status or error message, that is displayed to the - /// right of the module name in the Modules window. - /// VSConstants.E_NOTIMPL. - int IDebugModule2.ReloadSymbols_Deprecated(string urlToSymbols, out string debugMessage) - { - debugMessage = null; - System.Diagnostics.Debug.Fail("This function is not called by the debugger."); - return VSConstants.E_NOTIMPL; - } - - - /// - /// This method is not presented in IDebugModule3 webpage but the debug engine fails to build without it. It should have the same - /// behavior as the above IDebugModule2.ReloadSymbols_Deprecated. (http://msdn.microsoft.com/en-ca/library/bb145893.aspx) - /// - /// - /// - /// Not implemented. - int IDebugModule3.ReloadSymbols_Deprecated(string pszUrlToSymbols, out string pbstrDebugMessage) - { - throw new NotImplementedException(); - } - #endregion - - - /// - /// This method is not presented in IDebugModule3 webpage but the debug engine fails to build without it. - /// (http://msdn.microsoft.com/en-ca/library/bb145893.aspx). It should have the same behavior as the above - /// IDebugModule2.GetInfo, i.e., gets information about this module. (http://msdn.microsoft.com/en-ca/library/bb161975.aspx) - /// - /// A combination of flags from the MODULE_INFO_FIELDS enumeration that specify which fields of pInfo - /// are to be filled out. - /// A MODULE_INFO structure that is filled in with a description of the module. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugModule3.GetInfo(enum_MODULE_INFO_FIELDS dwFields, MODULE_INFO[] pinfo) - { - return ((IDebugModule2)this).GetInfo(dwFields, pinfo); - } - - - /// - /// Returns a list of paths searched for symbols and the results of searching each path. - /// [http://msdn.microsoft.com/en-ca/library/bb161971(v=vs.100).aspx] - /// - /// A combination of flags from the SYMBOL_SEARCH_INFO_FIELDS enumeration specifying which fields - /// of pInfo are to be filled in. - /// A MODULE_SYMBOL_SEARCH_INFO structure whose members are to be filled in with the specified information. - /// If this is a null value, this method returns E_INVALIDARG. - /// VSConstants.S_OK. - int IDebugModule3.GetSymbolInfo(enum_SYMBOL_SEARCH_INFO_FIELDS dwFields, MODULE_SYMBOL_SEARCH_INFO[] pinfo) - { - pinfo[0] = new MODULE_SYMBOL_SEARCH_INFO(); - pinfo[0].dwValidFields = 1; // SSIF_VERBOSE_SEARCH_INFO; - - string symbolsNotLoaded = "Symbols not loaded"; - pinfo[0].bstrVerboseSearchInfo = symbolsNotLoaded; - return VSConstants.S_OK; - } - - - /// - /// Retrieves information on whether the module represents user code or not. Used to support the JustMyCode features of the - /// debugger. [http://msdn.microsoft.com/en-ca/library/bb146644(v=vs.100).aspx] - /// The VSNDK debug engine does not support JustMyCode and therefore all modules are considered "My Code" - /// - /// Nonzero (TRUE) if module represents user code, zero (FALSE) if it does not. - /// VSConstants.S_OK. - int IDebugModule3.IsUserCode(out int pfUser) - { - pfUser = 1; - return VSConstants.S_OK; - } - - - /// - /// Loads and initializes symbols for the current module when the user explicitly asks for them to load. Not implemented. - /// [http://msdn.microsoft.com/en-ca/library/bb146634(v=vs.100).aspx] - /// - /// Not implemented. - int IDebugModule3.LoadSymbols() - { - throw new NotImplementedException(); - } - - - /// - /// Specifies whether the module should be considered user code or not. Used to support the JustMyCode features of the debugger. - /// [http://msdn.microsoft.com/en-ca/library/bb146327(v=vs.100).aspx] - /// The VSNDK debug engine does not support JustMyCode so this is not implemented - /// - /// Nonzero (TRUE) if the module should be considered user code, zero (FALSE) if it should not. - /// Not implemented. - int IDebugModule3.SetJustMyCodeState(int fIsUserCode) - { - throw new NotImplementedException(); - } - - } -} \ No newline at end of file diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7PendingBreakpoint.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7PendingBreakpoint.cs deleted file mode 100644 index 88942e04..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7PendingBreakpoint.cs +++ /dev/null @@ -1,388 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Text; - -namespace VSNDK.DebugEngine -{ - - /// - /// This class represents a peiding breakpoint that is ready to bind to a code location. A pending breakpoint is an abstract - /// representation of a breakpoint before it is bound. When a user creates a new breakpoint, the pending breakpoint is created - /// and is later bound. The bound breakpoints become children of the pending breakpoint. - /// - /// It implements IDebugPendingBreakpoint2: (http://msdn.microsoft.com/en-ca/library/bb161807.aspx) - /// - public class AD7PendingBreakpoint : IDebugPendingBreakpoint2 - { - /// - /// The breakpoint request that resulted in this pending breakpoint being created. - /// - private IDebugBreakpointRequest2 m_pBPRequest; - private BP_REQUEST_INFO m_bpRequestInfo; - private AD7Engine m_engine; - private BreakpointManager m_bpManager; - - private List m_boundBreakpoints; - public List boundBPs - { - get - { - return m_boundBreakpoints; - } - } - - private bool m_enabled; - private bool m_deleted; - - - /// - /// Constructor. - /// - /// The breakpoint request used to create this pending breakpoint. - /// The AD7Engine object that represents the DE. - /// The breakpoint manager. - public AD7PendingBreakpoint(IDebugBreakpointRequest2 pBPRequest, AD7Engine engine, BreakpointManager bpManager) - { - m_pBPRequest = pBPRequest; - BP_REQUEST_INFO[] requestInfo = new BP_REQUEST_INFO[1]; - m_pBPRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_BPLOCATION, requestInfo); - m_bpRequestInfo = requestInfo[0]; - m_pBPRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_CONDITION, requestInfo); - if (requestInfo[0].dwFields != 0) - { - m_bpRequestInfo.bpCondition = requestInfo[0].bpCondition; - m_bpRequestInfo.dwFields |= requestInfo[0].dwFields; - } - m_pBPRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_PASSCOUNT, requestInfo); - if (requestInfo[0].dwFields != 0) - { - m_bpRequestInfo.bpPassCount = requestInfo[0].bpPassCount; - m_bpRequestInfo.dwFields |= requestInfo[0].dwFields; - } - - m_engine = engine; - m_bpManager = bpManager; - m_boundBreakpoints = new System.Collections.Generic.List(); - - m_enabled = true; - m_deleted = false; - } - - - /// - /// Determines whether this pending breakpoint can bind to a code location. - /// - /// If successful, returns TRUE; otherwise, returns FALSE. - private bool CanBind() - { - // The engine only supports these types of breakpoints: - // - File and line number. - // - Function name and offset. - if (this.m_deleted || m_engine.m_process == null) - { - return false; - } - else if (m_bpRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE - || m_bpRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) - { - return true; - } - - return false; - } - - - /// - /// Remove all of the bound breakpoints for this pending breakpoint - /// - public void ClearBoundBreakpoints() - { - lock (m_boundBreakpoints) - { - for (int i = m_boundBreakpoints.Count - 1; i >= 0; i--) - { - ((IDebugBoundBreakpoint2)m_boundBreakpoints[i]).Delete(); - } - } - } - - - /// - /// Called by bound breakpoints when they are being deleted. - /// - /// A bound breakpoint. - public void OnBoundBreakpointDeleted(AD7BoundBreakpoint boundBreakpoint) - { - lock (m_boundBreakpoints) - { - m_boundBreakpoints.Remove(boundBreakpoint); - } - } - - #region IDebugPendingBreakpoint2 Members - - - /// GDB works with short path names only, which requires converting the path names to/from long ones. This function - /// returns the short path name for a given long one. - /// Long path name. - /// Returns this short path name. - /// Lenght of this short path name. - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern int GetShortPathName( - [MarshalAs(UnmanagedType.LPTStr)] - string path, - [MarshalAs(UnmanagedType.LPTStr)] - StringBuilder shortPath, - int shortPathLength - ); - - - /// - /// Bind this breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145901.aspx) - /// - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugPendingBreakpoint2.Bind() - { - try - { - if (CanBind()) - { - AD7BoundBreakpoint xBBP = null; - - // Visual Studio returns a start position that is one less than it actually is - xBBP = new AD7BoundBreakpoint(m_engine, m_bpRequestInfo, this); - - if (VSNDK.Package.ControlDebugEngine.isDebugEngineRunning == false) - { - return VSConstants.S_FALSE; - } - - if ((xBBP == null) || (xBBP.GDB_ID == 0)) - { - return VSConstants.S_FALSE; - } - - // Set the enabled state of the bound breakpoint based on the pending breakpoint's enabled state - ((IDebugBoundBreakpoint2)xBBP).Enable(Convert.ToInt32(m_enabled)); - - m_boundBreakpoints.Add(xBBP); - - return VSConstants.S_OK; - } - else - { - // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid - // expression, etc... The VSNDK debug engine does not support this, but a real world engine will want to send an - // instance of IDebugBreakpointErrorEvent2 to the UI and return a valid instance of IDebugErrorBreakpoint2 from - // IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then display information about why the - // breakpoint did not bind to the user. - return VSConstants.S_FALSE; - } - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Determines whether this pending breakpoint can bind to a code location. (http://msdn.microsoft.com/en-ca/library/bb146753.aspx) - /// - /// Returns an IEnumDebugErrorBreakpoints2 object that contains a list of IDebugErrorBreakpoint2 - /// objects if there could be errors. - /// If successful, returns S_OK; otherwise, returns S_FALSE - int IDebugPendingBreakpoint2.CanBind(out IEnumDebugErrorBreakpoints2 ppErrorEnum) - { - ppErrorEnum = null; - - if (!CanBind()) - { - // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid - // expression, etc... The VSNDK debug engine does not support this, but a real world engine will want to send an - // instance of IDebugBreakpointErrorEvent2 to the UI and return a valid instance of IDebugErrorBreakpoint2 from - // IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then display information about why the - // breakpoint did not bind to the user. - ppErrorEnum = null; - return VSConstants.S_FALSE; - } - - return VSConstants.S_OK; - } - - - /// - /// Deletes this pending breakpoint and all breakpoints bound from it. (http://msdn.microsoft.com/en-ca/library/bb145918.aspx) - /// - /// VSConstants.S_OK. - int IDebugPendingBreakpoint2.Delete() - { - lock (m_boundBreakpoints) - { - for (int i = m_boundBreakpoints.Count - 1; i >= 0; i--) - { - ((IDebugBoundBreakpoint2)m_boundBreakpoints[i]).Delete(); - } - } - - m_enabled = false; - m_deleted = true; - return VSConstants.S_OK; - } - - - /// - /// Toggles the enabled state of this pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145046.aspx) - /// - /// Set to nonzero (TRUE) to enable a pending breakpoint, or to zero (FALSE) to disable. - /// VSConstants.S_OK. - int IDebugPendingBreakpoint2.Enable(int fEnable) - { - lock (m_boundBreakpoints) - { - m_enabled = fEnable == 0 ? false : true; - - foreach (AD7BoundBreakpoint bp in m_boundBreakpoints) - { - ((IDebugBoundBreakpoint2)bp).Enable(fEnable); - } - } - - return VSConstants.S_OK; - } - - - /// - /// Enumerates all breakpoints bound from this pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145139.aspx) - /// - /// Returns an IEnumDebugBoundBreakpoints2 object that enumerates the bound breakpoints. - /// VSConstants.S_OK. - int IDebugPendingBreakpoint2.EnumBoundBreakpoints(out IEnumDebugBoundBreakpoints2 ppEnum) - { - lock (m_boundBreakpoints) - { - IDebugBoundBreakpoint2[] boundBreakpoints = m_boundBreakpoints.ToArray(); - ppEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); - } - return VSConstants.S_OK; - } - - - /// - /// Enumerates all error breakpoints that resulted from this pending breakpoint. - /// (http://msdn.microsoft.com/en-ca/library/bb145598.aspx) - /// - /// A combination of values from the enum_BP_ERROR_TYPE enumeration that selects the type of errors - /// to enumerate. - /// Returns an IEnumDebugErrorBreakpoints2 object that contains a list of IDebugErrorBreakpoint2 objects. - /// VSConstants.E_NOTIMPL. - int IDebugPendingBreakpoint2.EnumErrorBreakpoints(enum_BP_ERROR_TYPE bpErrorType, out IEnumDebugErrorBreakpoints2 ppEnum) - { - // Called when a pending breakpoint could not be bound. This may occur for many reasons such as an invalid location, an - // invalid expression, etc... The VSNDK debug engine does not support this, but a real world engine will want to send an - // instance of IDebugBreakpointErrorEvent2 to the UI and return a valid enumeration of IDebugErrorBreakpoint2 from - // IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then display information about why the breakpoint - // did not bind to the user. - ppEnum = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Gets the breakpoint request that was used to create this pending breakpoint. - /// (http://msdn.microsoft.com/en-ca/library/bb161770.aspx) - /// - /// Returns an IDebugBreakpointRequest2 object representing the breakpoint request that was used to - /// create this pending breakpoint. - /// VSConstants.S_OK. - int IDebugPendingBreakpoint2.GetBreakpointRequest(out IDebugBreakpointRequest2 ppBPRequest) - { - ppBPRequest = this.m_pBPRequest; - return VSConstants.S_OK; - } - - - /// - /// Gets the state of this pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb162178.aspx) - /// - /// A PENDING_BP_STATE_INFO structure that is filled in with a description of this pending breakpoint. - /// VSConstants.S_OK. - int IDebugPendingBreakpoint2.GetState(PENDING_BP_STATE_INFO[] pState) - { - if (m_deleted) - { - pState[0].state = (enum_PENDING_BP_STATE)enum_BP_STATE.BPS_DELETED; - } - else if (m_enabled) - { - pState[0].state = (enum_PENDING_BP_STATE)enum_BP_STATE.BPS_ENABLED; - } - else if (!m_enabled) - { - pState[0].state = (enum_PENDING_BP_STATE)enum_BP_STATE.BPS_DISABLED; - } - - return VSConstants.S_OK; - } - - - /// - /// Sets or changes the condition associated with the pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb144977.aspx). - /// Not implemented here, but a conditional breakpoint can be set using IDebugBoundBreakpoint2::SetCondition(). - /// - /// A BP_CONDITION structure that specifies the condition to set. - /// Not implemented. - int IDebugPendingBreakpoint2.SetCondition(BP_CONDITION bpCondition) - { - throw new NotImplementedException(); - } - - - /// - /// Sets or changes the pass count associated with the pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145038.aspx). - /// Not implemented here, but a pass count associated to a breakpoint can be set/changed using - /// IDebugBoundBreakpoint2::SetPassCount(). - /// - /// A BP_PASSCOUNT structure that contains the pass count. - /// Not implemented. - int IDebugPendingBreakpoint2.SetPassCount(BP_PASSCOUNT bpPassCount) - { - throw new NotImplementedException(); - } - - - /// - /// Toggles the virtualized state of this pending breakpoint. When a pending breakpoint is virtualized, the debug engine will - /// attempt to bind it every time new code loads into the program. (http://msdn.microsoft.com/en-ca/library/bb146187.aspx) - /// The VSNDK debug engine does not support this. Not implemented. - /// - /// Set to nonzero (TRUE) to virtualize the pending breakpoint, or to zero (FALSE) to turn off - /// virtualization. - /// VSConstants.S_OK. - int IDebugPendingBreakpoint2.Virtualize(int fVirtualize) - { - return VSConstants.S_OK; - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Port.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Port.cs deleted file mode 100644 index 9b7643ca..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Port.cs +++ /dev/null @@ -1,397 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Runtime.InteropServices.ComTypes; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Shell; -using VSNDK.Parser; -using System.Windows.Forms; - -namespace VSNDK.DebugEngine -{ - /// - /// This class implements a port. - /// - /// It implements: - /// - /// - IDebugPort2 - This interface represents a debug port on a machine. (http://msdn.microsoft.com/en-us/library/bb147021.aspx) - /// - IConnectionPointContainer - Supports connection points for connectable objects. Indicates to a client that the object is - /// connectable and provides the IConnectionPoint interface. (http://msdn.microsoft.com/en-CA/library/ms683857.aspx) - /// - IConnectionPoint - Supports connection points for connectable objects. (http://msdn.microsoft.com/en-us/library/ms694318.aspx) - /// - public class AD7Port : IDebugPort2, IConnectionPointContainer, IConnectionPoint - { - - /// - /// The name of the port. - /// - public readonly string m_name; - - /// - /// The IP of the port. - /// - public readonly string m_IP; - - /// - /// The password needed to have access to the port. - /// - public readonly string m_password; - - /// - /// Boolean variable that indicates if the port is associated to the Simulator or the Device. - /// - public readonly bool m_isSimulator; - - /// - /// The NDK host path. - /// - public readonly string m_toolsPath; - - /// - /// List of processes running on this port. - /// - private readonly List m_processes = new List(); - - /// - /// The GUID that identifies the port. - /// - public readonly Guid m_guid; - - /// - /// Represents the request that was used to create the port. - /// - private readonly AD7PortRequest m_request; - - /// - /// Represents the port supplier for this port. - /// - public readonly AD7PortSupplier m_supplier; - - /// - /// Maps objects to and from event "cookies" that represent a client's registration with an event provider. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.eventsinkcollection.aspx) - /// - private EventSinkCollection m_eventSinks = new EventSinkCollection(); - - - /// - /// Constructor. - /// - /// The port supplier for this port. - /// The request used to create the port. - /// The GUID that identifies the port. - /// The name of the port. - /// The password needed to have access to the port. - /// Variable that indicates if the port is associated to the Simulator or the Device. - /// The NDK host path. - public AD7Port(AD7PortSupplier supplier, AD7PortRequest request, Guid guid, string portName, string password, bool isSimulator, string toolsPath) - { - m_name = portName; - m_request = request; - m_supplier = supplier; - m_guid = guid; - if (isSimulator) - m_IP = m_name.Substring(11); - else - m_IP = m_name.Substring(8); - m_password = password; - m_isSimulator = isSimulator; - m_toolsPath = toolsPath; - } - - - /// - /// Gets the list of processes running on this port. - /// - /// Returns the list of processes running on this port. - IEnumerable GetProcesses() - { - IDebugCoreServer2 server = null; - if (m_processes.Count() != 0) - { - foreach (AD7Process p in m_processes) - { - AD7ProcessDestroyEvent ev = new AD7ProcessDestroyEvent(); - SendEvent(server, this, p, null, ev, ev.getGuid()); - } - m_processes.Clear(); - } - - string publicKeyPath = Environment.GetEnvironmentVariable("AppData") + @"\BlackBerry\bbt_id_rsa.pub"; - - string response = GDBParser.GetPIDsThroughGDB(m_IP, m_password, m_isSimulator, m_toolsPath, publicKeyPath, 7); - - if ((response == "TIMEOUT!") || (response.IndexOf("1^error,msg=", 0) != -1)) //found an error - { - if (response == "TIMEOUT!") // Timeout error, normally happen when the device is not connected. - { - MessageBox.Show("Please, verify if the Device/Simulator IP in \"BlackBerry -> Settings\" menu is correct and check if it is connected.", "Device/Simulator not connected or not configured properly", MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - else - if (response[29] == ':') // error: 1^error,msg="169.254.0.3:8000: The requested address is not valid in its context." - { - string txt = response.Substring(13, response.IndexOf(':', 13) - 13) + response.Substring(29, response.IndexOf('"', 31) - 29); - string caption = ""; - if (txt.IndexOf("The requested address is not valid in its context.") != -1) - { - txt += "\n\nPlease, verify the BlackBerry device/simulator IP settings."; - caption = "Invalid IP"; - } - else - { - txt += "\n\nPlease, verify if the device/simulator is connected."; - caption = "Connection failed"; - } - MessageBox.Show(txt, caption, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - response = ""; - } - else if (response.Contains("^done")) - { - response = response.Remove(response.IndexOf("^done")); - string[] tempListOfProcesses = response.Split('\n'); - - int ind = (response[0] == '&') ? 1 : 0; // ignore the first if it starts with & (&"info pidlist") - while (ind < tempListOfProcesses.Length - 1) - { - string process = tempListOfProcesses[ind]; - int pos = process.LastIndexOf('/'); - if (pos == -1) - { - ind++; - continue; - } - process = process.Remove(pos).Substring(2); - for (ind = ind + 1; ind < tempListOfProcesses.Length - 1; ind++) // ignore the duplicates - { - int pos2 = tempListOfProcesses[ind].LastIndexOf('/'); - if ((pos2 <= 2) || (tempListOfProcesses[ind].Substring(2, pos2 - 2) != process)) - break; - } - AD7Process proc = new AD7Process(this, process.Substring(process.IndexOf("- ") + 2), process.Remove(process.IndexOf(" "))); - m_processes.Add(proc); - AD7ProcessCreateEvent ev = new AD7ProcessCreateEvent(); - SendEvent(server, this, proc, null, ev, ev.getGuid()); - } - } - return m_processes; - } - - - /// - /// Send an event to SDM. - /// - /// Server. Using NULL. - /// The IDebugPort2 port. - /// The IDebugProcess2 process. - /// The IDebugProgram2 program. Using NULL. - /// The event. It can be: AD7ProcessDestroyEvent or AD7ProcessCreateEvent. - /// The event GUID. - private void SendEvent(IDebugCoreServer2 server, IDebugPort2 port, IDebugProcess2 process, IDebugProgram2 program, IDebugEvent2 ev, Guid iid) - { - foreach (var eventSink in m_eventSinks) - { - IDebugPortEvents2 events = eventSink as IDebugPortEvents2; - if (events != null) - { - events.Event(server, port, process, program, ev, ref iid); - } - } - } - - - #region Implementation of IDebugPort2 - - /// - /// Returns the port name. (http://msdn.microsoft.com/en-us/library/bb145890.aspx) - /// - /// Returns the name of the port. - /// VSConstants.S_OK. - public int GetPortName(out string pbstrName) - { - pbstrName = m_name; - return VSConstants.S_OK; - } - - - /// - /// Returns the port identifier. (http://msdn.microsoft.com/en-us/library/bb146747.aspx) - /// - /// Returns the GUID that identifies the port. - /// VSConstants.S_OK. - public int GetPortId(out Guid pguidPort) - { - pguidPort = m_guid; - return VSConstants.S_OK; - } - - - /// - /// Returns the request used to create a port. (http://msdn.microsoft.com/en-us/library/bb145127.aspx) - /// - /// Returns an IDebugPortRequest2 object representing the request that was used to create the port. - /// VSConstants.S_OK. - public int GetPortRequest(out IDebugPortRequest2 ppRequest) - { - ppRequest = m_request; - return VSConstants.S_OK; - } - - - /// - /// Returns the port supplier for this port. (http://msdn.microsoft.com/en-us/library/bb146688.aspx) - /// - /// Returns an IDebugPortSupplier2 object represents the port supplier for a port. - /// VSConstants.S_OK. - public int GetPortSupplier(out IDebugPortSupplier2 ppSupplier) - { - ppSupplier = m_supplier; - return VSConstants.S_OK; - } - - - /// - /// Returns the specified process running on a port. (http://msdn.microsoft.com/en-us/library/bb145867.aspx) - /// - /// An AD_PROCESS_ID structure that specifies the process identifier. - /// Returns an IDebugProcess2 object representing the process. - /// If successful, returns VSConstants.S_OK; otherwise, returns VSConstants.S_FALSE. - public int GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) - { - IEnumerable procList = GetProcesses(); - var proc = from p in procList - where p._processID == ProcessId.dwProcessId.ToString() - select p; - ppProcess = proc.FirstOrDefault(); - return ppProcess != null ? VSConstants.S_OK : VSConstants.S_FALSE; - } - - - /// - /// Enumerates all the processes running on a port. (http://msdn.microsoft.com/en-us/library/bb161302.aspx) - /// - /// Returns an IEnumDebugProcesses2 object that contains a list of all the processes running on a port. - /// VSConstants.S_OK. - public int EnumProcesses(out IEnumDebugProcesses2 ppEnum) - { - IEnumerable procList = GetProcesses(); - IDebugProcess2[] processes = new IDebugProcess2[procList.Count()]; - int i = 0; - foreach (var debugProcess in procList) - { - processes[i] = debugProcess; - i++; - } - ppEnum = new AD7ProcessEnum(processes); - return VSConstants.S_OK; - } - - #endregion - - - #region IConnectionPoint Members - - /// - /// Establishes a connection between a connection point object and a client's sink. (http://msdn.microsoft.com/en-us/library/ms678815.aspx) - /// - /// An "object" instance of the client's advise sink. The client's sink receives - /// outgoing calls from the connection point. - /// A returned token that uniquely identifies this connection. - public void Advise(object pUnkSink, out int pdwCookie) - { - pdwCookie = (int)m_eventSinks.Add(pUnkSink); - } - - - /// - /// Creates an enumerator object to iterate through the current connections for this connection point. - /// Not implemented. (http://msdn.microsoft.com/en-us/library/ms680755.aspx) - /// - /// An IEnumConnections object that receives the newly created enumerator. - public void EnumConnections(out IEnumConnections ppEnum) - { - throw new NotImplementedException(); - } - - - /// - /// Retrieves the IID of the outgoing interface managed by this connection point. (http://msdn.microsoft.com/en-us/library/ms693468.aspx) - /// - /// An identifier of the outgoing interface managed by this connection point. - public void GetConnectionInterface(out Guid pIID) - { - pIID = typeof(IDebugPortEvents2).GUID; - } - - - /// - /// Retrieves the IConnectionPointContainer interface pointer for the parent connectable object. (http://msdn.microsoft.com/en-us/library/ms679669.aspx) - /// - /// An IConnectionPointContainer object. - public void GetConnectionPointContainer(out IConnectionPointContainer ppCPC) - { - ppCPC = this; - } - - - /// - /// Terminates an advisory connection previously established between a connection point object and a client's sink. - /// (http://msdn.microsoft.com/en-us/library/ms686608.aspx) - /// - /// A connection token previously returned from IConnectionPoint::Advise. - public void Unadvise(int dwCookie) - { - m_eventSinks.RemoveAt((uint)dwCookie); - } - - #endregion - - - #region IConnectionPointContainer Members - - /// - /// Creates an enumerator object to iterate through all the connection points supported in the connectable object, one - /// connection point per outgoing IID. Not implemented. (http://msdn.microsoft.com/en-CA/library/ms682460.aspx) - /// - /// An IEnumConnectionPoints object that receives the newly created enumerator. - public void EnumConnectionPoints(out IEnumConnectionPoints ppEnum) - { - // We only need FindConnectionPoint(). - throw new NotImplementedException(); - } - - - /// - /// Returns a pointer to the IConnectionPoint interface of a connection point for a specified IID, if that IID describes a - /// supported outgoing interface. (http://msdn.microsoft.com/en-CA/library/ms692476.aspx) - /// - /// Interface identifier of the outgoing interface whose connection point object is being requested. - /// An IConnectionPoint object that receives the connection point that supports the riid interface. - public void FindConnectionPoint(ref Guid riid, out IConnectionPoint ppCP) - { - ppCP = null; - if (riid == typeof(IDebugPortEvents2).GUID) - { - ppCP = this; - } - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7PortRequest.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7PortRequest.cs deleted file mode 100644 index 6bc062dc..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7PortRequest.cs +++ /dev/null @@ -1,63 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace VSNDK.DebugEngine -{ - /// - /// This class describes a port. This description is used to add the port to a port supplier. - /// - /// It implements IDebugPortRequest2 (http://msdn.microsoft.com/en-us/library/bb146168.aspx) - /// - public class AD7PortRequest : IDebugPortRequest2 - { - /// - /// The name of the port to be created. - /// - private string m_name; - - - /// - /// Constructor. - /// - /// The name of the port. It is contains the IP and password of the Device/Simulator. The password must be - /// removed when creating the port because this name will be displayed in Attach to Process UI. - public AD7PortRequest(string name) - { - m_name = name; - } - - #region Implementation of IDebugPortRequest2 - - /// - /// Gets the name of the port to create. - /// - /// Returns the name of the port. - /// VSConstants.S_OK. - public int GetPortName(out string portName) - { - portName = m_name; - return VSConstants.S_OK; - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7PortSupplier.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7PortSupplier.cs deleted file mode 100644 index 60f5ec62..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7PortSupplier.cs +++ /dev/null @@ -1,339 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio; -using Microsoft.Win32; -using System.Windows.Forms; -using System.Security.Cryptography; -using System.Runtime.InteropServices.ComTypes; -using Microsoft.VisualStudio.Shell; -using VSNDK.Parser; - -namespace VSNDK.DebugEngine -{ - /// - /// This class supplies ports to the Session Debug Manager (SDM). - /// - /// It implements: - /// - /// - IDebugPortSupplier2 - This interface supplies ports to the session debug manager (SDM). (http://msdn.microsoft.com/en-ca/library/bb145819.aspx) - /// - IDebugPortSupplierDescription2 - Enables the Visual Studio UI to display text inside the Transport Information section of - /// the Attach to Process dialog box. (http://msdn.microsoft.com/en-us/library/bb458056.aspx) - /// - /// It is needed to enable updating the list of processes in the "attach to process" user interface. - /// - [ComVisible(true)] - [Guid("BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6")] - public class AD7PortSupplier : IDebugPortSupplier2, IDebugPortSupplierDescription2 - { - - /// - /// The name of the port supplier. - /// - private string m_name; - - /// - /// The description for the port supplier. - /// - private string m_description; - - /// - /// The NDK host path. - /// - private string m_toolsPath = ""; - - /// - /// List of ports for this port supplier. - /// - Dictionary m_ports = new Dictionary(); - - - /// - /// Constructor. - /// - public AD7PortSupplier() - { - m_name = "BlackBerry"; - m_description = "The BlackBerry transport lets you select a process that is running in a BlackBerry Device/Simulator"; - } - - private int verifyAndAddPorts() - { - if (GDBParser.s_running == true) // Returning because VS can debug only one app at a time. - return 0; - - RegistryKey rkHKCU = Registry.CurrentUser; - RegistryKey rkPluginRegKey = null; - string DeviceIP = ""; - string DevicePassword = ""; - string SimulatorIP = ""; - string SimulatorPassword = ""; - - try - { - rkPluginRegKey = rkHKCU.OpenSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - m_toolsPath = rkPluginRegKey.GetValue("NDKHostPath").ToString(); - - if ((m_toolsPath == null) || (m_toolsPath == "")) - return -1; - - m_toolsPath += "/usr/bin"; - - DeviceIP = rkPluginRegKey.GetValue("device_IP").ToString(); - if ((DeviceIP != "") && (DeviceIP != null)) - { - DevicePassword = rkPluginRegKey.GetValue("device_password").ToString(); - if ((DevicePassword != "") && (DevicePassword != null)) - { - try - { - DevicePassword = Decrypt(DevicePassword); - } - catch - { - DevicePassword = ""; - } - } - if (DevicePassword == "") - { - MessageBox.Show("Missing Device password", "Missing Device Password", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } - else - { - DeviceIP = ""; - } - SimulatorIP = rkPluginRegKey.GetValue("simulator_IP").ToString(); - SimulatorPassword = rkPluginRegKey.GetValue("simulator_password").ToString(); - if ((SimulatorPassword != "") && (SimulatorPassword != null)) - { - try - { - SimulatorPassword = Decrypt(SimulatorPassword); - } - catch - { - SimulatorPassword = ""; - } - } - } - catch (Exception ex) - { - System.Windows.Forms.MessageBox.Show(ex.Message, "Microsoft Visual Studio", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); - } - - rkPluginRegKey.Close(); - rkHKCU.Close(); - - if ((DeviceIP != "") && (DevicePassword != "")) - { - IDebugPort2 p; - AddPort(new AD7PortRequest("Device: " + DeviceIP + "-" + DevicePassword), out p); - } - - if (SimulatorIP != "") - { - IDebugPort2 p; - AddPort(new AD7PortRequest("Simulator: " + SimulatorIP + "-" + SimulatorPassword), out p); - } - return 1; - } - - - /// - /// Creates an AD7Port. - /// - /// Port request. - /// Returns an AD7Port. - AD7Port CreatePort(AD7PortRequest port_request) - { - string portname; - Guid guid; - bool isSimulator = false; - port_request.GetPortName(out portname); - string password = portname.Substring(portname.IndexOf('-') + 1); - portname = portname.Remove(portname.IndexOf('-')); - if (portname.Substring(0, 6) == "Device") - guid = new Guid("{69519DBB-5329-4CCE-88A9-EC1628AD99C2}"); - else - { - guid = new Guid("{25040BDD-6683-4D5C-8EFA-EB4DDF5CA08E}"); - isSimulator = true; - } - - return new AD7Port(this, port_request, guid, portname, password, isSimulator, m_toolsPath); - } - - - #region Implementation of IDebugPortSupplier2 - - /// - /// Adds a port. (http://msdn.microsoft.com/en-ca/library/bb161980.aspx) - /// - /// An IDebugPortRequest2 object that describes the port to be added. - /// Returns an IDebugPort2 object that represents the port. - /// VSConstants.S_OK. - public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) - { - AD7PortRequest port_request = (AD7PortRequest)pRequest; - var port = CreatePort(port_request); - m_ports.Add(port.m_guid, port); - ppPort = port; - return VSConstants.S_OK; - } - - - /// - /// Verifies that a port supplier can add new ports. (http://msdn.microsoft.com/en-ca/library/bb145880.aspx) - /// - /// VSConstants.S_OK. - public int CanAddPort() - { - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of all the ports supplied by a port supplier. (http://msdn.microsoft.com/en-ca/library/bb146984.aspx) - /// - /// Returns an IEnumDebugPorts2 object containing a list of ports supplied. - /// VSConstants.S_OK. - public int EnumPorts(out IEnumDebugPorts2 ppEnum) - { - m_ports.Clear(); - int success = verifyAndAddPorts(); - AD7Port[] ports = new AD7Port[m_ports.Count()]; - - if (m_ports.Count() > 0) - { - int i = 0; - foreach (var p in m_ports) - { - ports[i] = p.Value; - i++; - } - } - else - { - if (success == 0) - MessageBox.Show("Visual Studio can debug only one BlackBerry application at a time.\n\nPlease, select a different transport or close the current debug session.", "Visual Studio is already debugging an application", MessageBoxButtons.OK, MessageBoxIcon.Warning); - else if (success == -1) - MessageBox.Show("You must select an API Level to be able to attach to a running process.\n\nPlease, use \"BlackBerry -> Settings -> Get more\" to download one.", "Missing NDK", MessageBoxButtons.OK, MessageBoxIcon.Warning); - else - MessageBox.Show("Missing Device/Simulator information. Please, use menu BlackBerry -> Settings to add any of those information.", "Missing Device/Simulator Data", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - - ppEnum = new AD7PortEnum(ports); - return VSConstants.S_OK; - } - - - /// - /// Gets a port from a port supplier. (http://msdn.microsoft.com/en-ca/library/bb161812.aspx) - /// - /// Globally unique identifier (GUID) of the port. - /// Returns an IDebugPort2 object that represents the port. - /// VSConstants.S_OK. - public int GetPort(ref Guid guidPort, out IDebugPort2 ppPort) - { - ppPort = m_ports[guidPort]; - return VSConstants.S_OK; - } - - - /// - /// Gets the port supplier identifier. (http://msdn.microsoft.com/en-ca/library/bb146617.aspx) - /// - /// Returns the GUID of the port supplier. - /// VSConstants.S_OK. - public int GetPortSupplierId(out Guid pguidPortSupplier) - { - pguidPortSupplier = this.GetType().GUID; - return VSConstants.S_OK; - } - - - /// - /// Gets the port supplier name. (http://msdn.microsoft.com/en-ca/library/bb162136.aspx) - /// - /// Returns the name of the port supplier. - /// VSConstants.S_OK. - public int GetPortSupplierName(out string pbstrName) - { - pbstrName = m_name; - return VSConstants.S_OK; - } - - - /// - /// Removes a port. Not implemented. (http://msdn.microsoft.com/en-ca/library/bb162306.aspx) - /// - /// An IDebugPort2 object that represents the port to be removed. - /// Not implemented. It should returns S_OK if successful; or an error code. - public int RemovePort(IDebugPort2 pPort) - { - throw new NotImplementedException(); - } - - #endregion - - - #region Implementation of IDebugPortSupplierDescription2 - - /// - /// Retrieves the description for the port supplier. (http://msdn.microsoft.com/en-us/library/bb457978.aspx) - /// - /// Metadata flags for the description. - /// Description of the port supplier. - /// VSConstants.S_OK. - public int GetDescription(enum_PORT_SUPPLIER_DESCRIPTION_FLAGS[] pdwFlags, out string pbstrText) - { - pbstrText = m_description; - return VSConstants.S_OK; - } - - #endregion - - /// - /// Decrypts a given string. - /// - /// A base64 encoded string that was created - /// through the or - /// extension methods. - /// The decrypted string. - /// Keep in mind that the decrypted string remains in memory - /// and makes your application vulnerable per se. If runtime protection - /// is essential, should be used. - /// If - /// is a null reference. - public string Decrypt(string cipher) - { - if (cipher == null) throw new ArgumentNullException("cipher"); - - //parse base64 string - byte[] data = Convert.FromBase64String(cipher); - - //decrypt data - byte[] decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.LocalMachine); - - return Encoding.Unicode.GetString(decrypted); - } - } -} \ No newline at end of file diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Process.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Process.cs deleted file mode 100644 index 0ec91b9a..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Process.cs +++ /dev/null @@ -1,412 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using VSNDK.Parser; -using System.Collections.Specialized; -using Microsoft.VisualStudio.Shell.Interop; -//using VSNDK.AddIn; -using System.Windows.Forms; - - -namespace VSNDK.DebugEngine -{ - /// - /// This class represents a process running on a port. If the port is the local port, then IDebugProcess2 usually represents a - /// physical process on the local machine. Not implemented completely. (http://msdn.microsoft.com/en-ca/library/bb147137.aspx). - /// - /// It also implements IDebugProcessEx2: This interface lets the session debug manager (SDM) notify a process that it is - /// attaching to or detaching from the process. (http://msdn.microsoft.com/en-us/library/bb145892.aspx) - /// - /// Process "Is a container for a set of programs". - /// - /// This interface is implemented by a custom port supplier to manage programs as a group. An IDebugProcess2 contains one or more - /// IDebugProgram2 interfaces. - /// - public class AD7Process : IDebugProcess2, IDebugProcessEx2 - { - /// - /// Identifies the session in which this process is attached to. - /// - IDebugSession2 session; - - /// - /// The name of the process. Not used till now. Has no value assigned to it. - /// - public string _name; - - /// - /// The AD7Port object that represents the port used in Attach to Process UI. - /// - public AD7Port _portAttach = null; - - /// - /// The IDebugPort2 object that represents the port on which the process was launched. - /// - IDebugPort2 _port = null; - - /// - /// Process GUID. - /// - public Guid _processGUID = Guid.NewGuid(); - - /// - /// Process ID. - /// - public string _processID; - - /// - /// The server on which this process is running. Not used till now. Has no value assigned to it. - /// - IDebugCoreServer2 _server; - - /// - /// The AD7Engine object that represents the DE. - /// - protected AD7Engine _engine = null; - - /// - /// A program that is running in this process. It should be an array of programs, as a process "is a container for - /// a set of programs" but, at this moment, the VSNDK supports only one program at a time. - /// - public IDebugProgram2 m_program = null; - - /// - /// The list of programs that are running in this process. - /// - List m_listOfPrograms = new List(); - - /// - /// Constructor. - /// - /// The AD7Engine object that represents the DE. - /// The IDebugPort2 object that represents the port on which the process was launched. - public AD7Process(AD7Engine aEngine, IDebugPort2 aPort) - { - _engine = aEngine; - _port = aPort; - m_program = aEngine.m_program; - } - - - /// - /// Constructor. - /// - /// The AD7Port object that represents the port used in Attach to Process UI. - /// The process ID. - /// The process name. - public AD7Process(AD7Port aPort, string ID, string name) - { - _portAttach = aPort; - _processID = ID; - _name = name; - } - - - /// - /// Attaches the session debug manager (SDM) to the process. Not implemented. Currently using IDebugEngine2.Attach. - /// (http://msdn.microsoft.com/en-ca/library/bb145875.aspx) - /// - /// An IDebugEventCallback2 object that is used for debug event notification. - /// An array of GUIDs of debug engines to be used to debug programs running in the process. - /// This parameter can be a null value. - /// The number of debug engines in the rgguidSpecificEngines array and the size of the - /// rghrEngineAttach array. - /// An array of HRESULT codes returned by the debug engines. - /// VSConstants.S_OK. - public int Attach(IDebugEventCallback2 pCallback, Guid[] rgguidSpecificEngines, uint celtSpecificEngines, int[] rghrEngineAttach) - { - return VSConstants.S_OK; - } - - - /// - /// Determines if the session debug manager (SDM) can detach the process. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb145567.aspx) - /// - /// VSConstants.S_OK. - public int CanDetach() - { - return VSConstants.S_OK; - } - - - /// - /// Requests that the next program that is running code in this process halt and send an IDebugBreakEvent2 event object. - /// Not implemented. (http://msdn.microsoft.com/en-us/library/bb162292.aspx) - /// - /// VSConstants.S_OK. - public int CauseBreak() - { - return VSConstants.S_OK; - } - - - /// - /// Detaches the debugger from this process by detaching all of the programs in the process. - /// (http://msdn.microsoft.com/en-us/library/bb162197.aspx) - /// - /// VSConstants.S_OK. - public int Detach() - { - _port = null; - _portAttach = null; - _engine = null; - m_program = null; - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of all the programs contained by this process. - /// (http://msdn.microsoft.com/en-us/library/bb162305.aspx) - /// - /// Returns an IEnumDebugPrograms2 object that contains a list of all the programs in the process. - /// VSConstants.S_OK. - public int EnumPrograms(out IEnumDebugPrograms2 ppEnum) - { - if (m_listOfPrograms.Count == 0) - { - AD7ProgramNodeAttach pn = new AD7ProgramNodeAttach(this, new Guid("{E5A37609-2F43-4830-AA85-D94CFA035DD2}")); - m_listOfPrograms.Add((IDebugProgram2)pn); - } - IDebugProgram2[] p = new IDebugProgram2[m_listOfPrograms.Count()]; - int i = 0; - foreach (var prog in m_listOfPrograms) - { - p[i] = prog; - i++; - } - ppEnum = new AD7ProgramEnum(p); - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of all the threads running in all programs in the process. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb144981.aspx) - /// - /// Returns an IEnumDebugThreads2 object that contains a list of all threads in all programs in the - /// process. - /// VSConstants.S_OK. - public int EnumThreads(out IEnumDebugThreads2 ppEnum) - { - ppEnum = null; - return VSConstants.S_OK; - } - - - /// - /// Gets the name of the session that is debugging the process. [DEPRECATED. SHOULD ALWAYS RETURN E_NOTIMPL.] - /// (http://msdn.microsoft.com/en-us/library/bb146718.aspx) - /// - /// DEPRECATED. Return null. - /// This method should always return E_NOTIMPL. - public int GetAttachedSessionName(out string pbstrSessionName) - { - pbstrSessionName = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Gets a description of the process. (http://msdn.microsoft.com/en-us/library/bb145895.aspx) - /// - /// A combination of values from the PROCESS_INFO_FIELDS enumeration that specifies which fields of - /// the pProcessInfo parameter are to be filled in. - /// A PROCESS_INFO structure that is filled in with a description of the process. - /// VSConstants.S_OK. - public int GetInfo(enum_PROCESS_INFO_FIELDS Fields, PROCESS_INFO[] pProcessInfo) - { - try - { - if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_FILE_NAME) != 0) - { - pProcessInfo[0].bstrFileName = this._name; - pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_FILE_NAME; - } - if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_BASE_NAME) != 0) - { - pProcessInfo[0].bstrBaseName = this._name.Substring(_name.LastIndexOf('/') + 1); - pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_BASE_NAME; - } - if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_TITLE) != 0) - { - pProcessInfo[0].bstrTitle = this._name; - pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_TITLE; - } - if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_PROCESS_ID) != 0) - { - pProcessInfo[0].ProcessId.dwProcessId = Convert.ToUInt32(this._processID); - pProcessInfo[0].ProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; - pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_PROCESS_ID; - } - if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_SESSION_ID) != 0) - { -// pProcessInfo[0].dwSessionId = 0; - pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_SESSION_ID; - } - if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_ATTACHED_SESSION_NAME) != 0) - { -// pProcessInfo[0].bstrAttachedSessionName = null; - pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_ATTACHED_SESSION_NAME; - } - if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_CREATION_TIME) != 0) - { -// pProcessInfo[0].CreationTime = null; - pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_CREATION_TIME; - } - - return VSConstants.S_OK; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Gets the name of the process. (http://msdn.microsoft.com/en-us/library/bb161270.aspx) - /// - /// A value from the GETNAME_TYPE enumeration that specifies what type of name to return. - /// Returns the name of the process. - /// VSConstants.S_OK. - public int GetName(enum_GETNAME_TYPE gnType, out string pbstrName) - { - pbstrName = _name; - return VSConstants.S_OK; - } - - - /// - /// Gets the system process identifier. (http://msdn.microsoft.com/en-us/library/bb146648.aspx) - /// - /// An AD_PROCESS_ID structure that is filled in with the system process identifier information. - /// VSConstants.S_OK. - public int GetPhysicalProcessId(AD_PROCESS_ID[] pProcessId) - { - if (_engine == null) - { - pProcessId[0].dwProcessId = Convert.ToUInt32(_processID); - pProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; - } - else - { - pProcessId[0].guidProcessId = _processGUID; - pProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; - } - - return VSConstants.S_OK; - } - - - /// - /// Gets the port that the process is running on. (http://msdn.microsoft.com/en-us/library/bb162121.aspx) - /// - /// Returns an IDebugPort2 object that represents the port on which the process was launched. - /// VSConstants.S_OK. - public int GetPort(out IDebugPort2 ppPort) - { - ppPort = _port; - return VSConstants.S_OK; - } - - - /// - /// Gets the GUID for this process. (http://msdn.microsoft.com/en-us/library/bb161938.aspx) - /// - /// Returns the GUID for this process. - /// VSConstants.S_OK. - public int GetProcessId(out Guid pguidProcessId) - { - pguidProcessId = _processGUID; - return VSConstants.S_OK; - } - - - /// - /// Gets the server that this process is running on. Not implemented completely because _server has no value assigned to it. - /// (http://msdn.microsoft.com/en-us/library/bb147017.aspx) - /// - /// Returns an IDebugCoreServer2 object that represents the server on which this process is running. - /// VSConstants.S_OK. - public int GetServer(out IDebugCoreServer2 ppServer) - { - ppServer = _server; - return VSConstants.S_OK; - } - - - /// - /// Terminates the process. Not implemented. (http://msdn.microsoft.com/en-us/library/bb146226.aspx) - /// - /// VSConstants.S_OK. - public int Terminate() - { - return VSConstants.S_OK; - } - - - #region IDebugProcessEx2 Members - - /// - /// Informs the process that a session is now debugging the process. (http://msdn.microsoft.com/en-us/library/bb162300.aspx) - /// - /// A value that uniquely identifies the session attaching to this process. - /// VSConstants.S_OK. - public int Attach(IDebugSession2 pSession) - { - session = pSession; - return VSConstants.S_OK; - } - - - /// - /// Informs the process that a session is no longer debugging the process. (http://msdn.microsoft.com/en-us/library/bb146313.aspx) - /// - /// A value that uniquely identifies the session to detach this process from. - /// VSConstants.S_OK. - public int Detach(IDebugSession2 pSession) - { - session = pSession; - return VSConstants.S_OK; - } - - - /// - /// Adds program nodes for a list of debug engines. (http://msdn.microsoft.com/en-us/library/bb146990.aspx) - /// In this project, it is used only one debug engine, that's why its GUID is assigned to the guidLaunchingEngine explicitly. - /// - /// The GUID of a DE that is to be used to launch programs (and is assumed to add its own - /// program nodes). - /// Array of GUIDs of DEs for which program nodes will be added. - /// The number of GUIDs in the rgguidSpecificEngines array. - /// VSConstants.S_OK. - public int AddImplicitProgramNodes(ref Guid guidLaunchingEngine, Guid[] rgguidSpecificEngines, uint celtSpecificEngines) - { - guidLaunchingEngine = new Guid("{E5A37609-2F43-4830-AA85-D94CFA035DD2}"); - return VSConstants.S_OK; - } - - #endregion - - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramNode.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramNode.cs deleted file mode 100644 index 94404c2b..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramNode.cs +++ /dev/null @@ -1,210 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; - -namespace VSNDK.DebugEngine -{ - /// - /// This class implements IDebugProgramNode2. (http://msdn.microsoft.com/en-ca/library/bb146735.aspx) - /// This interface represents a program that can be debugged. - /// A running process is viewed as a ProgramNode by VS. - /// A debug engine (DE) or a custom port supplier implements this interface to represent a program that can be debugged. - /// - public class AD7ProgramNode : IDebugProgramNode2 - { - /// - /// The GUID of the hosting process. - /// - readonly Guid m_processGuid; - - /// - /// The ID of the program to be debugged. - /// - public string m_programID; - - /// - /// The program friendly name. - /// - public string m_programName; - - /// - /// The file name of the program to be debugged. - /// - readonly string m_exePath; - - /// - /// The GUID of the VSNDK debug engine. - /// - readonly Guid m_engineGuid; - - - /// - /// Constructor. - /// At this moment, used only for testing purposes, because GetProviderProcessData (AD7ProgramProvider.cs) needs a program node. - /// - /// The GUID for this process. - public AD7ProgramNode(Guid processGuid) - { - m_processGuid = processGuid; - m_programID = ""; - m_exePath = ""; - m_programName = ""; - m_engineGuid = new Guid(AD7Engine.Id); - } - - - /// - /// Constructor. - /// - /// The GUID for this process. - /// The ID of the program to be debugged. - /// The name of the executable to be debugged. - /// The GUID of the VSNDK debug engine. - public AD7ProgramNode(Guid processGuid, string programID, string exePath, Guid engineGuid) - { - m_processGuid = processGuid; - m_programID = programID; - - m_exePath = exePath; - do - { - m_exePath = m_exePath.Replace("\\\\", "\\"); - } - while (m_exePath.IndexOf("\\\\") != -1); - - int i = exePath.LastIndexOf('\\'); - if ((i != -1) && (i < (exePath.Length - 1))) - m_programName = exePath.Substring(i + 1); - else - m_programName = exePath; - - m_engineGuid = engineGuid; - } - - #region IDebugProgramNode2 Members - - - /// - /// Gets the name and identifier of the DE running this program. (http://msdn.microsoft.com/en-ca/library/bb146303.aspx) - /// - /// Returns the name of the DE running the program (C++-specific: this can be a null pointer - /// indicating that the caller is not interested in the name of the engine). - /// Returns the globally unique identifier of the DE running the program (C++-specific: this can - /// be a null pointer indicating that the caller is not interested in the GUID of the engine). - /// VSConstants.S_OK. - int IDebugProgramNode2.GetEngineInfo(out string engineName, out Guid engineGuid) - { - engineName = ""; - engineGuid = m_engineGuid; - - return VSConstants.S_OK; - } - - - /// - /// Gets the system process identifier for the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb162159.aspx) - /// - /// Returns the system process identifier for the hosting process. - /// VSConstants.S_OK. - int IDebugProgramNode2.GetHostPid(AD_PROCESS_ID[] pHostProcessId) - { - // According to the MSDN documentation (http://msdn.microsoft.com/en-us/library/bb162159.aspx), - // it should return the process id of the hosting process, but what is expected is the program ID... - pHostProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; - pHostProcessId[0].guidProcessId = m_processGuid; - - return VSConstants.S_OK; - } - - - /// - /// Gets the name of the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb145135.aspx) - /// - /// A value from the GETHOSTNAME_TYPE enumeration that specifies the type of name to return. - /// Returns the name of the hosting process. - /// VSConstants.S_OK. - int IDebugProgramNode2.GetHostName(enum_GETHOSTNAME_TYPE dwHostNameType, out string processName) - { - if (dwHostNameType == enum_GETHOSTNAME_TYPE.GHN_FILE_NAME) - processName = "(BB-pid = " + m_programID + ") " + m_exePath; - else - processName = m_programName; - return VSConstants.S_OK; - } - - - /// - /// Gets the name of a program. (http://msdn.microsoft.com/en-us/library/bb145928.aspx) - /// - /// Returns the name of the program. - /// VSConstants.S_OK. - int IDebugProgramNode2.GetProgramName(out string programName) - { - programName = m_programName; - return VSConstants.S_OK; - } - - #endregion - - #region Deprecated interface methods - // These methods are not called by the Visual Studio debugger, so they don't need to be implemented - - - /// - /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161399.aspx) - /// - /// The IDebugProgram2 interface that represents the program to attach to. - /// The IDebugEventCallback2 interface to be used to send debug events to the SDM. - /// A value from the ATTACH_REASON enumeration that specifies the reason for attaching. - /// VSConstants.E_NOTIMPL. - int IDebugProgramNode2.Attach_V7(IDebugProgram2 pMDMProgram, IDebugEventCallback2 pCallback, uint dwReason) - { - Debug.Fail("This function is not called by the debugger"); - return VSConstants.E_NOTIMPL; - } - - - /// - /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161803.aspx) - /// - /// VSConstants.E_NOTIMPL. - int IDebugProgramNode2.DetachDebugger_V7() - { - Debug.Fail("This function is not called by the debugger"); - return VSConstants.E_NOTIMPL; - } - - - /// - /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161297.aspx) - /// - /// Returns the name of the machine in which the program is running. - /// VSConstants.E_NOTIMPL. - int IDebugProgramNode2.GetHostMachineName_V7(out string hostMachineName) - { - Debug.Fail("This function is not called by the debugger"); - hostMachineName = null; - return VSConstants.E_NOTIMPL; - } - - #endregion - } - -} \ No newline at end of file diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramNodeAttach.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramNodeAttach.cs deleted file mode 100644 index fea2d83b..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramNodeAttach.cs +++ /dev/null @@ -1,470 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using System.Xml; -using System.Xml.Linq; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; - -namespace VSNDK.DebugEngine -{ - /// - /// This class is used only when the user wants to Attach to a running process and it implements: - /// - IDebugProgramNode2. (http://msdn.microsoft.com/en-ca/library/bb146735.aspx) - /// - and IDebugProgram2. (http://msdn.microsoft.com/en-us/library/bb147004.aspx) - /// - /// The Debug Engine does not use this class. It uses AD7ProgramNode.cs. This class is used only to represent each of the running - /// processes that can be attached to the debug engine. When the debug engine attaches to a running process, an AD7ProgramNode - /// class is used to represent the chosen running program. That's why some methods were not implemented. - /// - /// This interface represents a program that can be debugged. - /// A running process is viewed as a ProgramNode by VS. - /// A debug engine (DE) or a custom port supplier implements this interface to represent a program that can be debugged. - /// - class AD7ProgramNodeAttach : IDebugProgramNode2, IDebugProgram2 - { - /// - /// The hosting process. - /// - public AD7Process m_process; - - /// - /// The GUID of the hosting process. - /// - public Guid m_processGuid; - - /// - /// The ID of the program to be debugged. - /// - public string m_programID; - - /// - /// The program friendly name. - /// - public string m_programName; - - /// - /// The file name of the program to be debugged. - /// - readonly string m_exePath; - - /// - /// The GUID of the VSNDK debug engine. - /// - readonly Guid m_engineGuid; - - - /// - /// Constructor. - /// - /// The hosting process. - /// The GUID of the VSNDK debug engine. - public AD7ProgramNodeAttach(AD7Process proc, Guid engineGuid) - { - m_process = proc; - m_processGuid = proc._processGUID; - m_programID = proc._processID; - - m_exePath = proc._name; - do - { - m_exePath = m_exePath.Replace("\\\\", "\\"); - } - while (m_exePath.IndexOf("\\\\") != -1); - - int i = proc._name.LastIndexOf('\\'); - if ((i != -1) && (i < (proc._name.Length - 1))) - m_programName = proc._name.Substring(i + 1); - else - m_programName = proc._name; - - m_engineGuid = engineGuid; - } - - - #region IDebugProgram2 Members - - - /// - /// Determines if a debug engine (DE) can detach from the program. (http://msdn.microsoft.com/en-us/library/bb161967.aspx) - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// VSConstants.S_OK. - public int CanDetach() - { - // The VSNDK debug engine always supports detach - return VSConstants.S_OK; - } - - - /// - /// Requests that the program stop execution the next time one of its threads attempts to run. The debugger calls CauseBreak - /// when the user clicks on the pause button in VS. The debugger should respond by entering breakmode. - /// (http://msdn.microsoft.com/en-us/library/bb145018.aspx) - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// VSConstants.S_OK. - public int CauseBreak() - { - return ((IDebugEngine2)this).CauseBreak(); - } - - - /// - /// Continues running this program from a stopped state. Any previous execution state (such as a step) is preserved, and - /// the program starts executing again. (http://msdn.microsoft.com/en-us/library/bb162148.aspx). - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// An IDebugThread2 object that represents the thread. - /// VSConstants.S_OK. - public int Continue(IDebugThread2 pThread) - { - // This method is not called by the debug engine. - return VSConstants.S_OK; - } - - - /// - /// Detaches a debug engine from the program. (http://msdn.microsoft.com/en-us/library/bb146228.aspx) - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// VSConstants.S_OK. - public int Detach() - { - // This method is not called by the debug engine. - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of the code contexts for a given position in a source file. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb145902.aspx) - /// - /// An object representing an abstract position in a source file known to the IDE. - /// Returns an IEnumDebugCodeContexts2 object that contains a list of the code contexts. - /// Not implemented. - public int EnumCodeContexts(IDebugDocumentPosition2 pDocPos, out IEnumDebugCodeContexts2 ppEnum) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Retrieves a list of the code paths for a given position in a source file. EnumCodePaths is used for the step-into specific - /// feature -- right click on the current statement and decide which function to step into. This is not something that the - /// VSNDK debug engine supports. (http://msdn.microsoft.com/en-us/library/bb162326.aspx) - /// - /// The word under the cursor in the Source or Disassembly view in the IDE. - /// An IDebugCodeContext2 object representing the current code context. - /// An IDebugStackFrame2 object representing the stack frame associated with the current breakpoint. - /// Nonzero (TRUE) if in the Source view, or zero (FALSE) if in the Disassembly view. - /// Returns an IEnumCodePaths2 object containing a list of the code paths. - /// Returns an IDebugCodeContext2 object representing an additional code context to be set as a - /// breakpoint in case the chosen code path is skipped. This can happen in the case of a short-circuited Boolean expression, - /// for example. - /// VSConstants.E_NOTIMPL. - public int EnumCodePaths(string Hint, IDebugCodeContext2 start, IDebugStackFrame2 frame, int fSource, out IEnumCodePaths2 pathEnum, out IDebugCodeContext2 safetyContext) - { - pathEnum = null; - safetyContext = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Retrieves a list of the modules that this program has loaded and is executing. - /// (http://msdn.microsoft.com/en-us/library/bb146980.aspx) - /// - /// Returns an IEnumDebugModules2 object that contains a list of the modules. - /// VSConstants.S_OK. - public int EnumModules(out IEnumDebugModules2 ppEnum) - { - // Setting ppEnum to null because we are not adding/working with this feature now. It was causing an error - // when opening Threads Window and ppEnum = new AD7ModuleEnum(new[] { m_module }). - ppEnum = null; - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of the threads that are running in the program. (http://msdn.microsoft.com/en-us/library/bb145110.aspx) - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// Returns an IEnumDebugThreads2 object that contains a list of the threads. - /// If successful, returns S_OK; otherwise, returns an error code. - public int EnumThreads(out IEnumDebugThreads2 ppEnum) - { - ppEnum = null; - return VSConstants.S_OK; - } - - - /// - /// Gets the program's properties. The VSNDK debug engine does not support this. - /// (http://msdn.microsoft.com/en-us/library/bb161801.aspx) - /// - /// Returns an IDebugProperty2 object that represents the program's properties. - /// Not implemented. - public int GetDebugProperty(out IDebugProperty2 ppProperty) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Gets the disassembly stream for this program or a part of this program. - /// The sample engine does not support dissassembly so it returns E_NOTIMPL - /// - /// Specifies a value from the DISASSEMBLY_STREAM_SCOPE enumeration that defines the scope of the - /// disassembly stream. - /// An object that represents the position of where to start the disassembly stream. - /// Returns an IDebugDisassemblyStream2 object that represents the disassembly stream. - /// VSConstants.E_NOTIMPL. - public int GetDisassemblyStream(enum_DISASSEMBLY_STREAM_SCOPE dwScope, IDebugCodeContext2 codeContext, out IDebugDisassemblyStream2 disassemblyStream) - { - disassemblyStream = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// This method gets the Edit and Continue (ENC) update for this program. A custom debug engine always returns E_NOTIMPL - /// - /// Returns an internal interface that can be used to update this program. - /// VSConstants.S_OK. - public int GetENCUpdate(out object update) - { - // The VSNDK debug engine does not participate in managed edit & continue. - update = null; - return VSConstants.S_OK; - } - - - /// - /// Retrieves the memory bytes occupied by the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145291.aspx) - /// - /// Returns an IDebugMemoryBytes2 object that represents the memory bytes of the program. - /// Not implemented. - public int GetMemoryBytes(out IDebugMemoryBytes2 ppMemoryBytes) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Gets the name of the program. The name returned by this method is always a friendly, user-displayable name that describes - /// the program. (http://msdn.microsoft.com/en-us/library/bb161279.aspx) - /// - /// Returns the name of the program. - /// VSConstants.S_OK. - public int GetName(out string programName) - { - programName = this.m_programName; - return VSConstants.S_OK; - } - - - /// - /// Gets a GUID for this program. A debug engine (DE) must return the program identifier originally passed to the - /// IDebugProgramNodeAttach2::OnAttach or IDebugEngine2::Attach methods. This allows identification of the program - /// across debugger components. (http://msdn.microsoft.com/en-us/library/bb145581.aspx) - /// - /// Returns the GUID for this program. - /// VSConstants.S_OK. - public int GetProgramId(out Guid guidProgramId) - { - guidProgramId = m_processGuid; - return VSConstants.S_OK; - } - - - /// - /// Performs a step. This method is deprecated. Use the IDebugProcess3::Step method instead. - /// (http://msdn.microsoft.com/en-us/library/bb162134.aspx) - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// An IDebugThread2 object that represents the thread being stepped. - /// A value from the STEPKIND enumeration that specifies the kind of step. - /// A value from the STEPUNIT enumeration that specifies the unit of step. - /// If successful, returns S_OK; otherwise, returns an error code. - public int Step(IDebugThread2 pThread, enum_STEPKIND sk, enum_STEPUNIT Step) - { - return VSConstants.S_OK; - } - - - /// - /// Terminates the program. (http://msdn.microsoft.com/en-us/library/bb145919.aspx) - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// VSConstants.S_OK. - public int Terminate() - { - return VSConstants.S_OK; - } - - - /// - /// Writes a dump to a file. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145827.aspx) - /// - /// A value from the DUMPTYPE enumeration that specifies the type of dump, for example, short or - /// long. - /// The URL to write the dump to. Typically, this is in the form of file://c:\path\filename.ext, - /// but may be any valid URL. - /// VSConstants.E_NOTIMPL. - public int WriteDump(enum_DUMPTYPE DUMPTYPE, string pszDumpUrl) - { - // The VSNDK debugger does not support creating or reading mini-dumps. - return VSConstants.E_NOTIMPL; - } - - - /// - /// Get the process that this program is running in. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145293.aspx) - /// - /// Returns the IDebugProcess2 interface that represents the process. - /// VSConstants.E_NOTIMPL. - public int GetProcess(out IDebugProcess2 process) - { - Debug.Fail("This function is not called by the debugger"); - - process = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Attaches to the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb161973.aspx) - /// - /// An IDebugEventCallback2 object to be used for debug event notification. - /// VSConstants.E_NOTIMPL. - public int Attach(IDebugEventCallback2 pCallback) - { - Debug.Fail("This function is not called by the debugger"); - - return VSConstants.E_NOTIMPL; - } - - - /// - /// Continues running this program from a stopped state. Any previous execution state (such as a step) is cleared, and the - /// program starts executing again. Not implemented. (http://msdn.microsoft.com/en-us/library/bb162315.aspx) - /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. - /// - /// VSConstants.S_OK. - public int Execute() - { - return VSConstants.S_OK; - } - - #endregion - - #region IDebugProgramNode2 Members - - - /// - /// Gets the name and GUID of the debug engine running this program. (http://msdn.microsoft.com/en-ca/library/bb146303.aspx) - /// - /// Returns the name of the DE running this program. - /// Returns the GUID of the DE running this program. - /// VSConstants.S_OK. - public int GetEngineInfo(out string engineName, out Guid engineGuid) - { - engineName = "VSNDK Debug Engine"; - engineGuid = m_engineGuid; - - return VSConstants.S_OK; - } - - - /// - /// Gets the system process identifier for the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb162159.aspx) - /// - /// Returns the system process identifier for the hosting process. - /// VSConstants.S_OK. - public int GetHostPid(AD_PROCESS_ID[] pHostProcessId) - { - // According to the MSDN documentation (http://msdn.microsoft.com/en-us/library/bb162159.aspx), - // it should return the process id of the hosting process, but what is expected is the program ID... - pHostProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; - pHostProcessId[0].guidProcessId = m_processGuid; - - return VSConstants.S_OK; - } - - - /// - /// Gets the name of the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb145135.aspx) - /// - /// A value from the GETHOSTNAME_TYPE enumeration that specifies the type of name to return. - /// Returns the name of the hosting process. - /// VSConstants.S_OK. - public int GetHostName(enum_GETHOSTNAME_TYPE dwHostNameType, out string processName) - { - if (dwHostNameType == enum_GETHOSTNAME_TYPE.GHN_FILE_NAME) - processName = "(BB-pid = " + m_programID + ") " + m_exePath; - else - processName = m_programName; - return VSConstants.S_OK; - } - - - /// - /// Gets the name of a program. (http://msdn.microsoft.com/en-us/library/bb145928.aspx) - /// - /// Returns the name of the program. - /// VSConstants.S_OK. - int IDebugProgramNode2.GetProgramName(out string programName) - { - programName = m_programName; - return VSConstants.S_OK; - } - - #endregion - - #region Deprecated interface methods - // These methods are not called by the Visual Studio debugger, so they don't need to be implemented - - - /// - /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161399.aspx) - /// - /// The IDebugProgram2 interface that represents the program to attach to. - /// The IDebugEventCallback2 interface to be used to send debug events to the SDM. - /// A value from the ATTACH_REASON enumeration that specifies the reason for attaching. - /// VSConstants.E_NOTIMPL. - public int Attach_V7(IDebugProgram2 pMDMProgram, IDebugEventCallback2 pCallback, uint dwReason) - { - Debug.Fail("This function is not called by the debugger"); - return VSConstants.E_NOTIMPL; - } - - - /// - /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161803.aspx) - /// - /// VSConstants.E_NOTIMPL. - public int DetachDebugger_V7() - { - Debug.Fail("This function is not called by the debugger"); - return VSConstants.E_NOTIMPL; - } - - - /// - /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161297.aspx) - /// - /// Returns the name of the machine in which the program is running. - /// VSConstants.E_NOTIMPL. - public int GetHostMachineName_V7(out string hostMachineName) - { - Debug.Fail("This function is not called by the debugger"); - hostMachineName = null; - return VSConstants.E_NOTIMPL; - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramProvider.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramProvider.cs deleted file mode 100644 index fbd3518b..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7ProgramProvider.cs +++ /dev/null @@ -1,147 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; - -namespace VSNDK.DebugEngine -{ - /// - /// This class implments IDebugProgramProvider2. (http://msdn.microsoft.com/en-us/library/bb161298.aspx) - /// This registered interface allows the session debug manager (SDM) to obtain information about programs - /// that have been "published" through the IDebugProgramPublisher2 interface. - /// - /// Partially implemented and not used at this moment. - /// - [ComVisible(true)] - [Guid("AD06FD46-C790-4D5C-A274-8815DF9511B8")] - public class AD7ProgramProvider : IDebugProgramProvider2 - { - - /// - /// Constructor. - /// - public AD7ProgramProvider() - { - } - - #region IDebugProgramProvider2 Members - - - /// - /// Obtains information about programs running, filtered in a variety of ways. - /// (http://msdn.microsoft.com/en-us/library/bb147025.aspx) - /// - /// A combination of flags from the PROVIDER_FLAGS enumeration. - /// The port the calling process is running on. - /// An AD_PROCESS_ID structure holding the ID of the process that contains the program in question. - /// An array of GUIDs for debug engines assigned to debug this process (these will be used to filter - /// the programs that are actually returned based on what the supplied engines support; if no engines are specified, then all - /// programs will be returned). - /// A PROVIDER_PROCESS_DATA structure that is filled in with the requested information. - /// If successful, returns S_OK; otherwise, returns VSConstants.S_FALSE. - int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, PROVIDER_PROCESS_DATA[] processArray) - { - processArray[0] = new PROVIDER_PROCESS_DATA(); - - if (((uint)Flags & (uint)enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES) != 0) - { - // The debugger is asking the engine to return the program nodes it can debug. The VSNDK debug engine claims that it can - // debug all processes, and returns exactly one program node for each process. A full-featured debugger may wish to - // examine the target process and determine if it understands how to debug it. - - IDebugProgramNode2 node = (IDebugProgramNode2)(new AD7ProgramNode(ProcessId.guidProcessId)); - - IntPtr[] programNodes = { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; - - IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); - Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); - - processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; - processArray[0].ProgramNodes.Members = destinationArray; - processArray[0].ProgramNodes.dwCount = (uint)programNodes.Length; - - return VSConstants.S_OK; - } - - return VSConstants.S_FALSE; - } - - - /// - /// Gets a program node, given a specific process ID. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb162155.aspx) - /// - /// A combination of flags from the PROVIDER_FLAGS enumeration. - /// The port the calling process is running on. - /// An AD_PROCESS_ID structure holding the ID of the process that contains the program in question. - /// GUID of the debug engine that the program is attached to (if any). - /// ID of the program for which to get the program node. - /// An IDebugProgramNode2 object representing the requested program node. - /// VSConstants.E_NOTIMPL. - int IDebugProgramProvider2.GetProviderProgramNode(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 programNode) - { - // This method is used for Just-In-Time debugging support, which this program provider does not support - programNode = null; - return VSConstants.E_NOTIMPL; - } - - - /// - /// Establishes a locale for any language-specific resources needed by the DE. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/bb161383.aspx) - /// - /// Language ID to establish. For example, 1033 for English. - /// VSConstants.S_OK. - int IDebugProgramProvider2.SetLocale(ushort wLangID) - { - return VSConstants.S_OK; - } - - - /// - /// Establishes a callback to watch for provider events associated with specific kinds of processes, allowing the process to - /// be notified of port events. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145594.aspx) - /// - /// A combination of flags from the PROVIDER_FLAGS enumeration. - /// The port the calling process is running on. - /// An AD_PROCESS_ID structure holding the ID of the process that contains the program in question. - /// An array of GUIDs of debug engines associated with the process. - /// GUID of the debug engine that launched this process (if any). - /// An IDebugPortNotify2 object that receives the event notifications. - /// VSConstants.S_OK. - int IDebugProgramProvider2.WatchForProviderEvents(enum_PROVIDER_FLAGS Flags, IDebugDefaultPort2 port, AD_PROCESS_ID ProcessId, CONST_GUID_ARRAY EngineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 ad7EventCallback) - { - // The VSNDK debug engine is a native debugger, and can therefore always provide a program node - // in GetProviderProcessData. Non-native debuggers may wish to implement this method as a way - // of monitoring the process before code for their runtime starts. For example, if implementing a - // 'foo script' debug engine, one could attach to a process which might eventually run 'foo script' - // before this 'foo script' started. - // - // To implement this method, an engine would monitor the target process and call AddProgramNode - // when the target process started running code which was debuggable by the engine. The - // enum_PROVIDER_FLAGS.PFLAG_ATTACHED_TO_DEBUGGEE flag indicates if the request is to start - // or stop watching the process. - - return VSConstants.S_OK; - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Property.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Property.cs deleted file mode 100644 index 3a8c8f7c..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Property.cs +++ /dev/null @@ -1,377 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using VSNDK.Parser; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Collections; - -namespace VSNDK.DebugEngine -{ - /// - /// An implementation of IDebugProperty2. (http://msdn.microsoft.com/en-ca/library/bb161287.aspx) - /// This interface represents a stack frame property, a program document property, or some other property. - /// The property is usually the result of an expression evaluation. - /// - class AD7Property : IDebugProperty2 - { - - /// - /// Object that contains all information about a variable / expression. - /// - private VariableInfo _variableInfo; - - - /// - /// Object that contains all information about a stack frame. - /// - private AD7StackFrame _stackFrame; - - - /// - /// Constructor. - /// - /// Contains all information about a variable / expression. - public AD7Property(AD7StackFrame vi) - { - _stackFrame = vi; - } - - /// - /// Constructor. - /// - /// Contains all information about a variable / expression. - public AD7Property(VariableInfo vi) - { - _variableInfo = vi; - } - - /// - /// Construct a DEBUG_PROPERTY_INFO representing this local or parameter. - /// - /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which variables are - /// to be filled in. - /// The Property info. - public DEBUG_PROPERTY_INFO ConstructDebugPropertyInfo(enum_DEBUGPROP_INFO_FLAGS dwFields) - { - DEBUG_PROPERTY_INFO propertyInfo = new DEBUG_PROPERTY_INFO(); - - if (_variableInfo != null) - { - string name = _variableInfo._name; - if ((dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME) != 0) - { - propertyInfo.bstrFullName = name; - propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME)); - } - - if ((dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME) != 0) - { - propertyInfo.bstrName = name; - propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME)); - } - - if ((dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE) != 0) - { - propertyInfo.bstrType = _variableInfo._type; - propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE)); - } - - if ((dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE) != 0) - { - propertyInfo.bstrValue = _variableInfo._value; - propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE)); - } - - if ((dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB) != 0) - { - if (_variableInfo._children != null) - { - propertyInfo.dwAttrib |= (enum_DBG_ATTRIB_FLAGS)DBG_ATTRIB_FLAGS.DBG_ATTRIB_OBJ_IS_EXPANDABLE; - } - } - - // If the debugger has asked for the property, or the property has children (meaning it is a pointer in the sample) - // then set the pProperty field so the debugger can call back when the chilren are enumerated. - if ((dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP) != 0 || _variableInfo._children != null) - { - propertyInfo.pProperty = (IDebugProperty2)this; - propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP)); - } - - } - return propertyInfo; - } - - - #region IDebugProperty2 Members - - /// - /// Enumerates the children of a property. This provides support for dereferencing pointers, displaying members of an array, or - /// fields of a class or struct. (http://msdn.microsoft.com/en-us/library/bb161791.aspx) - /// - /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in - /// the enumerated DEBUG_PROPERTY_INFO structures are to be filled in. - /// Specifies the radix to be used in formatting any numerical information. - /// GUID of the filter used with the dwAttribFilter and pszNameFilter parameters to select which - /// DEBUG_PROPERTY_INFO children are to be enumerated. For example, guidFilterLocals filters for local variables. - /// A combination of flags from the DBG_ATTRIB_FLAGS enumeration that specifies what type of - /// objects to enumerate, for example DBG_ATTRIB_METHOD for all methods that might be children of this property. Used in - /// combination with the guidFilter and pszNameFilter parameters. - /// The name of the filter used with the guidFilter and dwAttribFilter parameters to select which - /// DEBUG_PROPERTY_INFO children are to be enumerated. For example, setting this parameter to "MyX" filters for all children - /// with the name "MyX." - /// Specifies the maximum time, in milliseconds, to wait before returning from this method. Use - /// INFINITE to wait indefinitely. - /// Returns an IEnumDebugPropertyInfo2 object containing a list of the child properties. - /// If successful, returns S_OK; otherwise returns S_FALSE. - public int EnumChildren(enum_DEBUGPROP_INFO_FLAGS dwFields, uint dwRadix, ref System.Guid guidFilter, enum_DBG_ATTRIB_FLAGS dwAttribFilter, string pszNameFilter, uint dwTimeout, out IEnumDebugPropertyInfo2 ppEnum) - { - ppEnum = null; - - if (_variableInfo != null) - { - if (_variableInfo._children != null) - { - if (_variableInfo._children.Count == 0) - { - // This is an array, struct, union, or pointer. - // Create a variable object so we can list this variable's children. - - /// Some VS variable names cannot be used by GDB. When that happens, it is added the prefix VsNdK_ to the GDB variable - /// name and it is stored in the GDBNames array. At the same time, the VS name is stored in the VSNames array using the - /// same index position. This bool variable just indicate if this prefix is used or not. - bool hasVsNdK_ = false; - - string numChildren = AD7StackFrame.m_dispatcher.createVar(_variableInfo._name, ref hasVsNdK_); - - ArrayList GDBNames = new ArrayList(); - ArrayList VSNames = new ArrayList(); - - if (hasVsNdK_) - { - _variableInfo._GDBName = "VsNdK_" + _variableInfo._name; - GDBNames.Add("VsNdK_" + _variableInfo._name); - VSNames.Add(_variableInfo._name); - } - - try // Catch non-numerical data - { - if (Convert.ToInt32(numChildren) > 0) // If the variable has children evaluate - { - if (_variableInfo._type.Contains("struct")) - if (_variableInfo._type[_variableInfo._type.Length - 1] == '*') - _variableInfo.listChildren(AD7StackFrame.m_dispatcher, "*", GDBNames, VSNames, hasVsNdK_, null); - else if (_variableInfo._type.Contains("[")) - _variableInfo.listChildren(AD7StackFrame.m_dispatcher, "struct[]", GDBNames, VSNames, hasVsNdK_, null); - else - _variableInfo.listChildren(AD7StackFrame.m_dispatcher, "struct", GDBNames, VSNames, hasVsNdK_, null); - else if (_variableInfo._type.Contains("[")) - _variableInfo.listChildren(AD7StackFrame.m_dispatcher, "[]", GDBNames, VSNames, hasVsNdK_, null); - else if (_variableInfo._type.Contains("*")) - _variableInfo.listChildren(AD7StackFrame.m_dispatcher, "*", GDBNames, VSNames, hasVsNdK_, null); - else - _variableInfo.listChildren(AD7StackFrame.m_dispatcher, "", GDBNames, VSNames, hasVsNdK_, null); - - } - } - catch (FormatException e) - { - } - AD7StackFrame.m_dispatcher.deleteVar(_variableInfo._name, hasVsNdK_); - } - DEBUG_PROPERTY_INFO[] properties = new DEBUG_PROPERTY_INFO[_variableInfo._children.Count]; - int i = 0; - foreach (VariableInfo child in _variableInfo._children) - { - VariableInfo.evaluateExpression(child._name, ref child._value, child._GDBName); - properties[i] = new AD7Property(child).ConstructDebugPropertyInfo(dwFields); - i++; - } - ppEnum = new AD7PropertyEnum(properties); - return VSConstants.S_OK; - } - } - else if (_stackFrame != null) - { - uint elementsReturned = 0; - _stackFrame.CreateLocalsPlusArgsProperties(dwFields, out elementsReturned, out ppEnum); - return VSConstants.S_OK; - } - - return VSConstants.S_FALSE; - } - - - /// - /// Returns the property that describes the most-derived property of a property. - /// (http://msdn.microsoft.com/en-ca/library/bb161781.aspx) - /// This is called to support object oriented languages. It allows the debug engine to return an IDebugProperty2 for the - /// most-derived object in a hierarchy. - /// The VSNDK debug engine does not support this. Not implemented. - /// - /// Returns an IDebugProperty2 object that represents the derived-most property. - /// Not implemented. - public int GetDerivedMostProperty(out IDebugProperty2 ppDerivedMost) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Returns the extended information of a property. (http://msdn.microsoft.com/en-ca/library/bb145070.aspx) - /// This method exists for the purpose of retrieving information that does not lend itself to being retrieved by calling the - /// IDebugProperty2::GetPropertyInfo method. This includes information about custom viewers, managed type slots and other - /// information. - /// The VSNDK debug engine does not support this. Not implemented. - /// - /// GUID that determines the type of extended information to be retrieved. - /// Returns a VARIANT (C++) or object (C#) that can be used to retrieve the extended property - /// information. For example, this parameter might return an IUnknown interface that can be queried for an IDebugDocumentText2 - /// interface. - /// Not implemented. - public int GetExtendedInfo(ref System.Guid guidExtendedInfo, out object pExtendedInfo) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Returns the memory bytes that compose the value of a property. (http://msdn.microsoft.com/en-ca/library/bb161360.aspx) - /// Not implemented. - /// - /// Returns an IDebugMemoryBytes2 object that can be used to retrieve the memory that contains - /// the value of the property. - /// Not implemented. - public int GetMemoryBytes(out IDebugMemoryBytes2 ppMemoryBytes) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Returns the memory context for a property value. (http://msdn.microsoft.com/en-ca/library/bb147028.aspx) - /// Not implemented. - /// - /// Returns the IDebugMemoryContext2 object that represents the memory associated with this property. - /// Not implemented. - public int GetMemoryContext(out IDebugMemoryContext2 ppMemory) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Returns the parent of a property. (http://msdn.microsoft.com/en-ca/library/bb146184.aspx) - /// Not implemented. - /// - /// Returns an IDebugProperty2 object that represents the parent of the property. - /// Not implemented. - public int GetParent(out IDebugProperty2 ppParent) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Fills in a DEBUG_PROPERTY_INFO structure that describes a property. (http://msdn.microsoft.com/en-ca/library/bb145852.aspx) - /// - /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields are to - /// be filled out in the pPropertyInfo structure. - /// Radix to be used in formatting any numerical information. - /// Specifies the maximum time, in milliseconds, to wait before returning from this method. Use - /// INFINITE to wait indefinitely. - /// Reserved for future use; set to a null value. - /// Reserved for future use; set to zero. - /// A DEBUG_PROPERTY_INFO structure that is filled in with the description of the property. - /// VSConstants.S_OK. - public int GetPropertyInfo(enum_DEBUGPROP_INFO_FLAGS dwFields, uint dwRadix, uint dwTimeout, IDebugReference2[] rgpArgs, uint dwArgCount, DEBUG_PROPERTY_INFO[] pPropertyInfo) - { - pPropertyInfo[0] = new DEBUG_PROPERTY_INFO(); - rgpArgs = null; - pPropertyInfo[0] = ConstructDebugPropertyInfo(dwFields); - - return VSConstants.S_OK; - } - - - /// - /// Returns a reference to the property's value. IDebugProperty2 represents a property, while IDebugReference2 represents a - /// reference to a property, typically a reference to an object in the program being debugged. Not implemented. - /// (http://msdn.microsoft.com/en-ca/library/bb145600.aspx) - /// - /// Returns an IDebugReference2 object representing a reference to the property's value. - /// Not implemented. - public int GetReference(out IDebugReference2 ppReference) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Returns the size, in bytes, of the property value. Not implemented. (http://msdn.microsoft.com/en-ca/library/bb145093.aspx) - /// - /// Returns the size, in bytes, of the property value. - /// Not implemented. - public int GetSize(out uint pdwSize) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Sets the value of the property from the value of a given reference. (http://msdn.microsoft.com/en-ca/library/bb145613.aspx) - /// The debugger will call this when the user tries to edit the property's values. As the sample has set the read-only flag on - /// its properties, this should not be called. - /// Not implemented. - /// - /// An array of arguments to pass to the managed code property setter. If the property setter does not - /// take arguments or if this IDebugProperty2 object does not refer to such a property setter, rgpArgs should be a null value. - /// This parameter is typically a null value. - /// The number of arguments in the rgpArgs array. - /// A reference, in the form of an IDebugReference2 object, to the value to use to set this property. - /// How long to take to set the value, in milliseconds. A typical value is INFINITE. This affects - /// the length of time that any possible evaluation can take. - /// Not implemented. - public int SetValueAsReference(IDebugReference2[] rgpArgs, uint dwArgCount, IDebugReference2 pValue, uint dwTimeout) - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Sets the value of a property from a given string. (http://msdn.microsoft.com/en-ca/library/bb160956.aspx) - /// The debugger will call this when the user tries to edit the property's values in one of the debugger windows. - /// - /// A string containing the value to be set. - /// A radix to be used in interpreting any numerical information. This can be 0 to attempt to determine - /// the radix automatically. - /// Specifies the maximum time, in milliseconds, to wait before returning from this method. Use - /// INFINITE to wait indefinitely. - /// VSConstants.S_OK. - public int SetValueAsString(string pszValue, uint dwRadix, uint dwTimeout) - { - string result = ""; - VariableInfo.evaluateExpression(this._variableInfo._name + "=" + pszValue, ref result, null); - - return VSConstants.S_OK; - } - - #endregion - - } -} diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7StackFrame.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7StackFrame.cs deleted file mode 100644 index 45efadb7..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7StackFrame.cs +++ /dev/null @@ -1,1442 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Collections; -using System.Text; -using Microsoft.VisualStudio; -using VSNDK.Parser; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; - -namespace VSNDK.DebugEngine -{ - /// - /// This class contains all information about a variable / expression. - /// - public class VariableInfo - { - - /// - /// Variable's name or expression. - /// - public string _name; - - /// - /// Variable's data type. - /// - public string _type; - - /// - /// Variable's value or the result of an expression. - /// - public string _value; - - /// - /// Variable's name to be used by GDB. - /// - public string _GDBName; - - /// - /// List of variable's children. - /// - public ArrayList _children; - - - /// - /// Evaluate an expression / Get the value of a variable. This method basically send a "-data-evaluate-expression" command to GDB - /// and evaluate the result. - /// - /// The expression/variable to be evaluated. - /// The result of the expression/ value of variable. - /// The GDB Name of the variable. - /// A boolean value indicating if the expression evaluation was successful or not. - public static bool evaluateExpression(string name, ref string result, string GDBName) - { - if (name[name.Length - 1] == '.') - name = name.Remove(name.Length - 1); - - // Waits for the parsed response for the GDB/MI command that evaluates "name" as an expression. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Data-Manipulation.html) - result = GDBParser.parseCommand("-data-evaluate-expression \"" + name + "\"", 2); - if (result.Substring(0, 2) == "61") // If result starts with 61, it means that there is an error. - { - if (GDBName != null) // Maybe that error was caused because GDB didn't accept the VS name. Use the GDBName if there is one. - { - // Gets the parsed response for the GDB/MI command that evaluates "GDBName" as an expression. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Data-Manipulation.html) - string result2 = GDBParser.parseCommand("-data-evaluate-expression \"" + GDBName + "\"", 2); - if (result2.Substring(0, 2) == "60") - result = result2; - } - } - - bool valid = true; - - if (result.Substring(0, 2) == "61") // If result starts with 61, it means that there is an error. So, expression is not valid. - valid = false; - - result = result.Substring(3); - result = result.Substring(1, result.Length - 2); // remove the quotes located in the beginning and at the end - result = result.Replace("\\\"", "\""); - - if (valid) - { - int endString = result.IndexOf("\\\\000"); - int ini, end = 0; - while (endString != -1) // remove garbage from strings - { - ini = result.IndexOf("\"", end); - while ((ini > 0) && (result[ini - 1] == '\\')) - ini = result.IndexOf("\"", ini + 1); - if (ini == -1) - break; - end = result.IndexOf("\"", ini + 1); - while ((end > 0) && (result[end - 1] == '\\')) - end = result.IndexOf("\"", end + 1); - if (end == -1) - break; - while ((endString != -1) && (endString < ini)) - endString = result.IndexOf("\\\\000", endString + 1); - if ((endString > ini) && (endString < end)) - { - result = result.Substring(0, endString) + result.Substring(end, (result.Length - end)); - end = endString; - endString = result.IndexOf("\\\\000", end); - } - end++; - }; - } - return valid; - } - - - /// - /// Gets the information about a variable/expression. - /// - /// Variable name / expression. - /// The event dispatcher. - /// Current stack frame. - /// Return the VariableInfo object. - public static VariableInfo get(string name, EventDispatcher m_eventDispatcher, AD7StackFrame m_frame) - { - VariableInfo vi = null; - string search = ""; - string separator = ""; - bool isArray = false; - bool isRoot = true; - - do - { - int dot = name.IndexOf("."); - int squareBracket = name.IndexOf("["); - int pos = name.IndexOf("->"); - if (dot == -1) - dot = name.Length; - if (squareBracket == -1) - squareBracket = name.Length; - if (pos == -1) - pos = name.Length; - int stop = dot < squareBracket ? dot : squareBracket; - stop = stop < pos ? stop : pos; - - search = search + separator + name.Substring(0, stop); - separator = ""; - - if (stop < name.Length) - { - separator = name.Substring(stop, 1); - if (separator == "-") - { - separator = "->"; - name = name.Substring(stop + 2, name.Length - (stop + 2)); - } - else if (separator == "[") - { - int aux = name.IndexOf("]"); - isArray = true; - separator = name.Substring(stop, (aux - stop) + 1); - name = name.Substring(aux + 1, name.Length - (aux + 1)); - } - else - name = name.Substring(stop + 1, name.Length - (stop + 1)); - } - else - name = ""; - - if (vi == null) - { - if (m_frame._locals != null) - { - foreach (VariableInfo var in m_frame._locals) - { - if (var._name == search) - { // if the "search" expression is a local variable, it doesn't need to create a VariableInfo object for that. - vi = var; - break; - } - } - } - - if (vi == null) - { - if (m_frame._arguments != null) - { - foreach (VariableInfo var in m_frame._arguments) - { // if the "search" expression is an argument, it doesn't need to create a VariableInfo object for that. - if (var._name == search) - { - vi = var; - break; - } - } - } - } - } - else - { - isRoot = false; - VariableInfo vi_child = null; - if (vi._children != null) - { - foreach (VariableInfo var in vi._children) - { - if (var._name == search) - { - vi_child = var; - break; - } - } - } - vi = vi_child; - } - } while ((vi != null) && ((isArray) || (name != ""))); - - - if (name != "") // variable not found probably because it is in an expression, so return to the original name to evaluate it. - search = search + separator + name; - - string result = ""; - bool valid; - if (vi == null) - valid = evaluateExpression(search, ref result, null); - else - valid = evaluateExpression(search, ref result, vi._GDBName); - - if (vi != null) - { - if ((vi._value != result) || (!isRoot)) // if is not root means that it can be expanded... - { - vi._value = result; - if (vi._value == null || (vi._type.Contains("*") && (vi._value != "0x0"))) - { - // This is an array, struct, union, or pointer. - // Create a variable object so we can list this variable's children. - ArrayList GDBNames = new ArrayList(); - ArrayList VSNames = new ArrayList(); - bool hasVsNdK_ = false; - m_eventDispatcher.createVar(vi._name, ref hasVsNdK_); - if (hasVsNdK_) - { - GDBNames.Add("VsNdK_" + vi._name); - VSNames.Add(vi._name); - } - vi._children = new ArrayList(); - if (vi._type.Contains("struct")) - if (vi._type[vi._type.Length - 1] == '*') - vi.listChildren(m_eventDispatcher, "*", GDBNames, VSNames, hasVsNdK_, null); - else if (vi._type.Contains("[")) - vi.listChildren(m_eventDispatcher, "struct[]", GDBNames, VSNames, hasVsNdK_, null); - else - vi.listChildren(m_eventDispatcher, "struct", GDBNames, VSNames, hasVsNdK_, null); - else if (vi._type.Contains("[")) - vi.listChildren(m_eventDispatcher, "[]", GDBNames, VSNames, hasVsNdK_, null); - else if (vi._type.Contains("*")) - vi.listChildren(m_eventDispatcher, "*", GDBNames, VSNames, hasVsNdK_, null); - else - vi.listChildren(m_eventDispatcher, "", GDBNames, VSNames, hasVsNdK_, null); - m_eventDispatcher.deleteVar(vi._name, hasVsNdK_); - } - } - } - else - { - if (!valid) - vi = new VariableInfo(search, "", result, null); - else - { - string aux_exp = search.Replace(" ", ""); - string datatype; - - // Sending 2 GDB commands to get the data type of "aux_exp" because it is not known, at this moment, if "aux_exp" - // is an expression, a primitive or a compound variable. - - // Gets the parsed response for the GDB command that returns the data type of "aux_exp". - // (http://sourceware.org/gdb/onlinedocs/gdb/Symbols.html) - string firstDatatype = GDBParser.parseCommand("whatis " + aux_exp, 3); - - // Gets the parsed response for the GDB command that returns a detailed description of the type. - // (http://sourceware.org/gdb/onlinedocs/gdb/Symbols.html) - string baseDatatype = GDBParser.parseCommand("ptype " + aux_exp, 4); - - if ((baseDatatype[baseDatatype.Length - 1] == '{') && (baseDatatype[baseDatatype.Length - 2] == ' ')) - baseDatatype = baseDatatype.Remove(baseDatatype.Length - 2); - if (baseDatatype.Length < firstDatatype.Length) - { - if (firstDatatype.Contains(baseDatatype)) - { - baseDatatype = firstDatatype; - } - } - if ((baseDatatype == firstDatatype) || ((baseDatatype.Contains("::")) && (!baseDatatype.Contains("union")))) - { - baseDatatype = ""; - datatype = firstDatatype; - } - else - { - datatype = baseDatatype; - } - if (datatype[datatype.Length - 1] == '*') - if (result == "0x0") - { - vi = new VariableInfo(search, firstDatatype, result, null); - } - else - { - vi = new VariableInfo(search, firstDatatype, baseDatatype, result, m_eventDispatcher, null, null); - } - else if ((datatype.Contains("struct")) || (datatype.Contains("["))) - { - vi = new VariableInfo(search, firstDatatype, baseDatatype, null, m_eventDispatcher, null, null); - } - else - { - vi = new VariableInfo(search, firstDatatype, result, null); - } - } - } - return vi; - } - - - /// - /// Call the right VariableInfo constructor for locals and arguments. - /// - /// The name of the variable. - /// The data type of the variable. - /// The value of the variable. - /// The event dispatcher. - /// Return the VariableInfo created object. - public static VariableInfo create(string name, string type, string value, EventDispatcher dispatcher) - { - VariableInfo newVar = new VariableInfo(name, type, "", value, dispatcher, null, null); - return newVar; - } - - - /// - /// Constructor for Variable Info Object without inquiring for the variable's children. - /// - /// The name of the variable. - /// The data type of the variable. - /// The value of the variable. - /// The GDB Name of the variable. - public VariableInfo(string name, string type, string value, string GDBName) - { - _name = name; - _type = type; - _value = value; - _children = null; - _GDBName = GDBName; - } - - - /// - /// Constructor for Variable Info Object inquiring for the variable's children - /// - /// The name of the variable. - /// The data type of the variable. - /// The base type of the variable. - /// The value of the variable. - /// The event dispatcher. - /// The names of the variables used by GDB. - /// The Names of the variables used by VS. - public VariableInfo(string name, string type, string baseType, string value, EventDispatcher dispatcher, ArrayList GDBNames, ArrayList VSNames) - { - /// numChildren - The result of the createvar returns ERROR or a number from 0 to "n" where "n" is the number of children - /// of the variable. - string numChildren = ""; - - _name = name; - _type = type; - _value = value; - _children = null; - _GDBName = null; - - if (baseType != "") - type = baseType; - - if (GDBNames == null) - { - GDBNames = new ArrayList(); - VSNames = new ArrayList(); - } - - if (value == null || (type.Contains("*") && (value != "0x0"))) - { - // This is an array, struct, union, or pointer. - // Create a variable object so we can list this variable's children. - - /// Some VS variable names cannot be used by GDB. When that happens, it is added the prefix VsNdK_ to the GDB variable - /// name and it is stored in the GDBNames array. At the same time, the VS name is stored in the VSNames array using the - /// same index position. This bool variable just indicate if this prefix is used or not. - bool hasVsNdK_ = false; - - numChildren = dispatcher.createVar(_name, ref hasVsNdK_); - - if (hasVsNdK_) - { - _GDBName = "VsNdK_" + _name; - GDBNames.Add("VsNdK_" + _name); - VSNames.Add(_name); - } - - try // Catch non-numerical data - { - if (Convert.ToInt32(numChildren) > 0) // If the variable has children, evaluate them. - { - _children = new ArrayList(); - if (type.Contains("struct")) - if (type[type.Length - 1] == '*') - this.listChildren(dispatcher, "*", GDBNames, VSNames, hasVsNdK_, null); - else if (type.Contains("[")) - this.listChildren(dispatcher, "struct[]", GDBNames, VSNames, hasVsNdK_, null); - else - this.listChildren(dispatcher, "struct", GDBNames, VSNames, hasVsNdK_, null); - else if (type.Contains("[")) - this.listChildren(dispatcher, "[]", GDBNames, VSNames, hasVsNdK_, null); - else if (type.Contains("*")) - this.listChildren(dispatcher, "*", GDBNames, VSNames, hasVsNdK_, null); - else - this.listChildren(dispatcher, "", GDBNames, VSNames, hasVsNdK_, null); - } - } - catch (FormatException e) - { - - } - - dispatcher.deleteVar(_name, hasVsNdK_); - } - - if (value == null) - evaluateExpression(name, ref _value, null); - } - - - /// - /// Gets the list of children for a given variable. - /// - /// The event dispatcher. - /// The variable's parent data type. "*" means it is a pointer; "struct[]" means it is an array of - /// structures; "struct" means it is a structure; and "[]" means it is an array. - /// The names of the variables used by GDB. - /// The Names of the variables used by VS. - /// Indicate if the variable name uses or not the prefix "VsNdK_". - /// The GDB Name of the variable. - public void listChildren(EventDispatcher dispatcher, string parentType, ArrayList GDBNames, ArrayList VSNames, bool hasVsNdK_, string GDBName) - { - string childListResponse; - if (GDBName == null) - { - if (hasVsNdK_) - { - childListResponse = dispatcher.listChildren(_GDBName); - } - else - { - childListResponse = dispatcher.listChildren(_name); - if ((childListResponse == "ERROR") && (_GDBName != null)) - { - childListResponse = dispatcher.listChildren(_GDBName); - } - } - } - else - childListResponse = dispatcher.listChildren(GDBName); - - if (childListResponse != "ERROR") - { - childListResponse = (childListResponse.Substring(3)).Replace("#;;;", ""); - - string[] childList = childListResponse.Split('#'); - foreach (string childString in childList) - { - string name = null; - string type = null; - string value = null; - int numChildren = 0; - bool valid = true; - - string[] childProperties = childString.Split(';'); - - if (childProperties[0] == "") - continue; - - name = childProperties[0]; - - if (name.Contains("::")) // discard this GDB expression. - { - continue; - } - - GDBName = name; - - int end = name.Length; - if (name[end - 1] == '"') - end--; - if (((name.Length > 8) && (name.Substring(end - 8, 8) == ".private")) || - ((name.Length > 7) && (name.Substring(end - 7, 7) == ".public")) || - ((name.Length > 10) && (name.Substring(end - 10, 10) == ".protected")) || - ((name.Length > 9) && (name.Substring(end - 9, 9) == ".private.")) || - ((name.Length > 8) && (name.Substring(end - 8, 8) == ".public.")) || - ((name.Length > 11) && (name.Substring(end - 11, 11) == ".protected."))) - { - // GDB is using an intermediate representation for the variable. Inquire GDB again using this intermediate name. - int index = VSNames.IndexOf(_name); - if (index != -1) - GDBNames[index] = GDBName; - else - { - GDBNames.Add(GDBName); - VSNames.Add(_name); - } - this.listChildren(dispatcher, parentType, GDBNames, VSNames, hasVsNdK_, GDBName); - continue; - } - else - { - int dot = name.LastIndexOf("."); - if (dot != -1) - { - int index = GDBNames.IndexOf(name.Substring(0, dot)); - if (index != -1) - { - name = VSNames[index].ToString() + name.Substring(dot); - } - } - - name = name.Replace(".private", ""); - name = name.Replace(".public", ""); - name = name.Replace(".protected", ""); - name = name.Replace("..", "."); - - dot = name.LastIndexOf(".*"); - if (dot != -1) - { - name = "*(" + name.Remove(dot) + ")"; - } - - if (parentType == "*") - { - dot = name.LastIndexOf('.'); - if (dot != -1) - { - name = name.Substring(0, dot) + "->" + name.Substring(dot + 1, name.Length - (dot + 1)); - } - } - else if (parentType == "[]") - { - dot = name.LastIndexOf('.'); - name = name.Substring(0, dot) + "[" + name.Substring(dot + 1, name.Length - (dot + 1)); - name = name + "]"; - } - GDBNames.Add(GDBName); - VSNames.Add(name); - } - - if (childProperties[1] != "") - numChildren = Convert.ToInt32(childProperties[1]); - - value = childProperties[2]; - if ((value == "") || (value.Contains("{...}")) || - ((value.Length >= 2) && (value[0] == '[') && (value[value.Length - 1] == ']'))) - valid = evaluateExpression(name, ref value, GDBName); - - type = childProperties[3]; - - VariableInfo child = new VariableInfo(name, type, value, GDBName); - - if ((valid) && (numChildren > 0 && value != "0x0")) - { - child._children = new ArrayList(); - } - if (VSNames.Contains(name)) - { - int index = VSNames.IndexOf(name); - VSNames.RemoveAt(index); - GDBNames.RemoveAt(index); - } - _children.Add(child); // If VS knows that there are children, it will inquiries again if those children data - // were not filled. - } - } - } - } - - - /// - /// Represents a logical stack frame on the thread stack. - /// - /// It implements: - /// - /// IDebugStackFrame2: Represents a single stack frame in a call stack in a particular thread. - /// (http://msdn.microsoft.com/en-us/library/bb161683.aspx) - /// - /// IDebugExpressionContext: Represents a context for expression evaluation, which allows expression evaluation and watch windows. - /// (http://msdn.microsoft.com/en-ca/library/bb146178.aspx) - /// - public class AD7StackFrame : IDebugStackFrame2, IDebugExpressionContext2 - { - /// - /// The class that manages debug events for the debug engine. - /// - public static EventDispatcher m_dispatcher; - - /// - /// The AD7Engine object that represents the DE. - /// - public readonly AD7Engine m_engine; - - /// - /// Represents the thread for this stack frame. - /// - public readonly AD7Thread m_thread = null; - - /// - /// The short path file name that contains the source code of this stack frame. - /// - private string m_documentName = ""; - - /// - /// The function name associated to this stack frame. - /// - public string m_functionName = ""; - - /// - /// Represents the current position (line number) in m_documentName. - /// - private uint m_lineNum = 0; - - /// - /// Boolean value that indicates if this stack frame has an associated source code to present. - /// - private bool m_hasSource = false; - - /// - /// The current context's address. - /// - private uint m_address = 0; - - /// - /// List of variables that we want to filter from the locals window. - /// - private string[] m_variableFilter = { "__func__" }; - - /// - /// Contains the locals variables to this stack frame. - /// - public ArrayList _locals; - - /// - /// Contains the parameters used to call the method/function that originated this stack frame. - /// - public ArrayList _arguments; - - - /// - /// - /// - public VariableInfo _lastEvaluatedExpression; - - - /// - /// Search the __stackframes cache for the internal representation of the stack frame associated to the GDB frameInfo - /// information. If successful, returns the stack frame; otherwise, creates a new one and return it. - /// - /// The AD7Engine object that represents the DE. - /// Represents the thread for this stack frame. - /// Array of strings with the information provided by GDB about this stack frame. - /// Boolean value that indicates if a new object for this stack frame was created or not. - /// Returns the created/found stack frame. - public static AD7StackFrame create(AD7Engine engine, AD7Thread thread, string[] frameInfo, ref bool created) - { - created = false; - if (thread.__stackFrames != null) - { - foreach (AD7StackFrame frame in thread.__stackFrames) - { - if (frame.m_documentName != null && frame.m_functionName != null) - { - if (frame.m_documentName == frameInfo[3] && frame.m_functionName == frameInfo[2]) // frameInfo[2] = func, frameInfo[3] = file - return frame; - } - } - } - else - thread.__stackFrames = new ArrayList(); - - AD7StackFrame newFrame = new AD7StackFrame(engine, thread, frameInfo); - if (thread.__stackFrames == null) // that's weird, but sometimes VS is not initializing __stackFrames, so I added this loop to avoid other problems. - thread.__stackFrames = new ArrayList() { newFrame }; - else - thread.__stackFrames.Add(newFrame); - created = true; - return newFrame; - } - - - /// - /// Constructor. - /// - /// The AD7Engine object that represents the DE. - /// Represents the thread for this stack frame. - /// Array of strings with the information provided by GDB about this stack frame. - public AD7StackFrame(AD7Engine engine, AD7Thread thread, string[] frameInfo) - { - m_engine = engine; - m_thread = thread; - m_dispatcher = m_engine.eDispatcher; - - uint level = Convert.ToUInt32(frameInfo[0]); - string address = frameInfo[1]; - m_functionName = frameInfo[2]; - m_documentName = frameInfo[3]; - try - { - m_lineNum = Convert.ToUInt32(frameInfo[4]); - } - catch (Exception e) - { - m_lineNum = 0; - } - - _locals = new ArrayList(); - _arguments = new ArrayList(); - m_hasSource = (m_lineNum == 0) ? false : true; - ArrayList evaluatedVars = new ArrayList(); - - // Add the variable filter list to the evaluatedVars list. - // Causes named variables to be ignored. - evaluatedVars.AddRange(m_variableFilter); - - if (address.StartsWith("0x")) - address = address.Remove(0, 2); - m_address = uint.Parse(address, System.Globalization.NumberStyles.AllowHexSpecifier); - - // Query GDB for parameters and locals. - string variablesResponse = m_engine.eDispatcher.getVariablesForFrame(level, m_thread._id).Replace("#;;;", ""); - if (variablesResponse == null || variablesResponse == "ERROR" || variablesResponse == "") - return; - variablesResponse = variablesResponse.Substring(3); - - string[] variableStrings = variablesResponse.Split('#'); - - foreach (string variableString in variableStrings) - { - string name = null; - bool arg = false; - string type = null; - string value = null; - - string[] variableProperties = variableString.Split(';'); - - if (variableProperties[0] != "") - { - if (!evaluatedVars.Contains(variableProperties[0])) - { - name = variableProperties[0]; - evaluatedVars.Add(variableProperties[0]); - if (variableProperties[1] != "") - arg = true; - if (variableProperties[2] != "") - type = variableProperties[2]; - if (variableProperties[3] != "") - value = variableProperties[3]; - if (arg) - _arguments.Add(VariableInfo.create(name, type, value, m_engine.eDispatcher)); - else - _locals.Add(VariableInfo.create(name, type, value, m_engine.eDispatcher)); - } - } - } - } - - #region Non-interface methods - - - /// - /// Construct a FRAMEINFO for this stack frame with the requested information. - /// - /// A combination of flags from the FRAMEINFO_FLAGS enumeration that specifies which fields of the - /// frameInfo parameter are to be filled in. - /// A FRAMEINFO structure that is filled in with the description of the stack frame. - public void SetFrameInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, out FRAMEINFO frameInfo) - { - frameInfo = new FRAMEINFO(); - - // The debugger is asking for the formatted name of the function which is displayed in the callstack window. - // There are several optional parts to this name including the module, argument types and values, and line numbers. - // The optional information is requested by setting flags in the dwFieldSpec parameter. - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME) != 0) - { - // If there is source information, construct a string that contains the module name, function name, and optionally argument names and values. - if (m_hasSource) - { - frameInfo.m_bstrFuncName = ""; - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0) - { -// frameInfo.m_bstrFuncName = System.IO.Path.GetFileName(module.Name) + "!"; - } - - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_RETURNTYPE) != 0) - { - // Adds the return type to the m_bstrFuncName field. - //frameInfo.m_bstrFuncName += _returnType; - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LANGUAGE) != 0) - { - // Adds the language to the m_bstrFuncName field. - if (m_documentName.EndsWith(".c")) - frameInfo.m_bstrFuncName += "(C) "; - else if (m_documentName.EndsWith(".cpp") || m_documentName.EndsWith(".c++")) - frameInfo.m_bstrFuncName += "(C++) "; - } - - frameInfo.m_bstrFuncName += m_functionName; - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS) != 0) - { - // Add the arguments to the m_bstrFuncName field. - frameInfo.m_bstrFuncName += "("; - bool all = (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_ALL) != 0; - int i = 0; - foreach (VariableInfo arg in _arguments) - { - if (all || (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES) != 0) - { - frameInfo.m_bstrFuncName += arg._type + " "; - } - - if (all || (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES) != 0) - { - frameInfo.m_bstrFuncName += arg._name; - } - - if (all || (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES) != 0) - { - frameInfo.m_bstrFuncName += "=" + arg._value; - } - - if (i < _arguments.Count - 1) - { - frameInfo.m_bstrFuncName += ", "; - } - i++; - } - frameInfo.m_bstrFuncName += ")"; - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES) != 0) - { - frameInfo.m_bstrFuncName += " Line: " + m_lineNum.ToString(); - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_OFFSET) != 0) - { - // TODO: - // Adds to the m_bstrFuncName field the offset in bytes from the start of the line if FIF_FUNCNAME_LINES is specified. - // If FIF_FUNCNAME_LINES is not specified, or if line numbers are not available, adds the offset in bytes from the start of the function. - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_FORMAT) != 0) - { - // TODO: - // Formats the function name. The result is returned in the m_bstrFuncName field and no other fields are filled out. - // According to http://msdn.microsoft.com/en-us/library/bb145138.aspx, this flag "Specify the FIF_FUNCNAME_FORMAT - // flag to format the function name into a single string". This method already works on this way. - } - } - else - { - frameInfo.m_bstrFuncName = "[External Code]"; - // No source information, so only return the module name and the instruction pointer. - /* - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0) - { - frameInfo.m_bstrFuncName = EngineUtils.GetAddressDescription(module, ip); - } - else - { - frameInfo.m_bstrFuncName = EngineUtils.GetAddressDescription(null, ip); - } - */ - } - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME; - } - - // The debugger is requesting the name of the module for this stack frame. - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_MODULE) != 0) - { - frameInfo.m_bstrModule = ""; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_MODULE; - } - - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_RETURNTYPE) != 0) - { - // TODO: - // Initialize/use the m_bstrReturnType field. - frameInfo.m_bstrReturnType = ""; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_RETURNTYPE; - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS) != 0) - { - // Initialize/use the m_bstrArgs field. - frameInfo.m_bstrArgs = ""; - bool all = (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS_ALL) != 0; - int i = 0; - foreach (VariableInfo arg in _arguments) - { - if (all || (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS_TYPES) != 0) - { - frameInfo.m_bstrArgs += arg._type + " "; - } - - if (all || (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS_NAMES) != 0) - { - frameInfo.m_bstrArgs += arg._name; - } - - if (all || (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS_VALUES) != 0) - { - frameInfo.m_bstrArgs += "=" + arg._value; - } - - if (i < _arguments.Count - 1) - { - frameInfo.m_bstrArgs += ", "; - } - i++; - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS_NO_TOSTRING) != 0) - { - // TODO: - // Do not allow ToString() function evaluation or formatting when returning function arguments. - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS_NO_FUNC_EVAL) != 0) - { - // TODO: - // Specifies that function (property) evaluation should not be used when retrieving argument values. - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_ARGS_NOFORMAT) != 0) - { - // TODO: - // Specifies that the arguments are not be formatted (for example, do not add opening and closing parentheses around - // the argument list nor add a separator between arguments). - } - - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_ARGS; - } - - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_LANGUAGE) != 0) - { - // Initialize/use the m_bstrLanguage field. - if (m_documentName != null) - { - if (m_documentName.EndsWith(".c")) - frameInfo.m_bstrLanguage = "C"; - else if (m_documentName.EndsWith(".cpp") || m_documentName.EndsWith(".c++")) - frameInfo.m_bstrLanguage = "C++"; - else - frameInfo.m_bstrLanguage = ""; - } - else - frameInfo.m_bstrLanguage = ""; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_LANGUAGE; - } - - // The debugger would like a pointer to the IDebugModule2 that contains this stack frame. - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP) != 0) - { - frameInfo.m_pModule = m_engine.m_module; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP; - } - - // The debugger is requesting the range of memory addresses for this frame. - // For the sample engine, this is the contents of the frame pointer. - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_STACKRANGE) != 0) - { - // TODO: - // Initialize/use the m_addrMin and m_addrMax (stack range) fields. - - frameInfo.m_addrMin = 0; - frameInfo.m_addrMax = 0; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STACKRANGE; - } - - // The debugger is requesting the IDebugStackFrame2 value for this frame info. - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FRAME) != 0) - { - frameInfo.m_pFrame = this; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FRAME; - } - - // Does this stack frame of symbols loaded? - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO) != 0) - { - frameInfo.m_fHasDebugInfo = m_hasSource ? 1 : 0; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO; - } - - // Is this frame stale? - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_STALECODE) != 0) - { - frameInfo.m_fStaleCode = 0; - frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STALECODE; - } - - // The debug engine is to filter non-user code frames so they are not included. - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FILTER_NON_USER_CODE ) != 0) - { - } - - // Frame information should be gotten from the hosted app-domain rather than the hosting process. - if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_DESIGN_TIME_EXPR_EVAL) != 0) - { - } - - } - - - /// - /// Construct an instance of IEnumDebugPropertyInfo2 for the combined locals and parameters. - /// - /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in - /// the enumObject are to be filled in. - /// Returns the number of elements in the enumeration. - /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. - public void CreateLocalsPlusArgsProperties(enum_DEBUGPROP_INFO_FLAGS dwFields, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) - { - elementsReturned = 0; - int localsLength = 0; - - if (_locals != null) - { - localsLength = _locals.Count; - elementsReturned += (uint)localsLength; - } - - if (_arguments != null) - { - elementsReturned += (uint)_arguments.Count; - } - DEBUG_PROPERTY_INFO[] propInfo = new DEBUG_PROPERTY_INFO[elementsReturned]; - - if (_locals != null) - { - int i = 0; - foreach(VariableInfo var in _locals) - { - AD7Property property = new AD7Property(var); - propInfo[i] = property.ConstructDebugPropertyInfo(dwFields); - i++; - } - } - - if (_arguments != null) - { - int i = 0; - foreach (VariableInfo arg in _arguments) - { - AD7Property property = new AD7Property(arg); - propInfo[localsLength + i] = property.ConstructDebugPropertyInfo(dwFields); - i++; - } - } - - enumObject = new AD7PropertyInfoEnum(propInfo); - } - - - /// - /// Construct an instance of IEnumDebugPropertyInfo2 for the locals collection only. - /// - /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in - /// the enumObject are to be filled in. - /// Returns the number of elements in the enumeration. - /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. - private void CreateLocalProperties(enum_DEBUGPROP_INFO_FLAGS dwFields, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) - { - elementsReturned = (uint)_locals.Count; - DEBUG_PROPERTY_INFO[] propInfo = new DEBUG_PROPERTY_INFO[_locals.Count]; - - int i = 0; - foreach (VariableInfo var in _locals) - { - AD7Property property = new AD7Property(var); - propInfo[i] = property.ConstructDebugPropertyInfo(dwFields); - i++; - } - - enumObject = new AD7PropertyInfoEnum(propInfo); - } - - - /// - /// Construct an instance of IEnumDebugPropertyInfo2 for the parameters collection only. - /// - /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in - /// the enumObject are to be filled in. - /// Returns the number of elements in the enumeration. - /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. - private void CreateParameterProperties(enum_DEBUGPROP_INFO_FLAGS dwFields, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) - { - elementsReturned = (uint)_arguments.Count; - DEBUG_PROPERTY_INFO[] propInfo = new DEBUG_PROPERTY_INFO[_arguments.Count]; - - int i = 0; - foreach (VariableInfo arg in _arguments) - { - AD7Property property = new AD7Property(arg); - propInfo[i] = property.ConstructDebugPropertyInfo(dwFields); - i++; - } - - enumObject = new AD7PropertyInfoEnum(propInfo); - } - - #endregion - - #region IDebugStackFrame2 Members - - - /// - /// Creates an enumerator for properties associated with the stack frame, such as local variables. - /// (http://msdn.microsoft.com/en-us/library/bb145607.aspx). - /// - /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in - /// the enumerated DEBUG_PROPERTY_INFO structures are to be filled in. - /// The radix to be used in formatting any numerical information. - /// A GUID of a filter used to select which DEBUG_PROPERTY_INFO structures are to be enumerated, - /// such as guidFilterLocals. - /// Maximum time, in milliseconds, to wait before returning from this method. Use INFINITE to wait - /// indefinitely. - /// Returns the number of properties enumerated. This is the same as calling the - /// IEnumDebugPropertyInfo2::GetCount method. - /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugStackFrame2.EnumProperties(enum_DEBUGPROP_INFO_FLAGS dwFields, uint nRadix, ref Guid guidFilter, uint dwTimeout, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) - { - elementsReturned = 0; - enumObject = null; - - try - { - if (guidFilter == AD7Guids.guidFilterLocalsPlusArgs || - guidFilter == AD7Guids.guidFilterAllLocalsPlusArgs || - guidFilter == AD7Guids.guidFilterAllLocals) - { - CreateLocalsPlusArgsProperties(dwFields, out elementsReturned, out enumObject); - return VSConstants.S_OK; - } - else if (guidFilter == AD7Guids.guidFilterLocals) - { - CreateLocalProperties(dwFields, out elementsReturned, out enumObject); - return VSConstants.S_OK; - } - else if (guidFilter == AD7Guids.guidFilterArgs) - { - CreateParameterProperties(dwFields, out elementsReturned, out enumObject); - return VSConstants.S_OK; - } - else - { - return VSConstants.E_NOTIMPL; - } - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Gets the code context for this stack frame. The code context represents the current instruction pointer in this stack frame. - /// (http://msdn.microsoft.com/en-us/library/bb147046.aspx) - /// - /// Returns an IDebugCodeContext2 object that represents the current instruction pointer in this stack frame. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugStackFrame2.GetCodeContext(out IDebugCodeContext2 memoryAddress) - { - memoryAddress = null; - try - { - memoryAddress = new AD7MemoryAddress(m_engine, m_address); - return VSConstants.S_OK; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Gets a description of the properties associated with a stack frame. - /// (http://msdn.microsoft.com/en-us/library/bb144920.aspx) - /// - /// Returns an IDebugProperty2 object that describes the properties of this stack frame. - /// VSConstants.S_OK. - int IDebugStackFrame2.GetDebugProperty(out IDebugProperty2 property) - { - property = new AD7Property(this); - return VSConstants.S_OK; - } - - - /// - /// Gets the document context for this stack frame. The debugger will call this when the current stack frame is changed and - /// will use it to open the correct source document for this stack frame. (http://msdn.microsoft.com/en-us/library/bb146338.aspx) - /// - /// Returns an IDebugDocumentContext2 object that represents the current position in a source - /// document. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugStackFrame2.GetDocumentContext(out IDebugDocumentContext2 docContext) - { - this.m_engine.cleanEvaluatedThreads(); - docContext = null; - - try - { - if (m_hasSource) - { - // Assume all lines begin and end at the beginning of the line. - TEXT_POSITION begTp = new TEXT_POSITION(); - begTp.dwColumn = 0; - begTp.dwLine = m_lineNum - 1; - TEXT_POSITION endTp = new TEXT_POSITION(); - endTp.dwColumn = 0; - endTp.dwLine = m_lineNum - 1; - - docContext = new AD7DocumentContext(m_documentName, begTp, endTp, null); - return VSConstants.S_OK; - } - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - - return VSConstants.S_FALSE; - } - - - /// - /// Gets an evaluation context for expression evaluation within the current context of a stack frame and thread. - /// Generally, an expression evaluation context can be thought of as a scope for performing expression evaluation. - /// Call the IDebugExpressionContext2::ParseText method to parse an expression and then call the resulting - /// IDebugExpression2::EvaluateSync or IDebugExpression2::EvaluateAsync methods to evaluate the parsed expression. - /// (http://msdn.microsoft.com/en-us/library/bb161269.aspx) - /// - /// Returns an IDebugExpressionContext2 object that represents a context for expression evaluation. - /// VSConstants.S_OK. - int IDebugStackFrame2.GetExpressionContext(out IDebugExpressionContext2 ppExprCxt) - { - ppExprCxt = (IDebugExpressionContext2)this; - return VSConstants.S_OK; - } - - - /// - /// Gets a description of the stack frame. (http://msdn.microsoft.com/en-us/library/bb145146.aspx) - /// - /// A combination of flags from the FRAMEINFO_FLAGS enumeration that specifies which fields of the - /// pFrameInfo parameter are to be filled in. - /// The radix to be used in formatting any numerical information. - /// A FRAMEINFO structure that is filled in with the description of the stack frame. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugStackFrame2.GetInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, uint nRadix, FRAMEINFO[] pFrameInfo) - { - try - { - SetFrameInfo(dwFieldSpec, out pFrameInfo[0]); - - int frame = 0; - if (this.m_thread.__stackFrames != null) - { - foreach (AD7StackFrame sf in this.m_thread.__stackFrames) - { - if (sf.m_functionName == this.m_functionName) - break; - frame++; - } - } - - if (this.m_thread._id != this.m_engine.currentThread()._id) - this.m_engine.eDispatcher.selectThread(this.m_thread._id); - - // Waits for the parsed response for the GDB/MI command that changes the selected frame. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) - GDBParser.parseCommand("-stack-select-frame " + frame, 5); - - if (this.m_thread._id != this.m_engine.currentThread()._id) - this.m_engine.eDispatcher.selectThread(this.m_engine.currentThread()._id); - - this.m_engine.cleanEvaluatedThreads(); - - return VSConstants.S_OK; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Gets the language associated with this stack frame. (http://msdn.microsoft.com/en-us/library/bb145096.aspx) - /// - /// Returns the name of the language that implements the method associated with this stack frame. - /// Returns the GUID of the language. - /// VSConstants.S_OK. - int IDebugStackFrame2.GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) - { - if (m_documentName.EndsWith(".c")) - { - pbstrLanguage = "C"; - pguidLanguage = AD7Guids.guidLanguageCpp; - } - else if (m_documentName.EndsWith(".cpp") || m_documentName.EndsWith(".c++")) - { - pbstrLanguage = "C++"; - pguidLanguage = AD7Guids.guidLanguageCpp; - } - - return VSConstants.S_OK; - } - - - /// - /// Gets the name of the stack frame. The name of a stack frame is typically the name of the method being executed. - /// Not implemented. (http://msdn.microsoft.com/en-us/library/bb145002.aspx) - /// - /// Returns the name of the stack frame. - /// Not implemented. - int IDebugStackFrame2.GetName(out string name) - { - name = null; - - return VSConstants.E_NOTIMPL; - } - - - /// - /// Gets a machine-dependent representation of the range of physical addresses associated with a stack frame. - /// Not implemented. (http://msdn.microsoft.com/en-us/library/bb145597.aspx) - /// - /// Returns the lowest physical address associated with this stack frame. - /// Returns the highest physical address associated with this stack frame. - /// Not implemented. - int IDebugStackFrame2.GetPhysicalStackRange(out ulong addrMin, out ulong addrMax) - { - addrMin = 0; - addrMax = 0; - - return VSConstants.E_NOTIMPL; - } - - - /// - /// Gets the thread associated with a stack frame. (http://msdn.microsoft.com/en-us/library/bb161776.aspx) - /// - /// Returns an IDebugThread2 object that represents the thread. - /// VSConstants.S_OK. - int IDebugStackFrame2.GetThread(out IDebugThread2 thread) - { - thread = m_thread; - return VSConstants.S_OK; - } - - #endregion - - #region IDebugExpressionContext2 Members - - - /// - /// Retrieves the name of the evaluation context. The name is the description of this evaluation context. It is typically - /// something that can be parsed by an expression evaluator that refers to this exact evaluation context. For example, in - /// C++ the name is as follows: "{ function-name, source-file-name, module-file-name }" - /// Not implemented. (http://msdn.microsoft.com/en-ca/library/bb161724.aspx) - /// - /// Returns the name of the evaluation context. - /// Not implemented. - int IDebugExpressionContext2.GetName(out string pbstrName) - { - throw new NotImplementedException(); - } - - - /// - /// Parses a text-based expression for evaluation. (http://msdn.microsoft.com/en-ca/library/bb162304.aspx). - /// GDB will parse and evaluate the expression, returning the result or an error in the expression. So, the only task for this - /// method is to create the IDebugExpression2 object that will be sent indirectly to the methods responsible for the evaluation. - /// - /// The expression to be parsed. - /// A combination of flags from the PARSEFLAGS enumeration that controls parsing. - /// The radix to be used in parsing any numerical information in pszCode. - /// Returns the IDebugExpression2 object that represents the parsed expression, which is ready for - /// binding and evaluation. - /// Returns the error message if the expression contains an error. - /// Returns the character index of the error in pszCode if the expression contains an error. - /// VSConstants.S_OK. - int IDebugExpressionContext2.ParseText(string pszCode, - enum_PARSEFLAGS dwFlags, - uint nRadix, - out IDebugExpression2 ppExpr, - out string pbstrError, - out uint pichError) - { - pbstrError = ""; - pichError = 0; - ppExpr = null; - - ppExpr = new AD7Expression(pszCode, this, m_engine.eDispatcher); - return VSConstants.S_OK; - } - - #endregion - } -} - diff --git a/src/VSNDK.DebugEngine/AD7.Impl/AD7Thread.cs b/src/VSNDK.DebugEngine/AD7.Impl/AD7Thread.cs deleted file mode 100644 index c7ee3025..00000000 --- a/src/VSNDK.DebugEngine/AD7.Impl/AD7Thread.cs +++ /dev/null @@ -1,752 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; -using VSNDK.Parser; -using System.Runtime.InteropServices; -using System.Collections; - -namespace VSNDK.DebugEngine -{ - - /// - /// Thread's category, from http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/807e26cc-4f3f-4e90-a9a8-b550d484b8c1 - /// - enum enum_THREADCATEGORY - { - THREADCATEGORY_Worker = 0, - THREADCATEGORY_UI = (THREADCATEGORY_Worker + 1), - THREADCATEGORY_Main = (THREADCATEGORY_UI + 1), - THREADCATEGORY_RPC = (THREADCATEGORY_Main + 1), - THREADCATEGORY_Unknown = (THREADCATEGORY_RPC + 1) - }; - - - /// - /// This class represents a thread running in a program and it implements: - /// - /// IDebugThread2: (http://msdn.microsoft.com/en-ca/library/bb145332.aspx) - /// - /// IDebugThread100: (http://msdn.microsoft.com/en-us/library/ff471152.aspx) - /// - public class AD7Thread : IDebugThread2, IDebugThread100 - { - /// - /// The AD7Engine object that represents the DE. - /// - public AD7Engine _engine = null; - - /// - /// Thread's name. - /// - public string _threadDisplayName; - - /// - /// The suspend count determines how many times the IDebugThread2::Suspend method has been called so far. - /// - private uint _suspendCount; - - /// - /// Full long path file name. - /// - public string _filename; - - /// - /// Line number. - /// - public uint _line; - - /// - /// Contains flags that specifies the information that were already verified about this thread's stack frame object. - /// Used to avoid reevaluating stack frames that were already evaluated. - /// - public int _alreadyEvaluated = 0; - - /// - /// Contains the stack frames for this thread - /// - public ArrayList __stackFrames = null; - - /// - /// A FRAMEINFO structure that is filled in with the description of the previous stack frame that works as a cache, to avoid - /// reevaluate the stack frame again. - /// - public FRAMEINFO[] previousFrameInfoArray = new FRAMEINFO[0]; - - /// - /// Thread's ID. - /// - public string _id; - - /// - /// Thread's state. - /// - public string _state; - - /// - /// Process' ID + Thread's ID. - /// - public string _targetID; - - /// - /// Thread's priority. - /// - public string _priority; - - - /// - /// Constructor. - /// - /// The AD7Engine object that represents the DE. - /// Thread's ID. - /// Process' ID + Thread's ID. - /// Thread's state. - /// Thread's priority. - /// Thread's name. - /// Full short path file name. - /// Line number. - public AD7Thread(AD7Engine aEngine, string id, string targetID, string state, string priority, string name, string fullname, string line)//, DebuggedThread debuggedThread) - { - _engine = aEngine; - _suspendCount = 0; - if (id == "1") - _threadDisplayName = "Main Thread"; - else - _threadDisplayName = (name != "") ? name : ""; - - if (fullname.Contains("~")) - { - // Need to lengthen the path used by Visual Studio. - StringBuilder longPathName = new StringBuilder(1024); - GetLongPathName(fullname, longPathName, longPathName.Capacity); - _filename = longPathName.ToString(); - } - else - _filename = fullname; - - try - { - _line = Convert.ToUInt32(line); - } - catch - { - _line = 0; - } - - _id = id; - _state = state; - _targetID = targetID; - _priority = priority; - } - - - /// GDB works with short path names only, which requires converting the path names to/from long ones. This function - /// returns the long path name for a given short one. - /// Short path name. - /// Returns this long path name. - /// Lenght of this long path name. - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern int GetLongPathName( - [MarshalAs(UnmanagedType.LPTStr)] - string path, - [MarshalAs(UnmanagedType.LPTStr)] - StringBuilder longPath, - int longPathLength - ); - - - /// - /// Called by EventDipatcher to set the current location during break mode. - /// - /// Full short path file name. - /// Line number. - public void setCurrentLocation(string filename, uint line) - { - if (filename.Contains("~")) - { - // Need to lengthen the path used by Visual Studio. - StringBuilder longPathName = new StringBuilder(1024); - GetLongPathName(filename, longPathName, longPathName.Capacity); - _filename = longPathName.ToString(); - } - else - _filename = filename; - _line = line; - } - - - /// - /// Gets the function name. - /// - /// If successful, returns the function name; otherwise, returns "". - public string getFunctionName() - { - string func = ""; - - if ((this._id != "") && (this._id != this._engine.currentThread()._id)) - _engine.eDispatcher.selectThread(this._id); - - string stackResponse = _engine.eDispatcher.getStackFrames().Replace("#;;;;", ""); - - if (stackResponse != "") - { - string[] frameStrings = stackResponse.Split('#'); - - // Query the stack depth without inquiring GDB. - int numStackFrames = frameStrings.Length; - - if (numStackFrames > 30) // limiting the amount of stackFrames to avoid VS crashing. - numStackFrames = 30; - - for (int i = 0; i < numStackFrames; i++) - { - string[] frameInfo = frameStrings[i].Split(';'); - if (frameInfo.Length >= 2) - { - if ((frameInfo[2] != "") && (frameInfo[2] != "??") && (!frameInfo[2].Contains("object."))) - { - func = frameInfo[2]; - break; - } - } - } - - if ((this._id != "") && (this._id != this._engine.currentThread()._id)) - _engine.eDispatcher.selectThread(this._engine.currentThread()._id); - } - - return func; - } - - - /// - /// Determines whether the next statement can be set to the given stack frame and code context. Not implemented. - /// (http://msdn.microsoft.com/en-ca/library/bb146582.aspx) - /// - /// Reserved for future use; set to a null value. If this is a null value, use the current - /// stack frame. - /// An IDebugCodeContext2 object that describes the code location about to be executed and - /// its context. - /// VSConstants.S_OK. - int IDebugThread2.CanSetNextStatement(IDebugStackFrame2 pStackFrame, IDebugCodeContext2 pCodeContext) - { - return VSConstants.S_OK; - } - - - /// - /// Retrieves a list of the stack frames for this thread. (http://msdn.microsoft.com/en-ca/library/bb145138.aspx) - /// - /// A combination of flags from the FRAMEINFO_FLAGS enumeration that specifies which fields of the - /// FRAMEINFO structures are to be filled out. - /// Radix used in formatting numerical information in the enumerator. - /// Returns an IEnumDebugFrameInfo2 object that contains a list of FRAMEINFO structures describing the - /// stack frame. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugThread2.EnumFrameInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, uint nRadix, out IEnumDebugFrameInfo2 ppEnum) - { - if (this._id == "") - { - ppEnum = null; - return Constants.S_FALSE; - } - - if (this._engine.evaluatedTheseFlags(this._id, dwFieldSpec)) - { - ppEnum = new AD7FrameInfoEnum(previousFrameInfoArray); - return Constants.S_OK; - } - - // Ask for general stack information. - if ((this._id != "") && (this._id != this._engine.currentThread()._id)) - _engine.eDispatcher.selectThread(this._id); - - string stackResponse = _engine.eDispatcher.getStackFrames().Replace("#;;;;", ""); - if (stackResponse == "") - { - ppEnum = null; - return Constants.S_FALSE; - } - string[] frameStrings = stackResponse.Split('#'); - - // Query the stack depth without inquiring GDB. - int numStackFrames = frameStrings.Length; - - if (numStackFrames > 30) // limiting the amount of stackFrames to avoid VS crashing. - numStackFrames = 30; - - ppEnum = null; - try - { - bool created = false; - FRAMEINFO[] frameInfoArray = new FRAMEINFO[numStackFrames]; - for (int i = 0; i < numStackFrames; i++) - { - string[] frameInfo = frameStrings[i].Split(';'); - if (frameInfo.Length >= 3) - { - if (frameInfo[3].Contains("~")) - { - // Need to lengthen the path used by Visual Studio. - StringBuilder longPathName = new StringBuilder(1024); - GetLongPathName(frameInfo[3], longPathName, longPathName.Capacity); - frameInfo[3] = longPathName.ToString(); - } - AD7StackFrame frame = AD7StackFrame.create(_engine, this, frameInfo, ref created); - if (frame.m_thread.__stackFrames == null) // that's weird, but sometimes VS is not initializing __stackFrames, so I added this loop to avoid other problems. - { - while (frame.m_thread.__stackFrames == null) - frame.m_thread.__stackFrames = new ArrayList() { frame }; - } - frame.SetFrameInfo(dwFieldSpec, out frameInfoArray[i]); - } - } - if ((previousFrameInfoArray.Length != frameInfoArray.Length) || (created == true)) - { - previousFrameInfoArray = frameInfoArray; - ppEnum = new AD7FrameInfoEnum(frameInfoArray); - } - else - { - bool isEqual = true; - for (int i = 0; i < frameInfoArray.Length; i++) - { - if (frameInfoArray[i].m_bstrFuncName != previousFrameInfoArray[i].m_bstrFuncName) - { - isEqual = false; - break; - } - if (frameInfoArray[i].m_dwValidFields != previousFrameInfoArray[i].m_dwValidFields) - { - isEqual = false; - break; - } - if (frameInfoArray[i].m_bstrLanguage != previousFrameInfoArray[i].m_bstrLanguage) - { - isEqual = false; - break; - } - } - if (!isEqual) - { - previousFrameInfoArray = frameInfoArray; - ppEnum = new AD7FrameInfoEnum(frameInfoArray); - } - else - { - ppEnum = new AD7FrameInfoEnum(previousFrameInfoArray); - } - } - - if ((this._id != "") && (this._id != this._engine.currentThread()._id)) - _engine.eDispatcher.selectThread(this._engine.currentThread()._id); - - return Constants.S_OK; - } - catch (ComponentException e) - { - if ((this._id != "") && (this._id != this._engine.currentThread()._id)) - _engine.eDispatcher.selectThread(this._engine.currentThread()._id); - return e.HResult; - } - catch (Exception e) - { - if ((this._id != "") && (this._id != this._engine.currentThread()._id)) - _engine.eDispatcher.selectThread(this._engine.currentThread()._id); - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Gets the logical thread associated with this physical thread. Not implemented. - /// (http://msdn.microsoft.com/en-ca/library/bb161676.aspx) - /// - /// An IDebugStackFrame2 object that represents the stack frame. - /// Returns an IDebugLogicalThread2 interface that represents the associated logical - /// thread. A debug engine implementation should set this to a null value. - /// VSConstants.S_OK. - int IDebugThread2.GetLogicalThread(IDebugStackFrame2 pStackFrame, out IDebugLogicalThread2 ppLogicalThread) - { - ppLogicalThread = null; - return VSConstants.S_OK; - } - - - /// - /// Gets the name of a thread. (http://msdn.microsoft.com/en-ca/library/bb162273.aspx) - /// - /// Returns the name of the thread. - /// VSConstants.S_OK. - int IDebugThread2.GetName(out string pbstrName) - { - pbstrName = _threadDisplayName; - return VSConstants.S_OK; - } - - - /// - /// Gets the program in which a thread is running. (http://msdn.microsoft.com/en-ca/library/bb147002.aspx) - /// - /// Returns an IDebugProgram2 object that represents the program this thread is running in. - /// VSConstants.S_OK. - int IDebugThread2.GetProgram(out IDebugProgram2 ppProgram) - { - ppProgram = _engine.m_program; - return VSConstants.S_OK; - } - - - /// - /// Gets the system thread identifier. (http://msdn.microsoft.com/en-ca/library/bb161964.aspx) - /// - /// Returns the system thread identifier. - /// VSConstants.S_OK. - int IDebugThread2.GetThreadId(out uint pdwThreadId) - { - try - { - pdwThreadId = Convert.ToUInt32(this._id); - } - catch - { - pdwThreadId = 0; - } - return VSConstants.S_OK; - } - - - /// - /// Gets the properties that describe this thread. (http://msdn.microsoft.com/en-ca/library/bb145602.aspx) - /// - /// A combination of flags from the THREADPROPERTY_FIELDS enumeration that determines which fields of - /// ptp are to be filled in. - /// A THREADPROPERTIES structure that that is filled in with the properties of the thread. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugThread2.GetThreadProperties(enum_THREADPROPERTY_FIELDS dwFields, THREADPROPERTIES[] ptp) - { - try - { - if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_ID) != 0) - { - try - { - ptp[0].dwThreadId = Convert.ToUInt32(this._id); - } - catch - { - ptp[0].dwThreadId = 0; - } - ptp[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_ID; - } - if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT) != 0) - { - // VSNDK debug engine doesn't support suspending threads - ptp[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT; - } - if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_STATE) != 0) - { - if (this._state == "running") - ptp[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_RUNNING; - else - ptp[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_STOPPED; - ptp[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_STATE; - } - if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_PRIORITY) != 0) - { - ptp[0].bstrPriority = "Normal"; - ptp[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_PRIORITY; - } - if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_NAME) != 0) - { - ptp[0].bstrName = _threadDisplayName; - ptp[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_NAME; - } - if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_LOCATION) != 0) - { - ptp[0].bstrLocation = ""; - if (__stackFrames != null) - { - foreach (AD7StackFrame frame in __stackFrames) - { - if (frame.m_functionName != "") - { - ptp[0].bstrLocation = frame.m_functionName; - break; - } - } - } - if (ptp[0].bstrLocation == "") - ptp[0].bstrLocation = "[External Code]"; - - ptp[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_LOCATION; - } - - return Constants.S_OK; - } - catch (ComponentException e) - { - return e.HResult; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - - /// - /// Resumes execution of a thread. (http://msdn.microsoft.com/en-ca/library/bb145813.aspx) - /// - /// Returns the suspend count after the resume operation. - /// VSConstants.S_OK. - int IDebugThread2.Resume(out uint pdwSuspendCount) - { - _suspendCount--; - pdwSuspendCount = _suspendCount; - if (_suspendCount == 0) - { - // Send GDB command to resume execution of thread - } - return VSConstants.S_OK; - } - - - /// - /// Sets the next statement to the given stack frame and code context. Not implemented. - /// (http://msdn.microsoft.com/en-ca/library/bb160944.aspx) - /// - /// Reserved for future use; set to a null value. - /// An IDebugCodeContext2 object that describes the code location about to be executed and - /// its context. - /// VSConstants.S_OK. - int IDebugThread2.SetNextStatement(IDebugStackFrame2 pStackFrame, IDebugCodeContext2 pCodeContext) - { - return VSConstants.S_OK; - } - - - /// - /// Sets the name of the thread. (http://msdn.microsoft.com/en-ca/library/bb162322.aspx) - /// - /// The name of the thread. - /// VSConstants.S_OK. - int IDebugThread2.SetThreadName(string pszName) - { - _threadDisplayName = pszName; - return VSConstants.S_OK; - } - - - /// - /// Suspends a thread. (http://msdn.microsoft.com/en-us/library/bb145297.aspx) - /// - /// Returns the suspend count after the suspend operation. - /// VSConstants.S_OK - int IDebugThread2.Suspend(out uint pdwSuspendCount) - { - _suspendCount++; - pdwSuspendCount = _suspendCount; - return VSConstants.S_OK; - } - - #region IDebugThread100 Members - - - /// - /// Sets the name of the thread. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.setthreaddisplayname.aspx) - /// - /// The name of the thread. - /// VSConstants.S_OK. - int IDebugThread100.SetThreadDisplayName(string name) - { - this._threadDisplayName = name; - return Constants.S_OK; - } - - - /// - /// Gets the name of a thread. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.getthreaddisplayname.aspx) - /// - /// Returns the name of the thread. - /// VSConstants.S_OK. - int IDebugThread100.GetThreadDisplayName(out string name) - { - name = this._threadDisplayName; - return Constants.S_OK; - } - - - /// - /// Returns whether this thread can be used to do function/property evaluation. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.candofunceval.aspx) - /// - /// VSConstants.S_FALSE. - int IDebugThread100.CanDoFuncEval() - { - return Constants.S_FALSE; - } - - - /// - /// Set flags. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.setflags.aspx) - /// - /// Flags. - /// VSConstants.E_NOTIMPL. - int IDebugThread100.SetFlags(uint flags) - { - // Not necessary to implement in the debug engine. Instead it is implemented in the SDM. - return Constants.E_NOTIMPL; - } - - - /// - /// Get flags. Not implemented. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.getflags.aspx) - /// - /// Flags. - /// VSConstants.E_NOTIMPL. - int IDebugThread100.GetFlags(out uint flags) - { - // Not necessary to implement in the debug engine. Instead it is implemented in the SDM. - flags = 0; - return Constants.E_NOTIMPL; - } - - - /// - /// Gets the properties that describe this thread. - /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.getthreadproperties100.aspx) - /// - /// A combination of flags from the THREADPROPERTIES100 enumeration that determines which fields of - /// ptp are to be filled in. - /// A THREADPROPERTIES100 structure that that is filled in with the properties of the thread. - /// If successful, returns S_OK; otherwise, returns an error code. - int IDebugThread100.GetThreadProperties100(uint dwFields, THREADPROPERTIES100[] ptp) - { - try - { - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_ID) != 0) - { - try - { - ptp[0].dwThreadId = Convert.ToUInt32(this._id); - } - catch - { - ptp[0].dwThreadId = 0; - } - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_ID; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_SUSPENDCOUNT) != 0) - { - // VSNDK debug engine doesn't support suspending threads - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_SUSPENDCOUNT; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_STATE) != 0) - { - if (this._state == "running") - ptp[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_RUNNING; - else - ptp[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_STOPPED; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_STATE; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY) != 0) - { - ptp[0].bstrPriority = "Normal"; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_NAME) != 0) - { - ptp[0].bstrName = _threadDisplayName; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_NAME; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME) != 0) - { - // Thread display name is being requested - ptp[0].bstrDisplayName = _threadDisplayName; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME; - - // Give this display name a higher priority than the default (0) - // so that it will actually be displayed - ptp[0].DisplayNamePriority = 10; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME_PRIORITY; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_LOCATION) != 0) - { - ptp[0].bstrLocation = ""; - if (__stackFrames != null) - { - foreach (AD7StackFrame frame in __stackFrames) - { - if ((frame.m_functionName != "") && (frame.m_functionName != "??")) - { - ptp[0].bstrLocation = frame.m_functionName; - break; - } - } - } - else - ptp[0].bstrLocation = getFunctionName(); - - if (ptp[0].bstrLocation == "") - ptp[0].bstrLocation = "[External Code]"; - - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_LOCATION; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_CATEGORY) != 0) - { - if (this._id == "1") - ptp[0].dwThreadCategory = (uint)enum_THREADCATEGORY.THREADCATEGORY_Main; - else - ptp[0].dwThreadCategory = (uint)enum_THREADCATEGORY.THREADCATEGORY_Worker; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_CATEGORY; - } - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_AFFINITY) != 0) - { - // Thread cpu affinity is being requested - ptp[0].AffinityMask = 0; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_AFFINITY; - } - - if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY_ID) != 0) - { - // Thread display name is being requested - ptp[0].priorityId = 0; - ptp[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY_ID; - } - return Constants.S_OK; - } - catch (ComponentException e) - { - return e.HResult; - } - catch (Exception e) - { - return EngineUtils.UnexpectedException(e); - } - } - - #endregion - } -} diff --git a/src/VSNDK.DebugEngine/Engine.Impl/BreakpointManager.cs b/src/VSNDK.DebugEngine/Engine.Impl/BreakpointManager.cs deleted file mode 100644 index bd69b948..00000000 --- a/src/VSNDK.DebugEngine/Engine.Impl/BreakpointManager.cs +++ /dev/null @@ -1,163 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using Microsoft.VisualStudio.Debugger.Interop; -using VSNDK.Parser; - -namespace VSNDK.DebugEngine -{ - /// - /// This class manages breakpoints for the engine. - /// - public class BreakpointManager - { - - /// - /// The AD7Engine object that represents the DE. - /// - private AD7Engine m_engine; - - /// - /// List of pending breakpoints. - /// - private List m_pendingBreakpoints; - - /// - /// List of active breakpoints. - /// - private List m_activeBPs; - - - /// - /// Breakpoint manager constructor. - /// - /// Associated Debug Engine. - public BreakpointManager(AD7Engine engine) - { - m_engine = engine; - m_pendingBreakpoints = new System.Collections.Generic.List(); - m_activeBPs = new System.Collections.Generic.List(); - } - - - /// - /// A helper method used to construct a new pending breakpoint. - /// - /// An IDebugBreakpointRequest2 object that describes the pending breakpoint to create. - /// Returns an IDebugPendingBreakpoint2 object that represents the pending breakpoint. - public void CreatePendingBreakpoint(IDebugBreakpointRequest2 pBPRequest, out IDebugPendingBreakpoint2 ppPendingBP) - { - AD7PendingBreakpoint pendingBreakpoint = new AD7PendingBreakpoint(pBPRequest, m_engine, this); - ppPendingBP = (IDebugPendingBreakpoint2)pendingBreakpoint; - m_pendingBreakpoints.Add(pendingBreakpoint); - } - - - /// - /// Return the active bound breakpoint matching the given GDB ID. - /// - /// Breakpoint ID in GDB. - /// If successful, returns the active bound breakpoint; otherwise, returns null. - public AD7BoundBreakpoint getBoundBreakpointForGDBID(uint GDB_ID) - { - foreach (AD7BoundBreakpoint bbp in m_activeBPs) - { - if ((bbp != null) && (bbp.GDB_ID == GDB_ID)) - { - return bbp; - } - } - return null; - } - - - /// - /// Called from the engine's detach method to remove the debugger's breakpoint instructions. - /// - public void ClearBoundBreakpoints() - { - foreach (AD7PendingBreakpoint pendingBreakpoint in m_pendingBreakpoints) - { - pendingBreakpoint.ClearBoundBreakpoints(); - } - } - - /// - /// Creates an entry and remotely enables the breakpoint in the debug stub. - /// - /// The bound breakpoint to add. - /// Breakpoint ID Number. - public int RemoteAdd(AD7BoundBreakpoint aBBP) - { - // Call GDB to set a breakpoint based on filename and line no. in aBBP - uint GDB_ID = 0; - uint GDB_LinePos = 0; - string GDB_Filename = ""; - string GDB_address = ""; - bool ret = false; - - if (aBBP.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) - { - ret = m_engine.eDispatcher.setBreakpoint(aBBP.m_filename, aBBP.m_line, out GDB_ID, out GDB_LinePos, out GDB_Filename, out GDB_address); - } - else if (aBBP.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) - { - ret = m_engine.eDispatcher.setBreakpoint(aBBP.m_func, out GDB_ID, out GDB_LinePos, out GDB_Filename, out GDB_address); - } - - if (ret) - { - m_activeBPs.Add(aBBP); - - aBBP.GDB_ID = GDB_ID; - aBBP.GDB_FileName = GDB_Filename; - aBBP.GDB_LinePos = GDB_LinePos; - aBBP.GDB_Address = GDB_address; - } - return (int)GDB_ID; - } - - /// - /// Enable bound breakpoint. - /// - /// The Bound breakpoint to enable. - public void RemoteEnable(AD7BoundBreakpoint aBBP) - { - m_engine.eDispatcher.enableBreakpoint(aBBP.GDB_ID, true); - } - - - /// - /// Disable bound breakpoint. - /// - /// The Bound breakpoint to disable. - public void RemoteDisable(AD7BoundBreakpoint aBBP) - { - m_engine.eDispatcher.enableBreakpoint(aBBP.GDB_ID, false); - } - - - /// - /// Remove the associated bound breakpoint. - /// - /// The breakpoint to remove. - public void RemoteDelete(AD7BoundBreakpoint aBBP) - { - m_activeBPs.Remove(aBBP); - m_engine.eDispatcher.deleteBreakpoint(aBBP.GDB_ID); - } - } -} diff --git a/src/VSNDK.DebugEngine/Engine.Impl/EngineCallback.cs b/src/VSNDK.DebugEngine/Engine.Impl/EngineCallback.cs deleted file mode 100644 index 9177e65b..00000000 --- a/src/VSNDK.DebugEngine/Engine.Impl/EngineCallback.cs +++ /dev/null @@ -1,235 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; -using System.Collections.ObjectModel; - -namespace VSNDK.DebugEngine -{ - /// - /// Used to send events to the debugger. Some examples of these events are thread create, exception thrown, module load. - /// - public class EngineCallback - { - - /// - /// The IDebugEventCallback2 object that receives debugger events. - /// - readonly IDebugEventCallback2 m_ad7Callback; - - /// - /// The AD7Engine object that represents the DE. - /// - readonly AD7Engine m_engine; - - - /// - /// Constructor. - /// - /// The AD7Engine object that represents the DE. - /// The IDebugEventCallback2 object that receives debugger events. - public EngineCallback(AD7Engine engine, IDebugEventCallback2 ad7Callback) - { - m_ad7Callback = ad7Callback; - m_engine = engine; - } - - - /// - /// Send events to the debugger. - /// - /// Event object to be sent to the debugger. - /// ID of the event. - /// A program that is running in a process. - /// A thread running in a program. - public void Send(IDebugEvent2 eventObject, string iidEvent, IDebugProgram2 program, IDebugThread2 thread) - { - uint attributes; - Guid riidEvent = new Guid(iidEvent); - - EngineUtils.RequireOk(eventObject.GetAttributes(out attributes)); - - if ((thread == null) && (m_engine != null) && (m_engine.thread != null) && (program != null) && (eventObject != null) && (riidEvent != null) && (attributes != null)) - { - if (m_engine._currentThreadIndex != -1) - { - EngineUtils.RequireOk(m_ad7Callback.Event(m_engine, null, program, m_engine.thread[m_engine._currentThreadIndex], eventObject, ref riidEvent, attributes)); - } - else - { - if (m_engine.thread != null) - EngineUtils.RequireOk(m_ad7Callback.Event(m_engine, null, program, m_engine.thread[0], eventObject, ref riidEvent, attributes)); - else - EngineUtils.RequireOk(m_ad7Callback.Event(m_engine, null, program, null, eventObject, ref riidEvent, attributes)); - } - } - else - EngineUtils.RequireOk(m_ad7Callback.Event(m_engine, null, program, thread, eventObject, ref riidEvent, attributes)); - } - - - /// - /// Call the method that will send the event to the debugger with all the arguments. - /// - /// Event object to be sent to the debugger. - /// ID of the event. - /// A thread running in a program. - public void Send(IDebugEvent2 eventObject, string iidEvent, IDebugThread2 thread) - { - Send(eventObject, iidEvent, m_engine, thread); - } - - - /// - /// IDebugErrorEvent2 is used to report error messages to the user when something goes wrong in the debug engine. - /// The VSNDK debug engine doesn't take advantage of this. Not implemented. - /// - /// - public void OnError(int hrErr) - { - } - - - /// - /// The VSNDK debug engine does not support binding breakpoints as modules load since the primary exe is the only module - /// symbols are loaded for. A production debugger will need to bind breakpoints when a new module is loaded. - /// - /// A module loaded in the debugged process. - public void OnModuleLoad(AD7Module debuggedModule) - { - // AD7Module ad7Module = new AD7Module(debuggedModule); - AD7ModuleLoadEvent eventObject = new AD7ModuleLoadEvent(debuggedModule, true /* this is a module load */); - - // debuggedModule.Client = ad7Module; - - Send(eventObject, AD7ModuleLoadEvent.IID, null); - } - - - /// - /// Send to the session debug manager (SDM) an event to output a string. - /// Not used. - /// - /// The output string. - public void OnOutputString(string outputString) - { - AD7OutputDebugStringEvent eventObject = new AD7OutputDebugStringEvent(outputString); - - Send(eventObject, AD7OutputDebugStringEvent.IID, null); - } - - - /// - /// Send an event to SDM with the breakpoint that was hit. - /// - /// The thread running in a program. - /// List of bound breakpoints. At this moment, this list has only one element. - public void OnBreakpoint(AD7Thread thread, IList clients) - { - IDebugBoundBreakpoint2[] boundBreakpoints = new IDebugBoundBreakpoint2[clients.Count]; - - int i = 0; - foreach (object objCurrentBreakpoint in clients) - { - boundBreakpoints[i] = (IDebugBoundBreakpoint2)objCurrentBreakpoint; - i++; - } - - AD7BoundBreakpointsEnum boundBreakpointsEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); - AD7BreakpointEvent eventObject = new AD7BreakpointEvent(boundBreakpointsEnum); - - Send(eventObject, AD7BreakpointEvent.IID, thread); - } - - - /// - // Exception events are sent when an exception occurs in the debugged that the debugger was not expecting. - // The VSNDK debug engine does not support these. Not implemented. - /// - public void OnException() - { - throw new Exception("The method or operation is not implemented."); - } - - - /// - /// Step complete is sent when a step has finished. Not implemented. - /// - public void OnStepComplete() - { - throw new Exception("The method or operation is not implemented."); -// AD7StepCompletedEvent.Send(m_engine); - // TODO: implement this method... - } - - - /// - /// This will get called when the engine receives the breakpoint event that is created when the user - /// hits the pause button in VS. - /// - /// The thread running in a program. - public void OnAsyncBreakComplete(AD7Thread thread) - { - AD7AsyncBreakCompleteEvent eventObject = new AD7AsyncBreakCompleteEvent(); - Send(eventObject, AD7AsyncBreakCompleteEvent.IID, thread); - } - - - /// - /// Engines notify the debugger about the results of a symbol search by sending an instance of IDebugSymbolSearchEvent2. - /// Not used. - /// - /// - /// - /// - public void OnSymbolSearch(AD7Module module, string status, uint dwStatusFlags) - { - string statusString = (dwStatusFlags == 1 ? "Symbols Loaded - " : "No symbols loaded") + status; - - AD7SymbolSearchEvent eventObject = new AD7SymbolSearchEvent(module, statusString, dwStatusFlags); - Send(eventObject, AD7SymbolSearchEvent.IID, null); - } - - - /// - /// Engines notify the debugger that a breakpoint has bound through the breakpoint bound event. - /// - /// The bounded breakpoint. - /// 0. - public void OnBreakpointBound(object objBoundBreakpoint, uint address) - { - AD7BoundBreakpoint boundBreakpoint = (AD7BoundBreakpoint)objBoundBreakpoint; - IDebugPendingBreakpoint2 pendingBreakpoint; - ((IDebugBoundBreakpoint2)boundBreakpoint).GetPendingBreakpoint(out pendingBreakpoint); - - AD7BreakpointBoundEvent eventObject = new AD7BreakpointBoundEvent((AD7PendingBreakpoint)pendingBreakpoint, boundBreakpoint); - Send(eventObject, AD7BreakpointBoundEvent.IID, null); - } - - - /// - /// Send an event to notify the SDM that this thread was created. - /// - /// The new thread running in a program. - public void OnThreadStart(AD7Thread debuggedThread) - { - AD7ThreadCreateEvent eventObject = new AD7ThreadCreateEvent(); - Send(eventObject, AD7ThreadCreateEvent.IID, debuggedThread); - } - } -} diff --git a/src/VSNDK.DebugEngine/Engine.Impl/EngineUtils.cs b/src/VSNDK.DebugEngine/Engine.Impl/EngineUtils.cs deleted file mode 100644 index 84bbc69d..00000000 --- a/src/VSNDK.DebugEngine/Engine.Impl/EngineUtils.cs +++ /dev/null @@ -1,55 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Debugger.Interop; -using System.Diagnostics; -using System.Globalization; - -namespace VSNDK.DebugEngine -{ - /// - /// Some utilities used in VSNDK debug engine projects. - /// - public static class EngineUtils - { - - /// - /// - /// - /// An integer value. - public static void RequireOk(int hr) - { - if (hr != 0) - { - throw new InvalidOperationException(); - } - } - - - /// - /// - /// - /// Exception. - /// VSConstants.E_NOTIMPL. - public static int UnexpectedException(Exception e) - { - Debug.Fail("Unexpected exception:" + e); - return VSConstants.E_NOTIMPL; - } - } -} diff --git a/src/VSNDK.DebugEngine/Engine.Impl/EventDispatcher.cs b/src/VSNDK.DebugEngine/Engine.Impl/EventDispatcher.cs deleted file mode 100644 index a3e7919c..00000000 --- a/src/VSNDK.DebugEngine/Engine.Impl/EventDispatcher.cs +++ /dev/null @@ -1,1906 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Microsoft.VisualStudio.Debugger.Interop; -using VSNDK.Parser; -using System.Threading; -using System.Windows.Forms; - -namespace VSNDK.DebugEngine -{ - /// - /// This class manages debug events for the debug engine. - /// - /// Process GDB's output by classifying it by type (e.g. breakpoint event) and providing relevant data. - /// Send GDB commands as appropriate for the received event (e.g. call -exec-continue to resume execution after a breakpoint is - /// inserted). - /// Call debug engine methods to notify the SDM of an event (e.g. if a breakpoint is hit, call EngineCallback.OnBreakpoint()). - /// - public class EventDispatcher - { - /// - /// The private AD7Engine object that represents the DE. - /// - private AD7Engine m_engine = null; - - /// - /// The public AD7Engine object that represents the DE. - /// - public AD7Engine engine - { - get { return m_engine; } - } - - /// - /// Thread responsible for handling asynchronous output from GDB. - /// - private Thread m_processingThread = null; - - /// - /// Represents the object that process asynchronous GDB's output by classifying it by type (e.g. breakpoint event). - /// - GDBOutput m_gdbOutput; - - /// - /// Boolean variable that indicates if the current code is known or unknown, i.e., if there is a source code file associated. - /// - public static bool m_unknownCode = false; - - /// - /// Object used to control the access to the critical section that exists in the "lockedBreakpoint" method. - /// - private Object m_lockBreakpoint = new Object(); - - /// - /// Object used to control the access to the critical section that exists in the "unlockBreakpoint" method. - /// - private Object m_unlockBreakpoint = new Object(); - - /// - /// Object used to control the access to the critical section that exists in the "enterCriticalRegion" method. - /// - private Object m_criticalRegion = new Object(); - - /// - /// Object used to control the access to the critical section that exists in the "leaveCriticalRegion" method. - /// - private Object m_leaveCriticalRegion = new Object(); - - /// - /// Boolean variable that indicates the GDB state: TRUE -> run mode; FALSE -> break mode. - /// - public static bool m_GDBRunMode = true; - - /// - /// Variable that is manipulated only in methods enterCriticalRegion and leaveCriticalRegion - /// - public bool inCriticalRegion = false; - - /// - /// There is a GDB bug that causes a message "Quit (expect signal SIGINT when the program is resumed)". If this message occurs - /// 5 times, VSNDK will end the debug session. That's why this variable is needed, to count the amount of this kind of message - /// that is received in a sequence. - /// - public int countSIGINT = 0; - - - /// - /// Ends the debug session by closing GDB, sending the appropriate events to the SDM, and breaking out of all - /// buffer- and event-listening loops. - /// - /// The exit code. - public void endDebugSession(uint exitCode) - { - // Exit the event dispatch loop. - m_gdbOutput._running = false; - - // Send events to the SDM. - AD7ThreadDestroyEvent.Send(engine, exitCode, null); - AD7ProgramDestroyEvent.Send(engine, exitCode); - - // Exit GDB. - GDBParser.exitGDB(); - - // Notify the AddIn that this debug session has ended. - VSNDK.Package.ControlDebugEngine.isDebugEngineRunning = false; - } - - - /// - /// Constructor. Starts the thread responsible for handling asynchronous GDB output. - /// - /// The AD7Engine object that represents the DE. - public EventDispatcher(AD7Engine engine) - { - m_engine = engine; - - m_gdbOutput = new GDBOutput(this); - m_processingThread = new Thread(m_gdbOutput.processingGDBOutput); - m_processingThread.Start(); - } - - - /// - /// Process asynchronous GDB's output by classifying it by type (e.g. breakpoint event). - /// - public class GDBOutput - { - /// - /// This object manages debug events in the engine. - /// - private EventDispatcher m_eventDispatcher = null; - - /// - /// This object manages breakpoints events. - /// - private HandleBreakpoints m_hBreakpoints = null; - - /// - /// This object manages events related to execution control (processes, threads, programs). - /// - private HandleProcessExecution m_hProcExe = null; - - /// - /// This object manages events related to output messages. - /// - private HandleOutputs m_hOutputs = null; - - /// - /// Boolean variable that corresponds to the event dispatcher status. When false, exit the event dispatch loop. - /// - public bool _running = true; - - - /// - /// Constructor. - /// - /// This object manages debug events in the engine. - public GDBOutput(EventDispatcher ed) - { - m_eventDispatcher = ed; - _running = true; - } - - - /// - /// Thread responsible for handling asynchronous GDB output. - /// - public void processingGDBOutput() - { - while (_running) - { - string response = ""; - while ((response = GDBParser.removeGDBResponse()) == "" && _running) - { - }; - - // Creating a char delimiter that will be used to split the response in more than one event - response = response.Replace("\r\n", "@"); - - string[] events = response.Split('@'); - foreach (string ev in events) - { - if (ev.Length > 1) // only to avoid empty events, when there are two delimiters characters together. - { - if (m_eventDispatcher.countSIGINT > 0) - if ((ev.Substring(0, 2) != "50") && (ev.Substring(0, 2) != "80")) - m_eventDispatcher.countSIGINT = 0; // Reset the counter, if GDB has recovered from a GDB bug. - switch (ev[0]) - { - case '0': // Events related to starting GDB. - break; - case '1': // Not used. - break; - case '2': // Events related to breakpoints (including breakpoint hits). - m_hBreakpoints = new HandleBreakpoints(m_eventDispatcher); - m_hBreakpoints.handle(ev); - break; - case '3': // Not used. - break; - case '4': // Events related to execution control (processes, threads, programs) 1. - m_hProcExe = new HandleProcessExecution(m_eventDispatcher); - m_hProcExe.handle(ev); - break; - case '5': // Events related to execution control (processes, threads, programs and GDB Bugs) 2. - m_hProcExe = new HandleProcessExecution(m_eventDispatcher); - m_hProcExe.handle(ev); - break; - case '6': // Events related to evaluating expressions. Not used. - break; - case '7': // Events related to stack frames. Not used. - break; - case '8': // Events related to output. - m_hOutputs = new HandleOutputs(m_eventDispatcher); - m_hOutputs.handle(ev); - break; - case '9': // Not used. - break; - default: // Event that was not parsed correctly, or not handled completely. - break; - } - } - } - } - } - } - - - /// - /// Interrupt the debugged process if necessary before changing a breakpoint. - /// - public void prepareToModifyBreakpoint() - { - if (m_engine.m_state != AD7Engine.DE_STATE.DESIGN_MODE - && m_engine.m_state != AD7Engine.DE_STATE.BREAK_MODE) - { - HandleProcessExecution.m_needsResumeAfterInterrupt = true; - m_engine.CauseBreak(); - } - } - - - /// - /// If the process was running when the breakpoint was changed, resume the process. - /// - public void resumeFromInterrupt() - { - if (HandleProcessExecution.m_needsResumeAfterInterrupt) - { - HandleProcessExecution.m_needsResumeAfterInterrupt = false; - continueExecution(); - } - } - - - /// - /// Code to set the breakpoint in GDB and then confirm and set in Visual Studio - /// - /// Initial command to set the breakpoint in GDB, with the entire path when setting - /// a breakpoint in a given line number. - /// Initial command to set the breakpoint in GDB, with only the file name when setting - /// a breakpoint in a given line number, or "" when setting a breakpoint in a function. - /// Returns the breakpoint ID in GDB. - /// Returns the breakpoint Line Number. - /// Returns the breakpoint File Name. - /// Returns the Breakpoint Address. - /// If successful, returns true; otherwise, returns false. - private bool setBreakpointImpl(string command, string command2, out uint GDB_ID, out uint GDB_line, out string GDB_filename, out string GDB_address) - { - string response; - string bpointAddress; - string bpointStopPoint; - - GDB_ID = 0; - GDB_filename = ""; - GDB_address = ""; - GDB_line = 0; - - if (VSNDK.Package.ControlDebugEngine.isDebugEngineRunning == true) - { - prepareToModifyBreakpoint(); - - // Gets the parsed response for the GDB/MI command that inserts breakpoint in a given line or a given function. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) - response = GDBParser.parseCommand(command, 6); - - if ((command2 != "") && ((response.Contains("")))) - { - response = GDBParser.parseCommand(command2, 6); - } - - if (((response.Length < 2) && (VSNDK.Package.ControlDebugEngine.isDebugEngineRunning == false)) || (response == "Function not found!")) - { - resumeFromInterrupt(); - return false; - } - - HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); - hBreakpoints.handle(response); - GDB_ID = (uint)hBreakpoints.number; - GDB_filename = hBreakpoints.FileName; - GDB_address = hBreakpoints.Address; - - if ((GDB_address != "") && (GDB_address != "")) - { - //** Run Code to verify breakpoint stop point. - - // Gets the parsed response for the GDB command that print information about the specified breakpoint, in this - // case, only its address. (http://sourceware.org/gdb/onlinedocs/gdb/Set-Breaks.html) - bpointAddress = GDBParser.parseCommand("info b " + GDB_ID.ToString(), 18); - - // Gets the parsed response for the GDB command that inquire what source line covers a particular address. - // (http://sourceware.org/gdb/onlinedocs/gdb/Machine-Code.html) - bpointStopPoint = GDBParser.parseCommand("info line *" + bpointAddress, 18); - - GDB_line = (uint)Convert.ToInt64(bpointStopPoint.Trim()); - } - else - { - GDB_address = "0x0"; - GDB_line = (uint)hBreakpoints.linePos; - } - - resumeFromInterrupt(); - - return true; - } - else - return false; - } - - - /// - /// Set a breakpoint given a filename and line number. - /// - /// Full path and filename for the code source. - /// The line number for the breakpoint. - /// Returns the breakpoint ID in GDB. - /// Returns the breakpoint Line Number. - /// Returns the breakpoint File Name. - /// Returns the Breakpoint Address. - /// If successful, returns true; otherwise, returns false. - public bool setBreakpoint(string filename, uint line, out uint GDB_ID, out uint GDB_line, out string GDB_filename, out string GDB_address) - { - string cmd = @"-break-insert --thread-group i1 -f " + filename + ":" + line; - int i = filename.LastIndexOf('\\'); - if ((i != -1) && (i + 1 < filename.Length)) - filename = filename.Substring(i + 1); - string cmd2 = @"-break-insert --thread-group i1 -f " + filename + ":" + line; - return setBreakpointImpl(cmd, cmd2, out GDB_ID, out GDB_line, out GDB_filename, out GDB_address); - } - - /// - /// Set a breakpoint given a function name. - /// - /// Function name. - /// Returns the breakpoint ID in GDB. - /// Returns the breakpoint Line Number. - /// Returns the breakpoint File Name. - /// Returns the Breakpoint Address. - /// If successful, returns true; otherwise, returns false. - public bool setBreakpoint(string func, out uint GDB_ID, out uint GDB_line, out string GDB_filename, out string GDB_address) - { - string cmd = @"-break-insert " + func; - return setBreakpointImpl(cmd, "", out GDB_ID, out GDB_line, out GDB_filename, out GDB_address); - } - - /// - /// Ignore a given number of hit counts in GDB. - /// - /// Breakpoint ID in GDB. - /// Number of hit counts to ignore. - /// If successful, returns true; otherwise, returns false. - public bool ignoreHitCount(uint GDB_ID, int ignore) - { - ignore -= 1; // The given number is decreased by one, because the VS command means to break when hit count is equal or greater - // than X hits. So, the equivalent GDB command is to break after (X - 1) hit counts. - - if (ignore < 0) - { - // Had to ignore the biggest number of times to keep the breakpoint enabled and to avoid stopping on it. - ignore = int.MaxValue; - } - - // Gets the parsed response for the GDB/MI command that makes the breakpoint "GDB_ID" ignore "ignore" hit counts. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) - string cmd = @"-break-after " + GDB_ID + " " + ignore; - string response = GDBParser.parseCommand(cmd, 18); - - if (response == "") - return false; - - HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); - hBreakpoints.handle(response); - - return true; - } - - - /// - /// Reset current hit count in GDB. There is no way to reset hit counts in GDB. To implement this functionality, the specified GDB - /// breakpoint is deleted and a new one is created with the same conditions, substituting the GDB_ID of the VS breakpoint. - /// - /// The VS breakpoint. - /// Is false when this method is called by SetCondition, true if not. Used to avoid setting - /// breakpoint conditions again in case it is called by SetCondition method. - /// If successful, returns true; otherwise, returns false. - public bool resetHitCount(AD7BoundBreakpoint bbp, bool resetCondition) - { - // Declare local Variables - uint GDB_LinePos = 0; - string GDB_Filename = ""; - string GDB_address = ""; - - uint GDB_ID = bbp.GDB_ID; - - // Deleting GDB breakpoint. - deleteBreakpoint(GDB_ID); - - // Creating a new GDB breakpoint. - bool ret = false; - if (bbp.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) - { - ret = setBreakpoint(bbp.m_filename, bbp.m_line, out GDB_ID, out GDB_LinePos, out GDB_Filename, out GDB_address); - } - else if (bbp.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) - { - ret = setBreakpoint(bbp.m_func, out GDB_ID, out GDB_LinePos, out GDB_Filename, out GDB_address); - } - - if (ret) - { - bbp.GDB_ID = GDB_ID; - bbp.m_hitCount = 0; - bbp.SetPassCount(bbp.m_bpPassCount); - if (resetCondition) - bbp.SetCondition(bbp.m_bpCondition); - - return true; - } - return false; - } - - - - - - /// - /// Set breakpoint condition in GDB. - /// - /// Breakpoint ID in GDB. - /// Condition to be set. When empty (""), means to remove any previous condition. - /// If successful, returns true; otherwise, returns false. - public bool setBreakpointCondition(uint GDB_ID, string condition) - { - string cmd; - - // Gets the parsed response for the GDB/MI command that sets a condition to the breakpoint "GDB_ID". If there is no - // condition, any previous one associated to this breakpoint will be removed. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) - if (condition != "") - cmd = @"-break-condition " + GDB_ID + " " + condition; - else - cmd = @"-break-condition " + GDB_ID; - string response = GDBParser.parseCommand(cmd, 19); - - if (response == "") - return false; - - HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); - hBreakpoints.handle(response); - return true; - } - - - /// - /// Delete a breakpoint in GDB. - /// - /// Breakpoint ID in GDB. - /// If successful, returns true; otherwise, returns false. - public bool deleteBreakpoint(uint GDB_ID) - { - if (m_gdbOutput._running) - { - prepareToModifyBreakpoint(); - - // Gets the parsed response for the GDB/MI command that deletes the breakpoint "GDB_ID". - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) - string response = GDBParser.parseCommand(@"-break-delete " + GDB_ID, 7); - if (response == null || response == "") - { - resumeFromInterrupt(); - return false; - } - - HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); - hBreakpoints.handle(response); - uint retID = (uint)hBreakpoints.number; - - resumeFromInterrupt(); - - if (GDB_ID != retID) - { - return false; - } - } - - return true; - } - - - /// - /// Enable or disable a breakpoint. - /// - /// Breakpoint ID in GDB. - /// If true, enable the breakpoint. If false, disable it. - /// If successful, returns true; otherwise, returns false. - public bool enableBreakpoint(uint GDB_ID, bool fEnable) - { - prepareToModifyBreakpoint(); - - string inputCommand; - string sEnable = "enable"; - - if (!fEnable) - { - sEnable = "disable"; - } - - // Gets the parsed response for the GDB/MI command that enables or disables the breakpoint "GDB_ID". - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) - inputCommand = @"-break-" + sEnable + " " + GDB_ID; - string response = GDBParser.parseCommand(inputCommand, 8); - - HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); - hBreakpoints.handle(response); - uint retID = (uint)hBreakpoints.number; - - resumeFromInterrupt(); - if (GDB_ID != retID) - { - return false; - } - - return true; - } - - - /// - /// Update hit count. - /// - /// Breakpoint ID in GDB. - /// Hit count. - public void updateHitCount(uint ID, uint hitCount) - { - var bbp = m_engine.BPMgr.getBoundBreakpointForGDBID(ID); - if (bbp != null) - { - if (!bbp.m_breakWhenCondChanged) - ((IDebugBoundBreakpoint2)bbp).SetHitCount(hitCount); - } - } - - - /// - /// Lock a breakpoint before updating its hit counts and/or condition. This is done to avoid a race condition that can happen when - /// user modifies a breakpoint condition at run time and the same breakpoint is hit. When that happens, only one event will be - /// handled at a time. - /// - /// Breakpoint to be locked. - /// True if user is adding/modifying count and conditions upon which a breakpoint is fired. It is also true - /// when event dispatcher is handling a breakpoint hit. - /// True if user is adding/modifying conditions under which a conditional breakpoint fires. It is also true - /// when event dispatcher is handling a breakpoint hit. - /// If successful, returns true; otherwise, returns false. - public bool lockedBreakpoint(AD7BoundBreakpoint bbp, bool hit, bool cond) - { - lock (m_lockBreakpoint) - { - if (hit && cond) - { - if ((!bbp.m_blockedPassCount) && (!bbp.m_blockedConditional)) - { - bbp.m_blockedPassCount = true; - bbp.m_blockedConditional = true; - return true; - } - } - else if (hit) - { - if (!bbp.m_blockedPassCount) - { - bbp.m_blockedPassCount = true; - return true; - } - } - else if (cond) - { - if (!bbp.m_blockedConditional) - { - bbp.m_blockedConditional = true; - return true; - } - } - return false; - } - } - - - /// - /// Unlock a breakpoint after updating its hit counts and/or condition. This is done to avoid a race condition that can happen when - /// user modifies a breakpoint condition at run time and the same breakpoint is hit. When that happens, only one event will be - /// handled at a time. - /// - /// Breakpoint to be locked. - /// True if user is adding/modifying count and conditions upon which a breakpoint is fired. It is also true - /// when event dispatcher is handling a breakpoint hit. - /// True if user is adding/modifying conditions under which a conditional breakpoint fires. It is also true - /// when event dispatcher is handling a breakpoint hit. - public void unlockBreakpoint(AD7BoundBreakpoint bbp, bool hit, bool cond) - { - lock (m_unlockBreakpoint) - { - if (hit && cond) - { - bbp.m_blockedPassCount = false; - bbp.m_blockedConditional = false; - } - else if (hit) - { - bbp.m_blockedPassCount = false; - } - else if (cond) - { - bbp.m_blockedConditional = false; - } - } - } - - - /// - /// Control access to a critical region, that manipulates some of the debug engine variables, like its state. This is done to - /// avoid a race condition that can happen when user modifies a breakpoint condition at run time and the same breakpoint is hit. - /// When that happens, only one event will be handled at a time. - /// - /// If successful, returns true; otherwise, returns false. - public bool enterCriticalRegion() - { - lock (m_criticalRegion) - { - if (!inCriticalRegion) - { - inCriticalRegion = true; - return true; - } - return false; - } - } - - - /// - /// Leave the critical region, that manipulates some of the debug engine variables, like its state. This is done to - /// avoid a race condition that can happen when user modifies a breakpoint condition at run time and the same breakpoint is hit. - /// When that happens, only one event will be handled at a time. - /// - public void leaveCriticalRegion() - { - lock (m_leaveCriticalRegion) - { - inCriticalRegion = false; - } - } - - - /// - /// Update VS when a breakpoint is hit in GDB. - /// - /// Breakpoint ID from GDB. - /// Thread ID. - public void breakpointHit(uint ID, string threadID) - { - var xBoundBreakpoints = new List(); - - // Search the active bound BPs and find ones that match the ID. - var bbp = m_engine.BPMgr.getBoundBreakpointForGDBID(ID); - - if (bbp != null) - xBoundBreakpoints.Add(bbp); - - if ((bbp == null) || (xBoundBreakpoints.Count == 0)) - { - // if no matching breakpoints are found then its one of the following: - // - Stepping operation - // - Code based break - // - Asm stepping - } - else - { - if (lockedBreakpoint(bbp, true, true)) - { - while (!enterCriticalRegion()) - { - Thread.Sleep(0); - } - - bool breakExecution = true; - - if (bbp.m_breakWhenCondChanged) - { - string result = ""; - bool valid = VariableInfo.evaluateExpression(bbp.m_bpCondition.bstrCondition, ref result, null); - if ((valid) && (bbp.m_previousCondEvaluation != result)) // check if condition evaluation has changed - { - if ((bbp.m_bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL) && (bbp.m_hitCount != bbp.m_bpPassCount.dwPassCount)) - { - breakExecution = false; - } - else if ((bbp.m_bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL_OR_GREATER) && (bbp.m_hitCount < bbp.m_bpPassCount.dwPassCount)) - { - breakExecution = false; - } - else if ((bbp.m_bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_MOD) && ((bbp.m_hitCount % bbp.m_bpPassCount.dwPassCount) != 0)) - { - breakExecution = false; - } - bbp.m_previousCondEvaluation = result; - } - else - breakExecution = false; - } - if (!breakExecution) // must continue the execution - { - bool hitBreakAll = m_engine.m_running.WaitOne(0); - if (hitBreakAll) - { - m_engine.m_state = AD7Engine.DE_STATE.RUN_MODE; - - // Sends the GDB command that resumes the execution of the inferior program. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand(@"-exec-continue --thread-group i1"); - EventDispatcher.m_GDBRunMode = true; - m_engine.m_running.Set(); - } - } - else - { - if (bbp.m_breakWhenCondChanged) - bbp.m_hitCount += 1; - - // Transition DE state - EventDispatcher.m_GDBRunMode = false; - m_engine.m_state = AD7Engine.DE_STATE.BREAK_MODE; - - // Found a bound breakpoint - m_engine.Callback.OnBreakpoint(m_engine.selectThread(threadID), xBoundBreakpoints.AsReadOnly()); - - if (bbp.m_isHitCountEqual) - { - // Have to ignore the biggest number of times to keep the breakpoint enabled and to avoid stopping on it. - ignoreHitCount(ID, int.MaxValue); - } - else if (bbp.m_hitCountMultiple != 0) - { - ignoreHitCount(ID, (int)(bbp.m_hitCountMultiple - (bbp.m_hitCount % bbp.m_hitCountMultiple))); - } - } - leaveCriticalRegion(); - unlockBreakpoint(bbp, true, true); - } - else - { - while (!enterCriticalRegion()) - { - Thread.Sleep(0); - } - - bool hitBreakAll = m_engine.m_running.WaitOne(0); - if (hitBreakAll) - { - m_engine.m_state = AD7Engine.DE_STATE.RUN_MODE; - - // Sends the GDB command that resumes the execution of the inferior program. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand(@"-exec-continue --thread-group i1"); - EventDispatcher.m_GDBRunMode = true; - m_engine.m_running.Set(); - } - - leaveCriticalRegion(); - } - } - } - - - /// - /// Returns the document context needed for showing the location of the current instruction pointer. - /// - /// File name. - /// Line number. - /// Returns the document context needed for showing the location of the current instruction pointer. - public AD7DocumentContext getDocumentContext(string filename, uint line) - { - // Get the location in the document that the breakpoint is in. - TEXT_POSITION[] startPosition = new TEXT_POSITION[1]; - startPosition[0].dwLine = line; - startPosition[0].dwColumn = 0; - TEXT_POSITION[] endPosition = new TEXT_POSITION[1]; - endPosition[0].dwLine = line; - endPosition[0].dwColumn = 0; - - uint address = 0; - AD7MemoryAddress codeContext = new AD7MemoryAddress(m_engine, address); - - return new AD7DocumentContext(filename, startPosition[0], endPosition[0], codeContext); - } - - - /// - /// Return the depth of the stack. - /// - /// Thread ID. - /// Returns the stack depth. - public int getStackDepth(string threadID) - { - // Returns the parsed response for the GDB/MI command that inquires about the depth of the stack. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) - return Convert.ToInt32(GDBParser.parseCommand(@"-stack-info-depth --thread " + threadID + " --frame 0", 9)); - } - - - /// - /// List the frames currently on the stack. - /// - /// Returns a string with the frames currently on the stack. - public string getStackFrames() - { - // Returns the parsed response for the GDB/MI command that list the frames currently on the stack. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) - return GDBParser.parseCommand(@"-stack-list-frames", 10); - } - - - /// - /// List the names of local variables and function arguments for the selected frame. - /// - /// Frame number. - /// Thread ID. - /// Returns a string with the names of local variables and function arguments for the selected frame. - public string getVariablesForFrame(uint frameIndex, string threadID) - { - // Returns the parsed response for the GDB/MI command that list the names of local variables and function arguments for the - // selected frame. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) - return GDBParser.parseCommand(@"-stack-list-variables --thread " + threadID + " --frame " + frameIndex + " --simple-values", 11); - } - - - /// - /// Make "id" the current thread. - /// - /// Thread ID. - public void selectThread(string id) - { - // Waits for the parsed response for the GDB/MI command that make "id" the current thread. - // (http://www.sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html) - GDBParser.parseCommand(@"-thread-select " + id, 12); - } - - - /// - /// Creates a variable object. - /// - /// Name of the variable. - /// Boolean value that indicates if the variable name has the prefix VsNdK_. - /// If successful, returns the variable's number of children; otherwise, returns string "ERROR". - public string createVar(string name, ref bool hasVsNdK_) - { - // Gets the variable's number of children after sending the following GDB/MI command to create a variable object. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html) - string response = GDBParser.parseCommand("-var-create " + name + " \"*\" " + name, 13); - if (response == "ERROR") - { - // The -var-create GDB/MI command can return an error when the variable name starts with some characters, like '_'. - // So, in case of an error, add the prefix VsNdK_ to the variable name and try to create it again. - response = GDBParser.parseCommand("-var-create VsNdK_" + name + " \"*\" " + name, 13); - if (response != "ERROR") - hasVsNdK_ = true; - } - return response; - } - - - /// - /// Deletes a previously created variable object and all of its children. - /// - /// Name of the variable. - /// Boolean value that indicates if the variable name has the prefix VsNdK_. - public void deleteVar(string name, bool hasVsNdK_) - { - // Waits for the parsed response for the GDB/MI command that deletes a previously created variable object and all of - // its children. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html) - if (!hasVsNdK_) - GDBParser.parseCommand("-var-delete " + name, 14); - else - GDBParser.parseCommand("-var-delete VsNdK_" + name, 14); - } - - - /// - /// Return a list of the children of the specified variable object. - /// - /// Variable name. - /// Return a string that contains the list of the children of the specified variable object. - public string listChildren(string name) - { - // Returns the parsed response for the GDB/MI command that list the children of the specified variable object. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html) - return GDBParser.parseCommand("-var-list-children --all-values " + name + " 0 50", 15); - } - - - /// - /// Kill the child process in which your program is running under gdb. - /// - public void killProcess() - { - // Waits for the parsed response for the GDB command that kills the child process in which your program is running. - // (http://sourceware.org/gdb/onlinedocs/gdb/Kill-Process.html#Kill-Process) - GDBParser.parseCommand("kill", 16); - } - - - /// - /// Called after the debug engine has set the initial breakpoints, or to resume a process that was interrupted. - /// - public void continueExecution() - { - //** Transition DE state - bool hitBreakAll = m_engine.m_running.WaitOne(0); - if (hitBreakAll) - { - m_engine.m_state = AD7Engine.DE_STATE.RUN_MODE; - - // Sends the GDB command that resumes the execution of the inferior program. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) - GDBParser.addGDBCommand(@"-exec-continue --thread-group i1"); - EventDispatcher.m_GDBRunMode = true; - m_engine.m_running.Set(); - } - } - } - - - /// - /// This class manages breakpoints events. - /// - public class HandleBreakpoints - { - /// - /// GDB breakpoint ID. - /// - private int m_number = -1; - - /// - /// Boolean variable that indicates if this breakpoint is enable (true) or disable (false). - /// - private bool m_enable = false; - - /// - /// Breakpoint address. - /// - private string m_addr = ""; - - /// - /// Name of the function that contains this breakpoint. - /// - private string m_func = ""; - - /// - /// File name that contains this breakpoint. - /// - private string m_filename = ""; - - /// - /// Line number for this breakpoint. - /// - private int m_line = -1; - - /// - /// Number of hits for this breakpoint. - /// - private int m_hits = -1; - - /// - /// Number of hits to be ignored by this breakpoint. - /// - private int m_ignoreHits = -1; - - /// - /// Condition associated to this breakpoint. - /// - private string m_condition = ""; - - /// - /// Thread ID that was interrupted when this breakpoint was hit. - /// - private string m_threadID = ""; - - /// - /// This object manages debug events in the engine. - /// - private EventDispatcher m_eventDispatcher = null; - - /// - /// GDB_ID Property - /// - public int number - { - get { return m_number; } - } - - /// - /// GDB Line Position Property - /// - public int linePos - { - get { return m_line; } - } - - /// - /// GDB File name - /// - public string FileName - { - get { return m_filename; } - } - - /// - /// GDB Address - /// - public string Address - { - get { return m_addr; } - } - - - /// - /// Constructor. - /// - /// This object manages debug events in the engine. - public HandleBreakpoints(EventDispatcher ed) - { - m_eventDispatcher = ed; - } - - - /// - /// This method manages breakpoints events by classifying each of them by sub-type (e.g. breakpoint inserted, modified, etc.). - /// - /// String that contains the event description. - public void handle(string ev) - { - int ini = 0; - int end = 0; - switch (ev[1]) - { - case '0': - // Breakpoint inserted (synchronous). - // Example: 20,1,y,0x0804d843,main,C:/Users/xxxxx/vsplugin-ndk/samples/Square/Square/main.c,319,0 - ini = 3; - end = ev.IndexOf(';', 3); - m_number = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - if (ev[end + 1] == 'y') - m_enable = true; - else - m_enable = false; - - ini = end + 3; - end = ev.IndexOf(';', ini); - m_addr = ev.Substring(ini, (end - ini)); - if (m_addr == "") - { - m_func = "??"; - EventDispatcher.m_unknownCode = true; - m_filename = ""; - m_line = 0; - m_hits = 0; - return; - } - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_func = ev.Substring(ini, end - ini); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_filename = ev.Substring(ini, end - ini); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_line = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_hits = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - - break; - case '1': - // Breakpoint modified (asynchronous). - // Example: 21,1,y,0x0804d843,main,C:/Users/xxxxxx/vsplugin-ndk/samples/Square/Square/main.c,318,1 - ini = 3; - end = ev.IndexOf(';', 3); - m_number = Convert.ToInt32(ev.Substring(ini, (end - ini))); ; - - if (ev[end + 1] == 'y') - m_enable = true; - else - m_enable = false; - - ini = end + 3; - end = ev.IndexOf(';', ini); - m_addr = ev.Substring(ini, (end - ini)); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_func = ev.Substring(ini, end - ini); - - // Need to set the flag for unknown code if necessary. - if (m_func == "??") - { - EventDispatcher.m_unknownCode = true; - } - else - { - EventDispatcher.m_unknownCode = false; - } - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_filename = ev.Substring(ini, end - ini); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_line = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_hits = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - - // Update hit count on affected bound breakpoint. - m_eventDispatcher.updateHitCount((uint)m_number, (uint)m_hits); - - break; - case '2': - // Breakpoint deleted asynchronously (a temporary breakpoint). Example: 22,2\r\n - m_number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); - - break; - case '3': - // Breakpoint enabled. Example: 23 (enabled all) or 23,1 (enabled only breakpoint 1) - if (ev.Length > 2) - m_number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); - else - m_number = 0; // 0 means ALL breakpoints. - - break; - case '4': - // Breakpoint disabled. Example: 24 (disabled all) or 24,1 (disabled only breakpoint 1) - if (ev.Length > 2) - m_number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); - else - m_number = 0; // 0 means ALL breakpoints. - - break; - case '5': - // Breakpoint deleted. Example: 25 (deleted all) or 25,1 (deleted only breakpoint 1) - if (ev.Length > 2) - m_number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); - else - m_number = 0; // 0 means ALL breakpoints. - - break; - case '6': - // Break after "n" hits (or ignore n hits). Example: 26;1;100 - ini = 3; - end = ev.IndexOf(';', 3); - m_number = Convert.ToInt32(ev.Substring(3, (end - 3))); - - ini = end + 1; - m_ignoreHits = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - - break; - case '7': - // Breakpoint hit. - // Example: 27,1,C:/Users/xxxxxx/vsplugin-ndk/samples/Square/Square/main.c,319;1\r\n - bool updatingCondBreak = this.m_eventDispatcher.engine.m_updatingConditionalBreakpoint.WaitOne(0); - if (updatingCondBreak) - { - - m_eventDispatcher.engine.resetStackFrames(); - - ini = 3; - end = ev.IndexOf(';', 3); - m_number = Convert.ToInt32(ev.Substring(3, (end - 3))); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_filename = ev.Substring(ini, end - ini); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_line = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_threadID = ev.Substring(ini, (ev.Length - ini)); - - this.m_eventDispatcher.engine.cleanEvaluatedThreads(); - - // Call the method/event that will stop SDM because a breakpoint was hit here. - if (m_eventDispatcher.engine._updateThreads) - { - m_eventDispatcher.engine.UpdateListOfThreads(); - } - m_eventDispatcher.engine.selectThread(m_threadID).setCurrentLocation(m_filename, (uint)m_line); - m_eventDispatcher.engine.setAsCurrentThread(m_threadID); - - // A breakpoint can be hit during a step - if (m_eventDispatcher.engine.m_state == AD7Engine.DE_STATE.STEP_MODE) - { - HandleProcessExecution.onStepCompleted(m_eventDispatcher, m_filename, (uint)m_line); - } - else - { - // Visual Studio shows the line position one more than it actually is - m_eventDispatcher.engine.m_docContext = m_eventDispatcher.getDocumentContext(m_filename, (uint)(m_line - 1)); - m_eventDispatcher.breakpointHit((uint)m_number, m_threadID); - } - this.m_eventDispatcher.engine.m_updatingConditionalBreakpoint.Set(); - } - break; - case '8': - // Breakpoint condition set. Example: 28;1;expression - ini = 3; - end = ev.IndexOf(';', 3); - if (end != -1) - { - m_number = Convert.ToInt32(ev.Substring(3, (end - 3))); - - ini = end + 1; - m_condition = ev.Substring(ini, (ev.Length - ini)); - } - else - { - m_number = Convert.ToInt32(ev.Substring(3)); - m_condition = ""; - } - break; - case '9': // Error in testing breakpoint condition - break; - default: // not used. - break; - } - } - } - - - /// - /// This class manages events related to execution control (processes, threads, programs). - /// - public class HandleProcessExecution - { - /// - /// Thread ID. - /// - private int m_threadId = -1; // when threadId is 0, it means all threads. - - /// - /// Process ID. - /// - private int m_processId = -1; - - /// - /// Name of the signal that caused an interruption. - /// - private string m_signalName = ""; - - /// - /// Meaning of the signal that caused an interruption. - /// - private string m_signalMeaning = ""; - - /// - /// File name. - /// - private string m_file = ""; - - /// - /// Line number. - /// - private int m_line = -1; - - /// - /// Address. - /// - private int m_address = -1; - - /// - /// Function name. - /// - private string m_func = ""; - - /// - /// Error caused by a GDB command that failed. - /// - private string m_error = ""; - - /// - /// This object manages debug events in the engine. - /// - private EventDispatcher m_eventDispatcher = null; - - /// - /// Boolean variable that indicates if GDB has to resume execution after handling what caused it to enter in break mode. - /// - public static bool m_needsResumeAfterInterrupt = false; - - /// - /// Used as a communication signal between the Event Dispatcher and the debug engine method responsible for stopping GDB - /// execution (IDebugEngine2.CauseBreak()). So, VS is able to wait for GDB's interruption before entering in break mode. - /// - public static ManualResetEvent m_mre = new ManualResetEvent(false); - - - /// - /// Constructor. - /// - /// This object manages debug events in the engine. - public HandleProcessExecution(EventDispatcher ed) - { - m_eventDispatcher = ed; - } - - - /// - /// This method manages events related to execution control by classifying each of them by sub-type (e.g. thread created, program interrupted, etc.). - /// - /// String that contains the event description. - public void handle(string ev) - { - int ini = 0; - int end = 0; - int numCommas = 0; - switch (ev[0]) - { - case '4': - switch (ev[1]) - { - case '0': - // Thread created. Example: 40,2,20537438 - EventDispatcher.m_GDBRunMode = true; - ini = 3; - end = ev.IndexOf(";", 3); - m_threadId = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_processId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - - m_eventDispatcher.engine._updateThreads = true; - - break; - case '1': - // Process running. Example: 41,1 (when threadId is 0 means "all threads": example: 41,0) - EventDispatcher.m_GDBRunMode = true; - m_threadId = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); - - break; - case '2': - // Program exited normally. Example: 42 - m_eventDispatcher.endDebugSession(0); - - break; - case '3': - // Program was exited with an exit code. Example: 43,1;1 (not sure if there is a threadID, but the last ";" exist) - // TODO: not tested yet - end = ev.IndexOf(";", 3); - uint exitCode = Convert.ToUInt32(ev.Substring(3, (end - 3))); - m_eventDispatcher.endDebugSession(exitCode); - - break; - case '4': - // Program interrupted. - // Examples: - // 44,ADDR,FUNC,THREAD-ID - // 44,ADDR,FUNC,FILENAME,LINE,THREAD-ID - - m_eventDispatcher.engine.resetStackFrames(); - EventDispatcher.m_GDBRunMode = false; - numCommas = 0; - foreach (char c in ev) - { - if (c == ';') - numCommas++; - } - - ini = 3; - end = ev.IndexOf(';', ini); - m_address = Convert.ToInt32(ev.Substring(ini, (end - ini)), 16); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_func = ev.Substring(ini, (end - ini)); - - if (m_func == "??") - { - EventDispatcher.m_unknownCode = true; - } - else - { - EventDispatcher.m_unknownCode = false; - } - - switch (numCommas) - { - case 3: - // Thread ID - ini = end + 1; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - EventDispatcher.m_unknownCode = true; - break; - case 4: - // Filename and line number - ini = end + 1; - end = ev.IndexOf(';', ini); - m_file = ev.Substring(ini, (end - ini)); - - ini = end + 1; - m_line = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - break; - case 5: - // Filename, line number and thread ID - ini = end + 1; - end = ev.IndexOf(';', ini); - m_file = ev.Substring(ini, (end - ini)); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_line = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - break; - default: - break; - } - - this.m_eventDispatcher.engine.cleanEvaluatedThreads(); - - - if (m_eventDispatcher.engine._updateThreads) - { - m_eventDispatcher.engine.UpdateListOfThreads(); - } - if (m_threadId > 0) - { - m_eventDispatcher.engine.selectThread(m_threadId.ToString()).setCurrentLocation(m_file, (uint)m_line); - m_eventDispatcher.engine.setAsCurrentThread(m_threadId.ToString()); - } - - // Call the method/event that will let SDM know that the debugged program was interrupted. - onInterrupt(m_threadId); - - // Signal that interrupt is processed - m_mre.Set(); - - break; - - case '5': - // End-stepping-range. - m_eventDispatcher.engine.resetStackFrames(); - EventDispatcher.m_GDBRunMode = false; - ini = 3; - end = ev.IndexOf(';', 3); - if (end == -1) - end = ev.Length; - string temp = ev.Substring(ini, (end - ini)); - - ini = end + 1; - - if (ev.Length > ini) - end = ev.IndexOf(';', ini); - else - end = -1; - - if (end == -1) - { - // Set sane default values for the missing file and line information - m_file = ""; - m_line = 1; - m_threadId = Convert.ToInt32(temp); - EventDispatcher.m_unknownCode = true; - } - else - { - m_file = temp; - m_line = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - EventDispatcher.m_unknownCode = false; - } - - this.m_eventDispatcher.engine.cleanEvaluatedThreads(); - - - if (m_eventDispatcher.engine._updateThreads) - { - m_eventDispatcher.engine.UpdateListOfThreads(); - } - if (m_threadId > 0) - { - if ((EventDispatcher.m_unknownCode == false) && (m_file != "")) - m_eventDispatcher.engine.selectThread(m_threadId.ToString()).setCurrentLocation(m_file, (uint)m_line); - m_eventDispatcher.engine.setAsCurrentThread(m_threadId.ToString()); - } - - HandleProcessExecution.onStepCompleted(m_eventDispatcher, m_file, (uint)m_line); - - break; - case '6': - // Function-finished. - m_eventDispatcher.engine.resetStackFrames(); - EventDispatcher.m_GDBRunMode = false; - ini = 3; - end = ev.IndexOf(';', 3); - if (end == -1) - { - // Set sane default values for the missing file and line information - m_file = ""; - m_line = 1; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - EventDispatcher.m_unknownCode = true; - } - else - { - m_file = ev.Substring(ini, (end - ini)); - ini = end + 1; - end = ev.IndexOf(';', ini); - m_line = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - EventDispatcher.m_unknownCode = false; - } - - this.m_eventDispatcher.engine.cleanEvaluatedThreads(); - - if (m_eventDispatcher.engine._updateThreads) - { - m_eventDispatcher.engine.UpdateListOfThreads(); - } - if (m_threadId > 0) - { - if ((EventDispatcher.m_unknownCode == false) && (m_file != "")) - m_eventDispatcher.engine.selectThread(m_threadId.ToString()).setCurrentLocation(m_file, (uint)m_line); - m_eventDispatcher.engine.setAsCurrentThread(m_threadId.ToString()); - } - - HandleProcessExecution.onStepCompleted(m_eventDispatcher, m_file, (uint)m_line); - - break; - case '7': - // -exec-interrupt or signal-meaning="Killed". There's nothing to do in this case. - m_eventDispatcher.engine.resetStackFrames(); - EventDispatcher.m_GDBRunMode = false; - - this.m_eventDispatcher.engine.cleanEvaluatedThreads(); - - m_threadId = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); - - if (m_eventDispatcher.engine._updateThreads) - { - m_eventDispatcher.engine.UpdateListOfThreads(); - } - if (m_threadId > 0) - { - if ((EventDispatcher.m_unknownCode == false) && (m_file != "")) - m_eventDispatcher.engine.selectThread(m_threadId.ToString()).setCurrentLocation(m_file, (uint)m_line); - m_eventDispatcher.engine.setAsCurrentThread(m_threadId.ToString()); - } - - if (m_eventDispatcher.engine.m_state != AD7Engine.DE_STATE.BREAK_MODE) - { - onInterrupt(m_threadId); - } - // Signal that interrupt is processed - m_mre.Set(); - - break; - case '8': - // SIGKILL - m_eventDispatcher.endDebugSession(0); - break; - case '9': - // ERROR, ex: 49,Cannot find bounds of current function - m_eventDispatcher.engine.resetStackFrames(); - this.m_eventDispatcher.engine.cleanEvaluatedThreads(); - - if (m_eventDispatcher.engine._updateThreads) - { - m_eventDispatcher.engine.UpdateListOfThreads(); - } - - if (ev.Length >= 3) - { - m_error = ev.Substring(3, (ev.Length - 3)); - if (m_error == "Cannot find bounds of current function") - { - // We don't have symbols for this function so further stepping won't be possible. Return from this function. - VSNDK.DebugEngine.EventDispatcher.m_unknownCode = true; - m_eventDispatcher.engine.Step(m_eventDispatcher.engine.currentThread(), enum_STEPKIND.STEP_OUT, enum_STEPUNIT.STEP_LINE); - } - } - break; - default: // Not used. - break; - } - break; - case '5': - switch (ev[1]) - { - case '0': - // Quit (expect signal SIGINT when the program is resumed) - m_eventDispatcher.countSIGINT += 1; - if (m_eventDispatcher.countSIGINT > 5) - { - m_eventDispatcher.endDebugSession(0); - MessageBox.Show("Lost communication with GDB. Please refer to documentation for more details.", "GDB failure", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - break; - case '1': - // Thread exited. Example: 51,2 - ini = 3; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - - m_eventDispatcher.engine._updateThreads = true; - - break; - case '2': - // GDB Bugs, like "... 2374: internal-error: frame_cleanup_after_sniffer ...". Example: 52 - m_eventDispatcher.endDebugSession(0); - MessageBox.Show("This is a known issue that can happen when interrupting GDB's execution by hitting the \"break all\" or toggling a breakpoint in run mode. \n\n GDB CRASHED. Details: \"../../gdb/frame.c:2374: internal-error: frame_cleanup_after_sniffer: Assertion `frame->prologue_cache == NULL' failed.\nA problem internal to GDB has been detected,\nfurther debugging may prove unreliable.\" \r\n \nPlease close the app in the device/simulator if you want to debug it again.", "GDB failure", MessageBoxButtons.OK, MessageBoxIcon.Error); - - break; - case '3': - // Lost communication with device/simulator: ^error,msg="Remote communication error: No error." - MessageBox.Show("Lost communication with the device/simulator.", "Communication lost", MessageBoxButtons.OK, MessageBoxIcon.Error); - m_eventDispatcher.endDebugSession(0); - - break; - case '4': - // Program interrupted due to a segmentation fault. - // Examples: - // 54,ADDR,FUNC,THREAD-ID - // 54,ADDR,FUNC,FILENAME,LINE,THREAD-ID - - m_eventDispatcher.engine.resetStackFrames(); - EventDispatcher.m_GDBRunMode = false; - numCommas = 0; - foreach (char c in ev) - { - if (c == ';') - numCommas++; - } - - ini = 3; - end = ev.IndexOf(';', ini); - m_address = Convert.ToInt32(ev.Substring(ini, (end - ini)), 16); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_func = ev.Substring(ini, (end - ini)); - - if (m_func == "??") - { - EventDispatcher.m_unknownCode = true; - } - else - { - EventDispatcher.m_unknownCode = false; - } - - switch (numCommas) - { - case 3: - // Thread ID - ini = end + 1; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - EventDispatcher.m_unknownCode = true; - break; - case 5: - // Filename, line number and thread ID - ini = end + 1; - end = ev.IndexOf(';', ini); - m_file = ev.Substring(ini, (end - ini)); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_line = Convert.ToInt32(ev.Substring(ini, (end - ini))); - - ini = end + 1; - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - break; - default: - break; - } - - MessageBox.Show("Segmentation Fault: If you continue debugging could take the environment to an unstable state.", "Segmentation Fault", MessageBoxButtons.OK, MessageBoxIcon.Warning); - - this.m_eventDispatcher.engine.cleanEvaluatedThreads(); - - if (m_eventDispatcher.engine._updateThreads) - { - m_eventDispatcher.engine.UpdateListOfThreads(); - } - if (m_threadId > 0) - { - m_eventDispatcher.engine.selectThread(m_threadId.ToString()).setCurrentLocation(m_file, (uint)m_line); - m_eventDispatcher.engine.setAsCurrentThread(m_threadId.ToString()); - } - - onInterrupt(m_threadId); - - break; - - case '5': - // Exited-signaled. Ex: 55;SIGSEGV;Segmentation fault - // or Aborted. Ex: 55;SIGABRT;Aborted - ini = 3; - end = ev.IndexOf(';', ini); - m_signalName = ev.Substring(ini, (end - ini)); - - ini = end + 1; - end = ev.IndexOf(';', ini); - m_signalMeaning = ev.Substring(ini, (end - ini)); - - ini = end + 1; - try - { - m_threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); - } - catch - { - } - - if (m_signalMeaning == "Segmentation fault") - { - MessageBox.Show("Segmentation Fault: Closing debugger.", "Segmentation Fault", MessageBoxButtons.OK, MessageBoxIcon.Error); - m_eventDispatcher.endDebugSession(0); - } - - if (m_signalMeaning == "Aborted") - { - MessageBox.Show("Program aborted: Closing debugger.", "Program Aborted", MessageBoxButtons.OK, MessageBoxIcon.Error); - m_eventDispatcher.endDebugSession(0); - } - - break; - case '6': - // GDB Bugs, like "... 3550: internal-error: handle_inferior_event ...". Example: 56 - m_eventDispatcher.endDebugSession(0); - MessageBox.Show("This is a known issue that can happen while debugging multithreaded programs. \n\n GDB CRASHED. Details: \"../../gdb/infrun.c:3550: internal-error: handle_inferior_event: Assertion ptid_equal (singlestep_ptid, ecs->ptid)' failed.\nA problem internal to GDB has been detected,\nfurther debugging may prove unreliable.\" \r\n \nPlease close the app in the device/simulator if you want to debug it again.", "GDB failure", MessageBoxButtons.OK, MessageBoxIcon.Error); - - break; - case '7': // Not used - break; - case '8': // Not used - break; - case '9': // Not used - break; - default: // Not used. - break; - } - break; - default: // Not used. - break; - } - } - - - /// - /// Update VS when a step action is completed in GDB. - /// - /// This object manages debug events in the engine. - /// File name. - /// Line number. - public static void onStepCompleted(EventDispatcher eventDispatcher, string file, uint line) - { - if (eventDispatcher.engine.m_state == AD7Engine.DE_STATE.STEP_MODE) - { - eventDispatcher.engine.m_state = AD7Engine.DE_STATE.BREAK_MODE; - - // Visual Studio shows the line position one more than it actually is - eventDispatcher.engine.m_docContext = eventDispatcher.getDocumentContext(file, line - 1); - AD7StepCompletedEvent.Send(eventDispatcher.engine); - } - } - - - /// - /// Update VS when the debugging process is interrupted in GDB. - /// - /// Thread ID. - private void onInterrupt(int threadID) - { - Debug.Assert(m_eventDispatcher.engine.m_state == AD7Engine.DE_STATE.RUN_MODE); - m_eventDispatcher.engine.m_state = AD7Engine.DE_STATE.BREAK_MODE; - - if (m_file != "" && m_line > 0) - { - // Visual Studio shows the line position one more than it actually is - m_eventDispatcher.engine.m_docContext = m_eventDispatcher.getDocumentContext(m_file, (uint)(m_line - 1)); - } - - // Only send OnAsyncBreakComplete if break-all was requested by the user - if (!m_needsResumeAfterInterrupt) - { - m_eventDispatcher.engine.Callback.OnAsyncBreakComplete(m_eventDispatcher.engine.selectThread(threadID.ToString())); - } - } - } - - - /// - /// This class manages events related to output messages. - /// - public class HandleOutputs - { - /// - /// GDB textual output from the running target to be presented in the VS standard output window. - /// - private string m_stdOut = ""; - - /// - /// Other GDB messages to be presented in the VS standard output window. - /// - private string m_console = ""; - - /// - /// This object manages debug events in the engine. - /// - private EventDispatcher m_eventDispatcher = null; - - - /// - /// Constructor. - /// - /// This object manages debug events in the engine. - public HandleOutputs(EventDispatcher ed) - { - m_eventDispatcher = ed; - } - - - /// - /// This method manages events related to output messages by classifying each of them by sub-type. - /// - /// String that contains the event description. - public void handle(string ev) - { - int ini = 0; - int end = 0; - switch (ev[1]) - { - case '0': // Display the m_console message in the VS output window. Example: 80,\"\"[New pid 15380494 tid 2]\\n\"\"!80 - ini = 4; - end = ev.IndexOf("\"!80", 4); - m_console = ev.Substring(ini, (end - ini)); - - // TODO: Call the method/event that will output this message in the VS output window. - - break; - case '1': // Display the m_stdOut message in the VS standard output window. Instruction should look like this: 81,\"\" ... "\"!81 - ini = 4; - end = ev.IndexOf("\"!81", 4); - m_stdOut = ev.Substring(ini, (end - ini)); - - // TODO: Call the method/event that will output this message in the VS standar output window. - - break; - default: // not used. - break; - } - } - } -} diff --git a/src/VSNDK.DebugEngine/NameValueCollectionHelper.cs b/src/VSNDK.DebugEngine/NameValueCollectionHelper.cs deleted file mode 100644 index 10c9ed6c..00000000 --- a/src/VSNDK.DebugEngine/NameValueCollectionHelper.cs +++ /dev/null @@ -1,76 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections.Specialized; - -namespace VSNDK.DebugEngine -{ - /// - /// - /// - public static class NameValueCollectionHelper - { - - /// - /// - /// - /// - /// - public static string DumpToString(NameValueCollection value) - { - var xSB = new StringBuilder(); - foreach (string xKey in value.Keys) - { - xSB.AppendFormat("{0}={1};", xKey, (string)value[xKey]); - } - return xSB.ToString(); - } - - - /// - /// - /// - /// - /// - public static void LoadFromString(NameValueCollection target, string value) - { - if (target.Count > 0) - { - throw new Exception("Target is not empty!"); - } - if (String.IsNullOrEmpty(value)) - { - return; - } - - string[] xPairs = value.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - foreach (var xPair in xPairs) - { - string[] xParts = xPair.Split('='); - if (xParts.Length > 1) - { - target.Add(xParts[0], xParts[1]); - } - else - { - target.Add(xParts[0], ""); - } - } - } - } -} \ No newline at end of file diff --git a/src/VSNDK.DebugEngine/Properties/AssemblyInfo.cs b/src/VSNDK.DebugEngine/Properties/AssemblyInfo.cs deleted file mode 100644 index 8a09361e..00000000 --- a/src/VSNDK.DebugEngine/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,50 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("VSNDK.DebugEngine")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("BlackBerry")] -[assembly: AssemblyProduct("VSNDK.DebugEngine")] -[assembly: AssemblyCopyright("Copyright © Research In Motion 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("7925a96c-7e19-4796-87ef-41634e94a31a")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/VSNDK.DebugEngine/VSNDK.DebugEngine.csproj b/src/VSNDK.DebugEngine/VSNDK.DebugEngine.csproj deleted file mode 100644 index 438496ec..00000000 --- a/src/VSNDK.DebugEngine/VSNDK.DebugEngine.csproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {59A7B188-E307-4495-A3AF-4ED76B086A87} - Library - Properties - VSNDK.DebugEngine - VSNDK.DebugEngine - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - True - - - True - - - True - - - True - - - - - - - - - - - - - - False - ..\..\..\..\..\..\..\Program Files\Microsoft Visual Studio 2010 SDK\VisualStudioIntegration\Common\Assemblies\v2.0\Microsoft.VisualStudio.Debugger.Interop.10.0.dll - - - False - ..\..\..\..\..\Microsoft.VisualStudio.Debugger.InteropA.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {CC7B28E0-CB31-44F7-A380-E7072F670F38} - GDBParser - - - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D} - VSNDK.Package - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.DebugEngine/VSNDK.DebugEngine.csproj.user b/src/VSNDK.DebugEngine/VSNDK.DebugEngine.csproj.user deleted file mode 100644 index 59536a59..00000000 --- a/src/VSNDK.DebugEngine/VSNDK.DebugEngine.csproj.user +++ /dev/null @@ -1,7 +0,0 @@ - - - - Program - C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe - - \ No newline at end of file diff --git a/src/VSNDK.Package.Test/DebugTokenDataTestClass.cs b/src/VSNDK.Package.Test/DebugTokenDataTestClass.cs deleted file mode 100644 index 8fc1d0de..00000000 --- a/src/VSNDK.Package.Test/DebugTokenDataTestClass.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using RIM.VSNDK_Package.DebugToken.Model; -using Microsoft.Win32; - -namespace VSNDK.Package.Test -{ - [TestFixture] - public class DebugTokenDataTestClass - { - private DebugTokenData DebugTokenObject; - - /// - /// Setup for testing - /// - [SetUp] - public void Setup() - { - /// Create Object - DebugTokenObject = new RIM.VSNDK_Package.DebugToken.Model.DebugTokenData(); - - /// Set Paths - This would normally be done by the creation of the package. - RegistryKey rkHKCU = Registry.CurrentUser; - RegistryKey rkNDKPath = null; - string qnx_target = ""; - string qnx_host = ""; - - rkNDKPath = rkHKCU.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - qnx_host = rkNDKPath.GetValue("NDKHostPath").ToString(); - qnx_target = rkNDKPath.GetValue("NDKHostPath").ToString(); - - string qnx_config = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK"; - - System.Environment.SetEnvironmentVariable("QNX_TARGET", qnx_target); - System.Environment.SetEnvironmentVariable("QNX_HOST", qnx_host); - System.Environment.SetEnvironmentVariable("QNX_CONFIGURATION", qnx_config); - - string ndkpath = string.Format(@"{0}/usr/bin;{1}\bin;{0}/usr/qde/eclipse/jre/bin;", qnx_host, qnx_config) + System.Environment.GetEnvironmentVariable("PATH"); - System.Environment.SetEnvironmentVariable("PATH", ndkpath); - } - - /// - /// Test for constructor - /// - [TestCase] - public void DebugTokenDataConstructorTest() - { - /// Verify Test Case - Assert.IsNotNull(DebugTokenObject); - } - - /// - /// Test what happens when Signing Certificate is unset. - /// - [TestCase] - public void CreateDebugToken_NoCert_Test() - { - /// Initialize Test Case - DebugTokenObject.CertPath = ""; - bool result = DebugTokenObject.createDebugToken(); - - /// Verify Test Case - Assert.IsFalse(result); - } - - /// - /// Test what happens when an invalid Key Store Password is sent - /// - [TestCase] - public void CreateDebugToken_InvalidKeyStore_Test() - { - /// Initialize Test Case - DebugTokenObject.KeyStorePassword = "invalid"; - bool result = DebugTokenObject.createDebugToken(); - - /// Verify Test Case - Assert.IsFalse(result); - } - - /// - /// Test what happens when an invalid Signing certificate path is sent - /// - [TestCase] - public void CreateDebugToken_InvalidCertPath_Test() - { - /// Initialize Test Case - DebugTokenObject.CertPath = @"C:\"; - bool result = DebugTokenObject.createDebugToken(); - - /// Verify Test Case - Assert.IsFalse(result); - } - - /// - /// Test what happens when an invalid Device PIN is sent - /// - [TestCase] - public void CreateDebugToken_InvalidDevicePIN_Test() - { - /// Initialize Test Case - DebugTokenObject.DevicePIN = "error"; - bool result = DebugTokenObject.createDebugToken(); - - /// Verify Test Case - Assert.IsFalse(result); - } - - /// - /// Test success test - /// - [TestCase] - public void CreateDebugToken_Success_Test() - { - - bool result = DebugTokenObject.createDebugToken(); - - /// Verify Test Case - Assert.IsTrue(result); - - } - - /// - /// Test what happens when DeviceID is empty - /// - [TestCase] - public void getDevicePin_EmptyDeviceID_Test() - { - /// Initialize Test Case - DebugTokenObject.DeviceIP = ""; - bool result = DebugTokenObject.getDeviceInfo(); - - /// Verify Test Case - Assert.IsFalse(result); - } - - /// - /// Test what happens when a successful command is run - /// - [TestCase] - public void getDevicePin_Success_Test() - { - /// Initialize Test Case - bool result = DebugTokenObject.getDeviceInfo(); - - /// Verify Test Case - Assert.IsTrue(result); - } - - /// - /// Test what happens when an invalid password is sent - /// - [TestCase] - public void getDevicePin_InvalidPassword_Test() - { - /// Initialize Test Case - DebugTokenObject.DevicePassword = "error"; - bool result = DebugTokenObject.getDeviceInfo(); - - /// Verify Test Case - Assert.IsFalse(result); - } - - /// - /// Test what happens when an invalid Device IP is sent - /// - [TestCase] - public void getDevicePin_InvalidDeviceIP_Test() - { - /// Initialize Test Case - DebugTokenObject.DeviceIP = "1.1.1.1"; - bool result = DebugTokenObject.getDeviceInfo(); - - /// Verify Test Case - Assert.IsFalse(result); - } - } -} diff --git a/src/VSNDK.Package.Test/Properties/AssemblyInfo.cs b/src/VSNDK.Package.Test/Properties/AssemblyInfo.cs deleted file mode 100644 index 02fcb1a5..00000000 --- a/src/VSNDK.Package.Test/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("VSNDK.Package.Test")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("VSNDK.Package.Test")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("857773c8-9090-43d9-b73e-bee08a70cb78")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/VSNDK.Package.Test/SettingsDataTests.cs b/src/VSNDK.Package.Test/SettingsDataTests.cs deleted file mode 100644 index 89f80ddb..00000000 --- a/src/VSNDK.Package.Test/SettingsDataTests.cs +++ /dev/null @@ -1,641 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using RIM.VSNDK_Package.Settings.Models; -using RIM.VSNDK_Package; -using Microsoft.Win32; -using System.Collections; -using System.IO; -using System.Xml; -using System.Windows.Data; - -namespace VSNDK.Package.Test -{ - [TestFixture] - class SettingsDataTests - { - private SettingsData settingsDataObject; - - /// - /// Setup for testing - /// - [TestFixtureSetUp] - public void TFSetup() - { - /// Create Object - settingsDataObject = new SettingsData(); - - /// Backup NDK Entries - string[] dirPaths = new string[2]; - dirPaths[0] = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\"; - dirPaths[1] = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\"; - - for (int i = 0; i < 2; i++) - { - if (!Directory.Exists(dirPaths[i])) - continue; - - string[] filePaths = Directory.GetFiles(dirPaths[i], "*.xml"); - - foreach (string file in filePaths) - { - try - { - File.Move(file, file.Replace(".xml", ".tmp")); - } - catch - { - break; - } - } - } - } - - - /// - /// Setup for testing - /// - [TestFixtureTearDown] - public void TFTearDown() - { - /// Backup NDK Entries - string[] dirPaths = new string[2]; - dirPaths[0] = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\"; - dirPaths[1] = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\"; - - for (int i = 0; i < 2; i++) - { - if (!Directory.Exists(dirPaths[i])) - continue; - - string[] filePaths = Directory.GetFiles(dirPaths[i], "*.tmp"); - - foreach (string file in filePaths) - { - try - { - File.Move(file, file.Replace(".tmp", ".xml")); - } - catch - { - break; - } - } - } - } - - - /// - /// Test function with key values not set. - /// - [TestCase] - public void GetDeviceInfoTest_KeyValuesNotSet() - { - /// Setup - settingsDataObject.DeviceIP = ""; - settingsDataObject.DevicePassword = ""; - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - - key.DeleteValue("device_password", false); - key.DeleteValue("device_IP", false); - } - } - - settingsDataObject.getDeviceInfo(); - - Assert.IsNullOrEmpty(settingsDataObject.DeviceIP, "Device IP is not empty or null, " + settingsDataObject.DeviceIP); - Assert.IsNullOrEmpty(settingsDataObject.DevicePassword, "Device Password is not empty or null, " + settingsDataObject.DevicePassword); - } - - /// - /// Test function with keys set. - /// - [TestCase] - public void GetDeviceInfoTest_KeyValuesSet() - { - string ipAddr = "127.0.0.1"; - string password = "password"; - - /// Setup - settingsDataObject.DeviceIP = ""; - settingsDataObject.DevicePassword = ""; - - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - key.SetValue("device_password", GlobalFunctions.Encrypt(password), RegistryValueKind.String); - key.SetValue("device_IP", ipAddr, RegistryValueKind.String); - } - } - - settingsDataObject.getDeviceInfo(); - - Assert.IsTrue(settingsDataObject.DeviceIP == ipAddr , "Device IP value is not equal to test value, " + ipAddr + "!= " + settingsDataObject.DeviceIP); - Assert.IsTrue(settingsDataObject.DevicePassword == password, "Device Password value is not equal to test value, " + password + " != " + settingsDataObject.DevicePassword); - } - - /// - /// Test function to set device info - /// - [TestCase] - public void SetDeviceInfoTest() - { - string deviceIP = "127.0.0.1"; - string devicePassword = "password"; - - /// Setup - settingsDataObject.DeviceIP = deviceIP; - settingsDataObject.DevicePassword = devicePassword; - - settingsDataObject.setDeviceInfo(); - - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - Assert.IsTrue(deviceIP == key.GetValue("device_IP").ToString(), "Device IP value is not equal to test value, " + deviceIP + "!= " + key.GetValue("device_IP").ToString()); - Assert.IsTrue(devicePassword == GlobalFunctions.Decrypt(key.GetValue("device_password").ToString()), "Device Password value is not equal to test value, " + devicePassword + " != " + GlobalFunctions.Decrypt(key.GetValue("device_password").ToString())); - } - } - - } - - /// - /// Test function with key value not set - /// - [TestCase] - public void GetSimulatorInfoTest_KeyValuesNotSet() - { - /// Setup - settingsDataObject.SimulatorIP = ""; - settingsDataObject.SimulatorPassword = ""; - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - - key.DeleteValue("simulator_password", false); - key.DeleteValue("simulator_IP", false); - } - } - - settingsDataObject.getSimulatorInfo(); - - Assert.IsNullOrEmpty(settingsDataObject.SimulatorIP, "Simulator IP is not empty or null, " + settingsDataObject.SimulatorIP); - Assert.IsNullOrEmpty(settingsDataObject.SimulatorPassword, "Simulator Password is not empty or null, " + settingsDataObject.SimulatorPassword); - } - - /// - /// Test function with key values set - /// - [TestCase] - public void GetSimulatorInfoTest_KeyValuesSet() - { - string ipAddr = "127.0.0.1"; - string password = "password"; - - /// Setup - settingsDataObject.SimulatorIP = ""; - settingsDataObject.SimulatorPassword = ""; - - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - key.SetValue("simulator_password", GlobalFunctions.Encrypt(password), RegistryValueKind.String); - key.SetValue("simulator_IP", ipAddr, RegistryValueKind.String); - } - } - - settingsDataObject.getSimulatorInfo(); - - Assert.IsTrue(settingsDataObject.SimulatorIP == ipAddr , "Simulator IP value is not equal to test value, " + ipAddr + "!= " + settingsDataObject.SimulatorIP); - Assert.IsTrue(settingsDataObject.SimulatorPassword == password, "Simulator Password value is not equal to test value, " + password + " != " + settingsDataObject.SimulatorPassword); - } - - /// - /// Test function to set simulator info - /// - [TestCase] - public void SetSimulatorInfoTest() - { - string simulatorIP = "127.0.0.1"; - string simulatorPassword = "password"; - - /// Setup - settingsDataObject.SimulatorIP = simulatorIP; - settingsDataObject.SimulatorPassword = simulatorPassword; - - settingsDataObject.setSimulatorInfo(); - - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - Assert.IsTrue(simulatorIP == key.GetValue("simulator_IP").ToString(), "Simulator IP value is not equal to test value, " + simulatorIP + "!= " + key.GetValue("simulator_IP").ToString()); - Assert.IsTrue(simulatorPassword == GlobalFunctions.Decrypt(key.GetValue("simulator_password").ToString()), "Simulator Password value is not equal to test value, " + simulatorPassword + " != " + GlobalFunctions.Decrypt(key.GetValue("simulator_password").ToString())); - } - } - - } - - /// - /// Test function with key value not set - /// - [TestCase] - public void GetNDKPathTest_KeyValuesNotSet() - { - /// Setup - settingsDataObject.HostPath = ""; - settingsDataObject.TargetPath = ""; - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - - key.DeleteValue("NDKHostPath", false); - key.DeleteValue("NDKTargetPath", false); - } - } - - settingsDataObject.getNDKPath(); - - Assert.IsNullOrEmpty(settingsDataObject.HostPath, "Host Path is not empty or null, " + settingsDataObject.HostPath); - Assert.IsNullOrEmpty(settingsDataObject.TargetPath, "Target Path is not empty or null, " + settingsDataObject.TargetPath); - } - - /// - /// Test function with key values set - /// - [TestCase] - public void GetNDKPathTest_KeyValuesSet() - { - string hostPath = @"C:\bbndk_vs\host\"; - string targetPath = @"C:\bbndk_vs\target\"; - - /// Setup - settingsDataObject.HostPath = ""; - settingsDataObject.TargetPath = ""; - - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - key.SetValue("NDKHostPath", hostPath, RegistryValueKind.String); - key.SetValue("NDKTargetPath", targetPath, RegistryValueKind.String); - } - } - - settingsDataObject.getNDKPath(); - - Assert.IsTrue(settingsDataObject.HostPath == hostPath, "Host Path value is not equal to test value, " + hostPath + "!= " + settingsDataObject.HostPath); - Assert.IsTrue(settingsDataObject.TargetPath == targetPath, "Target Path value is not equal to test value, " + targetPath + " != " + settingsDataObject.TargetPath); - } - - /// - /// Test function with valid version number - /// - [TestCase] - public void GetAPINameTest_ValidVersion() - { - string version = "10.2.0.1155"; - string name = "BlackBerry Native SDK 10.2"; - - string result = settingsDataObject.getAPIName(version); - - Assert.IsTrue(result == name, "API Name does not matched expected result., " + result + "!= " + name); - } - - /// - /// Test function with invalid version number - /// - [TestCase] - public void GetAPINameTest_InvalidVersion() - { - string version = "1.1.1.1"; - string name = ""; - - string result = settingsDataObject.getAPIName(version); - - Assert.IsTrue(result == name, "API Name does not matched expected result., " + result + "!= " + name); - } - - /// - /// Test function with no API's - /// - [TestCase] - public void RefreshScreen_NoAPIs() - { - settingsDataObject.RefreshScreen(); - - Assert.IsTrue(settingsDataObject.NDKEntries.Count == 0, "NDK Entries should be empty. "); - } - - /// - /// Test function with a single API in standard folder - /// - [TestCase] - public void RefreshScreen_APIs1() - { - string version = "10.2.0.1155"; - - GenerateXMLFiles(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\", version); - - settingsDataObject.RefreshScreen(); - - Assert.IsTrue(settingsDataObject.NDKEntries.Count == 1, "Number of Entries is unexpected. "); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).HostPath == @"C:/bbndk_vs/host_" + version.Replace('.', '_') + @"/win32/x86", "Host Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).TargetPath == @"C:/bbndk_vs/target_" + version.Replace('.', '_') + @"/win32/qnx6", "Target Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).NDKName == "BlackBerry Native SDK 10.2", "NDK Name is not expected"); - - RemoveXmlFiles(); - } - - /// - /// Test function with a single API in momentics folder - /// - [TestCase] - public void RefreshScreen_APIs2() - { - string version = "10.2.0.1155"; - - GenerateXMLFiles(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\", version); - - settingsDataObject.RefreshScreen(); - - Assert.IsTrue(settingsDataObject.NDKEntries.Count == 1, "Number of Entries is unexpected. "); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).HostPath == @"C:/bbndk_vs/host_" + version.Replace('.', '_') + @"/win32/x86", "Host Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).TargetPath == @"C:/bbndk_vs/target_" + version.Replace('.', '_') + @"/win32/qnx6", "Target Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).NDKName == "BlackBerry Native SDK 10.2", "NDK Name is not expected"); - - RemoveXmlFiles(); - } - - /// - /// Test function with multiple APIs - /// - [TestCase] - public void RefreshScreen_APIs3() - { - string version = "10.2.0.1155"; - string version2 = "10.2.0.1200"; - - GenerateXMLFiles(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\", version2); - GenerateXMLFiles(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\", version); - - settingsDataObject.RefreshScreen(); - - Assert.IsTrue(settingsDataObject.NDKEntries.Count == 2, "Number of Entries is unexpected. "); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).HostPath == @"C:/bbndk_vs/host_" + version.Replace('.', '_') + @"/win32/x86", "Host Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).TargetPath == @"C:/bbndk_vs/target_" + version.Replace('.', '_') + @"/win32/qnx6", "Target Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).NDKName == "BlackBerry Native SDK 10.2", "NDK Name is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(1)).HostPath == @"C:/bbndk_vs/host_" + version2.Replace('.', '_') + @"/win32/x86", "Host Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(1)).TargetPath == @"C:/bbndk_vs/target_" + version2.Replace('.', '_') + @"/win32/qnx6", "Target Path is not expected"); - Assert.IsTrue(((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(1)).NDKName == "BlackBerry Native SDK 10.2", "NDK Name is not expected"); - - RemoveXmlFiles(); - } - - /// - /// Test function for selecting no API - /// - [TestCase] - public void RefreshScreen_SelectedAPI1() - { - string version = "10.2.0.1155"; - string version2 = "10.2.0.1200"; - - GenerateXMLFiles(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\", version2); - GenerateXMLFiles(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\", version); - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - key.SetValue("NDKHostPath", "", RegistryValueKind.String); - key.SetValue("NDKTargetPath", "", RegistryValueKind.String); - } - } - - settingsDataObject.RefreshScreen(); - - Assert.IsTrue(settingsDataObject.NDKEntryClass.HostPath == "", "Host path is not blank"); - Assert.IsTrue(settingsDataObject.NDKEntryClass.TargetPath == "", "Target path is not blank"); - Assert.IsTrue(settingsDataObject.NDKEntryClass.NDKName == "", "NDK name is not blank"); - - RemoveXmlFiles(); - } - - - /// - /// Test function for selecting a single api - /// - [TestCase] - public void RefreshScreen_SelectedAPI2() - { - string version = "10.2.0.1155"; - string version2 = "10.2.0.1200"; - - GenerateXMLFiles(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\", version2); - GenerateXMLFiles(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\", version); - - string keyName = @"Software\BlackBerry\BlackBerryVSPlugin"; - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true)) - { - if (key == null) - { - // Do Nothing - } - else - { - key.SetValue("NDKHostPath", @"C:/bbndk_vs/host_" + version.Replace('.', '_') + @"/win32/x86", RegistryValueKind.String); - key.SetValue("NDKTargetPath", @"C:/bbndk_vs/target_" + version.Replace('.', '_') + @"/win32/qnx6", RegistryValueKind.String); - } - } - - settingsDataObject.RefreshScreen(); - - Assert.IsTrue(settingsDataObject.NDKEntryClass.HostPath == @"C:/bbndk_vs/host_" + version.Replace('.', '_') + @"/win32/x86", "Host path is not " + @"C:/bbndk_vs/host_" + version.Replace('.', '_') + @"/win32/x86"); - Assert.IsTrue(settingsDataObject.NDKEntryClass.TargetPath == @"C:/bbndk_vs/target_" + version.Replace('.', '_') + @"/win32/qnx6", "Target path is not " + @"C:/bbndk_vs/target_" + version.Replace('.', '_') + @"/win32/qnx6"); - Assert.IsTrue(settingsDataObject.NDKEntryClass.NDKName == "BlackBerry Native SDK 10.2", "BlackBerry Native SDK 10.2"); - - RemoveXmlFiles(); - } - - /// - /// Test the setting of the NDK Paths - /// - [TestCase] - public void TC_setNDKPaths() - { - // Initialize Test - string targetPath = ((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).TargetPath; - string hostPath = ((NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0)).HostPath; - string qnx_config = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK"; - - settingsDataObject.NDKEntryClass = (NDKEntryClass)settingsDataObject.NDKEntries.GetItemAt(0); - - RegistryKey regKeyCurrentUser = Registry.CurrentUser; - RegistryKey regKey = regKeyCurrentUser.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - regKey.SetValue("NDKTargetPath", ""); - regKey.SetValue("NDKHostPath", ""); - - // Run Test - settingsDataObject.setNDKPaths(); - - // Validate Test - Assert.IsTrue(regKey.GetValue("NDKHostPath").ToString() == hostPath, "Host path does not match expected result"); - Assert.IsTrue(regKey.GetValue("NDKTargetPath").ToString() == targetPath, "Target path does not match expected result"); - Assert.IsTrue(System.Environment.GetEnvironmentVariable("QNX_TARGET") == targetPath, "QNX_TARGET system variable is not match expected result"); - Assert.IsTrue(System.Environment.GetEnvironmentVariable("QNX_HOST") == hostPath, "QNX_HOST system variable is not match expected result"); - Assert.IsTrue(System.Environment.GetEnvironmentVariable("QNX_CONFIGURATION") == qnx_config, "QNX_CONFIGURATION system variable is not match expected result"); - Assert.IsTrue(System.Environment.GetEnvironmentVariable("PATH").Contains(hostPath), "Path system variable does not contain host path"); - Assert.IsTrue(System.Environment.GetEnvironmentVariable("PATH").Contains(qnx_config), "Path system variable does not contain config path"); - } - - /// - /// Helper function to generate XML Files - /// - /// - private void GenerateXMLFiles(string path, string version) - { - XmlDocument doc = new XmlDocument(); - XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", "no"); - doc.AppendChild(docNode); - - XmlNode sysDefNode = doc.CreateElement("qnxSystemDefinition"); - doc.AppendChild(sysDefNode); - - XmlNode installationNode = doc.CreateElement("installation"); - sysDefNode.AppendChild(installationNode); - - XmlNode baseNode = doc.CreateElement("base"); - baseNode.InnerText = @"C:/bbndk_vs"; - installationNode.AppendChild(baseNode); - - XmlNode hostNode = doc.CreateElement("host"); - hostNode.InnerText = @"C:/bbndk_vs/host_" + version.Replace('.', '_') + @"/win32/x86"; - installationNode.AppendChild(hostNode); - - XmlNode nameNode = doc.CreateElement("name"); - nameNode.InnerText = "BlackBerry Native SDK 10.2"; - installationNode.AppendChild(nameNode); - - XmlNode targetNode = doc.CreateElement("target"); - targetNode.InnerText = @"C:/bbndk_vs/target_" + version.Replace('.', '_') + @"/win32/qnx6"; - installationNode.AppendChild(targetNode); - - XmlNode versionNode = doc.CreateElement("version"); - versionNode.InnerText = version; - installationNode.AppendChild(versionNode); - - XmlNode annotationNode = doc.CreateElement("annotation"); - installationNode.AppendChild(annotationNode); - - XmlNode appInfoNode = doc.CreateElement("appInfo"); - XmlAttribute appInfoAttribute = doc.CreateAttribute("source"); - appInfoAttribute.Value = "p2install"; - appInfoNode.Attributes.Append(appInfoAttribute); - annotationNode.AppendChild(appInfoNode); - - XmlNode dversionNode = doc.CreateElement("detailedVersion"); - dversionNode.InnerText = version; - appInfoNode.AppendChild(dversionNode); - - Directory.CreateDirectory(path); - doc.Save(path + version + ".xml"); - } - - /// - /// Helper function to remove test xml files - /// - private void RemoveXmlFiles() - { - /// Remove NDK Entries - string[] dirPaths = new string[2]; - dirPaths[0] = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + @"bbndk_vs\..\qconfig\"; - dirPaths[1] = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\"; - - for (int i = 0; i < 2; i++) - { - if (!Directory.Exists(dirPaths[i])) - continue; - - string[] filePaths = Directory.GetFiles(dirPaths[i], "*.xml"); - - foreach (string file in filePaths) - { - try - { - File.Delete(file); - } - catch - { - break; - } - } - } - } - - - } -} diff --git a/src/VSNDK.Package.Test/SigningDataTestClass.cs b/src/VSNDK.Package.Test/SigningDataTestClass.cs deleted file mode 100644 index ae30ef85..00000000 --- a/src/VSNDK.Package.Test/SigningDataTestClass.cs +++ /dev/null @@ -1,252 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using RIM.VSNDK_Package.Signing.Models; -using RIM.VSNDK_Package; -using System.IO; -using Microsoft.Win32; - -namespace VSNDK.Package.Test -{ - [TestFixture] - public class SigningData_BackupRestore_TestClass - { - private SigningData _signingData = null; - private string _certName = ""; - private string _certTmpPath = ""; - - /// - /// Setup for testing - /// - [TestFixtureSetUp] - public void TFSetup() - { - /// Create Object - _signingData = new SigningData(); - _certName = "BackupTest.zip"; - _certTmpPath = @"\temp"; - } - - /// - /// Setup for testing - /// - [TestFixtureTearDown] - public void TFTearDown() - { - /// Remove Zip file and unzipped files - File.Delete(_signingData.CertPath + _certName); - Directory.Delete(_signingData.CertPath + _certTmpPath); - } - - /// - /// Test the backup functionality - /// - [TestCase] - public void SigningDataBackupTest() - { - _signingData.Backup(_certName); - Assert.True(File.Exists(_signingData.CertPath + _certName)); - } - - - /// - /// Test the restore functionality - /// - [TestCase] - public void SigningDataRestoreTest() - { - string certName = "BackupTest.zip"; - _signingData.CertPath = _signingData.CertPath + @"temp\"; - _signingData.Restore(certName); - Assert.True(Directory.Exists(_signingData.CertPath), "Restore directory not created"); - - DirectoryInfo di = new DirectoryInfo(_signingData.CertPath); - FileInfo[] fileList = di.GetFiles(); - - foreach (FileInfo file in fileList) - { - FileInfo file2 = new FileInfo(_signingData.CertPath + @"..\" + file.Name); - FileAssert.AreEqual(file, file2, "File isn't the same: " + file.Name); - } - } - } - - [TestFixture] - public class SigningData_Register_TestClass - { - private SigningData _signingData = null; - private string _cskPassword = ""; - private string _certName = ""; - private string _certTmpName = ""; - - /// - /// Setup for testing - /// - [TestFixtureSetUp] - public void TFSetup() - { - /// Create Object - _signingData = new SigningData(); - - _certName = @"/bbidtoken.csk"; - _certTmpName = @"/bbidtoken.csk.bak"; - - if (_signingData.Registered) - { - /// Backup CSK Password - RegistryKey rkHKCU = Registry.CurrentUser; - RegistryKey rkCDKPass = null; - rkCDKPass = rkHKCU.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - _cskPassword = GlobalFunctions.Decrypt(rkCDKPass.GetValue("CSKPass").ToString()); - rkCDKPass.Close(); - rkHKCU.Close(); - - /// Backup CSK File.. - File.Copy(_signingData.CertPath + _certName, _signingData.CertPath + _certTmpName); - - /// Remove Key so we can register again. - _signingData.UnRegister(); - - /// Backup CSK File.. - File.Copy(_signingData.CertPath + _certTmpName, _signingData.CertPath + _certName); - } - else - { - Assert.Ignore(); - } - } - - /// - /// Setup for testing - /// - [TestFixtureTearDown] - public void TFTearDown() - { - /// Remove backup file - File.Delete(_signingData.CertPath + _certTmpName); - } - - /// - /// Test the unregister function - All Registered - /// - [TestCase] - public void SigningDataRegisterTest() - { - string password = ""; - - /// Check success Fail - _signingData.Register("Test", _cskPassword); - - /// Check return value from remote call - StringAssert.IsMatch("CSK file deleted.\n", _signingData.Messages, "Return value from command is not as expected. " + _signingData.Messages); - - /// Check return value for errors - StringAssert.DoesNotMatch("", _signingData.Errors, "Errors have been regturned from remote call. " + _signingData.Errors); - - /// Check to see that the cert file was removed - Assert.True(File.Exists(_signingData.CertPath + @"/author.p12"), "Certificate File is not present"); - - /// Check to see that the csk file was removed - Assert.True(File.Exists(_signingData.CertPath + @"/bbidtoken.csk"), "CSK File is not present."); - - /// Get CSK Password - RegistryKey rkHKCU = Registry.CurrentUser; - RegistryKey rkCDKPass = null; - rkCDKPass = rkHKCU.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - password = GlobalFunctions.Decrypt(rkCDKPass.GetValue("CSKPass").ToString()); - StringAssert.IsMatch(_cskPassword, password, "Password is not a match " + _cskPassword + " != " + password); - rkCDKPass.Close(); - rkHKCU.Close(); - } - - } - - [TestFixture] - public class SigningData_UnRegister_TestClass - { - private SigningData _signingData = null; - private string _cskPassword = ""; - private string _certName = ""; - private string _certTmpName = ""; - - /// - /// Setup for testing - /// - [TestFixtureSetUp] - public void TFSetup() - { - /// Create Object - _signingData = new SigningData(); - - _certName = @"/bbidtoken.csk"; - _certTmpName = @"/bbidtoken.csk.bak"; - - if (_signingData.Registered) - { - /// Backup CSK Password - RegistryKey rkHKCU = Registry.CurrentUser; - RegistryKey rkCDKPass = null; - rkCDKPass = rkHKCU.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - _cskPassword = rkCDKPass.GetValue("CSKPass").ToString(); - rkCDKPass.Close(); - rkHKCU.Close(); - - /// Backup CSK File.. - File.Copy(_signingData.CertPath + _certName, _signingData.CertPath + _certTmpName); - } - else - { - Assert.Ignore(); - } - } - - /// - /// Setup for testing - /// - [TestFixtureTearDown] - public void TFTearDown() - { - /// Backup CSK File.. - File.Copy(_signingData.CertPath + _certTmpName, _signingData.CertPath + _certName); - - /// Check success Fail - _signingData.Register("Test Company", _cskPassword); - - /// Remove backup file - File.Delete(_signingData.CertPath + _certTmpName); - } - - /// - /// Test the unregister function - All Registered - /// - [TestCase] - public void SigningDataUnregisterTest() - { - /// Check success Fail - _signingData.UnRegister(); - - /// Check return value from remote call - StringAssert.IsMatch("CSK file deleted.\n", _signingData.Messages, "Return value from command is not as expected. " + _signingData.Messages); - - /// Check return value for errors - StringAssert.DoesNotMatch("", _signingData.Errors, "Errors have been regturned from remote call. " + _signingData.Errors); - - /// Check to see that the cert file was removed - Assert.False(File.Exists(_signingData.CertPath + @"/author.p12"), "Certificate File is still present"); - - /// Check to see that the csk file was removed - Assert.False(File.Exists(_signingData.CertPath + @"/bbidtoken.csk"), "CSK File is still present."); - - /// Get CSK Password - RegistryKey rkHKCU = Registry.CurrentUser; - RegistryKey rkCDKPass = null; - rkCDKPass = rkHKCU.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - StringAssert.IsMatch("", GlobalFunctions.Decrypt(rkCDKPass.GetValue("CSKPass").ToString()), "Password is not set to blank"); - rkCDKPass.Close(); - rkHKCU.Close(); - } - - } -} diff --git a/src/VSNDK.Package.Test/UpdateManagerDataTestClass.cs b/src/VSNDK.Package.Test/UpdateManagerDataTestClass.cs deleted file mode 100644 index fcc16bf8..00000000 --- a/src/VSNDK.Package.Test/UpdateManagerDataTestClass.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using RIM.VSNDK_Package.UpdateManager.Model; -using RIM.VSNDK_Package; -using System.IO; -using Microsoft.Win32; - -namespace VSNDK.Package.Test -{ - [TestFixture] - class UpdateManagerDataTestClass - { - private UpdateManagerData updateManagerDataObject; - - /// - /// Setup for testing - /// - [TestFixtureSetUp] - public void TF_Setup() - { - /// Create Object - updateManagerDataObject = new UpdateManagerData(); - - } - - [TestFixtureTearDown] - public void TF_TearDown() - { - - } - - /// - /// Test GetAPILevel with a bad version expecting a no match - /// - [TestCase] - public void TC_GetAPILevel_NoMatch() - { - /// Initialize Test - string version = "1.0.0.0"; - string expectedResult = ""; - - /// Run Test - string result = updateManagerDataObject.GetAPILevel(version); - - /// Validate Test - Assert.IsTrue(result == expectedResult, "Expected result is not empty, " + result); - } - - /// - /// Test GetAPILevel with a valid version expecting the correct API Level - /// - [TestCase] - public void TC_GetAPILevel_Match() - { - /// Initialize Test - string version = "10.2.0"; - string expectedResult = "10.2.0.1155"; - - /// Run Test - string result = updateManagerDataObject.GetAPILevel(version); - - /// Validate Test - Assert.IsTrue(result == expectedResult, "Expected result does not match, " + result + " != " + expectedResult); - } - - /// - /// Test IsRuntimeInstalled with a invalid version expecting blank - /// - [TestCase] - public void TC_IsRuntimeInstalled_NoMatch() - { - /// Initialize Test - string version = "10.2.0.1197"; - - /// Run Test - bool result = updateManagerDataObject.IsRuntimeInstalled(version); - - /// Validate Test - Assert.IsFalse(result, "Result should be false."); - } - - /// - /// Test IsRuntimeInstalled with a invalid version expecting blank - /// - [TestCase] - public void TC_IsRuntimeInstalled_Match() - { - /// Initialize Test - string version = "10.2.0.1197"; - Directory.CreateDirectory(GlobalFunctions.bbndkPathConst + @"\runtime_" + version.Replace(".", "_")); - - /// Run Test - bool result = updateManagerDataObject.IsRuntimeInstalled(version); - - /// Validate Test - Assert.IsTrue(result, "Result should be true."); - - ///Clean Up Test - Directory.Delete(GlobalFunctions.bbndkPathConst + @"\runtime_" + version.Replace(".", "_")); - } - - /// - /// Test getCurrentAPIVersion when an API Version is not set. - /// - [TestCase] - public void TC_getCurrentAPIVersion_Unset() - { - /// Initialize Test - RegistryKey regKeyCurrentUser = Registry.CurrentUser; - RegistryKey regKey = regKeyCurrentUser.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - regKey.SetValue("NDKTargetPath", ""); - regKey.Close(); - regKeyCurrentUser.Close(); - - /// Run Test - string result = updateManagerDataObject.getCurrentAPIVersion(); - - /// Validate Test - Assert.IsTrue(result == "", "Return value doesn't match expected result. " + result + " != " + ""); - - } - - /// - /// Test getCurrentAPIVersion when an API Version is set. - /// - [TestCase] - public void TC_getCurrentAPIVersion_Set() - { - /// Initialize Test - string version = "10.2.0.1155"; - RegistryKey regKeyCurrentUser = Registry.CurrentUser; - RegistryKey regKey = regKeyCurrentUser.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - regKey.SetValue("NDKTargetPath", @"C:/bbndk_vs/target_" + version.Replace('.', '_') + "/qnx6"); - - /// Run Test - string result = updateManagerDataObject.getCurrentAPIVersion(); - - /// Validate Test - Assert.IsTrue(result == version, "Return value doesn't match expected result. " + result + " != " + version); - - /// Clean Up - regKey.SetValue("NDKTargetPath", ""); - regKey.Close(); - regKeyCurrentUser.Close(); - } - - - } -} diff --git a/src/VSNDK.Package.Test/VSNDK.Package.Test.csproj b/src/VSNDK.Package.Test/VSNDK.Package.Test.csproj deleted file mode 100644 index 89f9ca10..00000000 --- a/src/VSNDK.Package.Test/VSNDK.Package.Test.csproj +++ /dev/null @@ -1,67 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D} - Library - Properties - VSNDK.Package.Test - VSNDK.Package.Test - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D} - VSNDK.Package - - - - - \ No newline at end of file diff --git a/src/VSNDK.Package/ControlDebugEngine.cs b/src/VSNDK.Package/ControlDebugEngine.cs deleted file mode 100644 index 0398c696..00000000 --- a/src/VSNDK.Package/ControlDebugEngine.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace VSNDK.Package -{ - public static class ControlDebugEngine - { - public static bool isDebugEngineRunning = false; - } -} diff --git a/src/VSNDK.Package/DebugToken/DebugTokenDialog.xaml b/src/VSNDK.Package/DebugToken/DebugTokenDialog.xaml deleted file mode 100644 index ef1720f5..00000000 --- a/src/VSNDK.Package/DebugToken/DebugTokenDialog.xaml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Package/Signing/RegistrationWindow.xaml.cs b/src/VSNDK.Package/Signing/RegistrationWindow.xaml.cs deleted file mode 100644 index a07778a3..00000000 --- a/src/VSNDK.Package/Signing/RegistrationWindow.xaml.cs +++ /dev/null @@ -1,86 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using RIM.VSNDK_Package.Signing.Models; -using System.IO; -using System.ComponentModel; - -namespace RIM.VSNDK_Package.Signing -{ - /// - /// Interaction logic for RegistrationWindow.xaml - /// - public partial class RegistrationWindow : Window - { - private SigningData signingData = null; - - /// - /// RegistrationWindow Constructor - /// - public RegistrationWindow() - { - InitializeComponent(); - - signingData = new SigningData(); - gridMain.DataContext = signingData; - } - - /// - /// Perform actions on the OK button click - /// - /// - /// - private void btnOk_Click(object sender, RoutedEventArgs e) - { - if (!signingData.Register(tbAuthor.Text, tbPassword.Password)) - { - MessageBox.Show(signingData.Errors, "Registration Window", MessageBoxButton.OK, MessageBoxImage.Exclamation, MessageBoxResult.OK); - signingData.Errors = null; - e.Handled = true; - return; - } - else if (!string.IsNullOrEmpty(signingData.Messages)) - { - signingData.Messages = signingData.Messages.Replace("CSK", "BB ID Token"); - MessageBox.Show(signingData.Messages, "Registration Window", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK); - signingData.Messages = null; - } - - signingData.Register("", ""); - - DialogResult = true; - } - - /// - /// Perform actions on close of dialog. - /// - /// - protected override void OnClosing(CancelEventArgs e) - { - signingData.CleanUp(); - } - } -} \ No newline at end of file diff --git a/src/VSNDK.Package/Signing/SigningDialog.xaml b/src/VSNDK.Package/Signing/SigningDialog.xaml deleted file mode 100644 index d4a092f6..00000000 --- a/src/VSNDK.Package/Signing/SigningDialog.xaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Package/VSNDK.PackagePackage.cs b/src/VSNDK.Package/VSNDK.PackagePackage.cs deleted file mode 100644 index 9bcbeee5..00000000 --- a/src/VSNDK.Package/VSNDK.PackagePackage.cs +++ /dev/null @@ -1,1453 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.InteropServices; -using System.ComponentModel.Design; -using Microsoft.Win32; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.VCProjectEngine; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.OLE.Interop; -using Microsoft.VisualStudio.Shell; -using System.Xml; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using EnvDTE; -using System.Windows.Forms; -using VSNDK.Package; -using EnvDTE80; -using System.Text.RegularExpressions; -using System.Collections.Specialized; -using System.Security.Cryptography; -using System.Text; -using RIM.VSNDK_Package.UpdateManager.Model; - -namespace RIM.VSNDK_Package -{ - /// - /// Class to store Installed APIs - /// - public class APIClass - { - public string Name { get; set; } - public string HostName { get; set; } - public string TargetName { get; set; } - public string Version { get; set; } - - public APIClass(string name, string hostName, string targetName, string version) - { - Name = name; - Version = version; - HostName = hostName; - TargetName = targetName; - } - } - - /// - /// Class to store API Targets - /// - public class APITargetClass - { - public string TargetName { get; set; } - public string TargetDescription { get; set; } - public string TargetVersion { get; set; } - public string LatestVersion { get; set; } - public int IsInstalled { get; set; } - public bool IsUpdate { get; set; } - public bool IsBeta { get; set; } - - public string InstalledVisibility - { - get { return IsInstalled > 0 ? "visible" : "collapsed"; } - } - - public string AvailableVisibility - { - get { return IsInstalled == 0 ? "visible" : "collapsed"; } - } - - public string UpdateVisibility - { - get { return IsUpdate ? "visible" : "collapsed"; } - } - - public string NoUpdateVisibility - { - get { return IsUpdate ? "collapsed" : "visible"; } - } - - public APITargetClass(string name, string description, string version) - { - TargetName = name; - TargetDescription = description; - TargetVersion = version; - LatestVersion = version; - IsInstalled = 0; - IsUpdate = false; - IsBeta = false; - } - } - - /// - /// Class to store Simulators - /// - public class SimulatorsClass - { - public string APILevel { get; set; } - public string TargetVersion { get; set; } - public bool LatestVersion { get; set; } - public bool IsInstalled { get; set; } - - public string TargetVersionText - { - get { return LatestVersion ? "Latest Version " + TargetVersion : TargetVersion; } - } - - public string InstalledVersionText - { - get { return "BlackBerry Native SDK Simulator (" + TargetVersion + ")"; } - } - - public string LabelAPIVersion - { - get { return LatestVersion ? "visible" : "collapsed"; } - } - - public string SubAPIVersion - { - get { return LatestVersion ? "collapsed" : "visible"; } - } - - public string LabelAPIVersionText - { - get - { - return "Simulator for BlackBerry Native SDK " + APILevel; - } - } - - public string AvailableVisibility - { - get { return IsInstalled ? "visible" : "collapsed"; } - } - - public string InstalledVisibility - { - get { return IsInstalled ? "collapsed" : "visible"; } - } - - public SimulatorsClass(string version, string apilevel, bool latest) - { - TargetVersion = version; - LatestVersion = latest; - APILevel = apilevel; - IsInstalled = false; - } - } - - /// - /// Class to retrieve Installed API List - /// - public class InstalledAPIListSingleton - { - private static InstalledAPIListSingleton _instance; - public List _installedAPIList; - - /// - /// Constructor - /// - private InstalledAPIListSingleton() - { - GetInstalledAPIList(); - } - - /// - /// Public property to retrieve the singleton instance - /// - public static InstalledAPIListSingleton Instance - { - get - { - if (_instance == null) - { - _instance = new InstalledAPIListSingleton(); - } - return _instance; - } - } - - /// - /// Get list of installed APIs - /// - /// - private void GetInstalledAPIList() - { - try - { - _installedAPIList = new List(); - - string dirPaths = GlobalFunctions.bbndkPathConst + @"\..\qconfig\"; - - string[] filePaths = Directory.GetFiles(dirPaths, "*.xml"); - foreach (string file in filePaths) - { - try - { - XmlDocument xmlDoc = new XmlDocument(); - xmlDoc.Load(file); - XmlNodeList name = xmlDoc.GetElementsByTagName("name"); - XmlNodeList version = xmlDoc.GetElementsByTagName("version"); - XmlNodeList hostpath = xmlDoc.GetElementsByTagName("host"); - XmlNodeList targetpath = xmlDoc.GetElementsByTagName("target"); - - APIClass aclass = new APIClass(name.Item(0).InnerText, hostpath.Item(0).InnerText, targetpath.Item(0).InnerText, version.Item(0).InnerText); - _installedAPIList.Add(aclass); - } - catch - { - break; - } - } - } - catch (Exception ex) - { - - } - } - - - } - - - /// - /// Class to retrieve Installed API List - /// - public class InstalledNDKListSingleton - { - private static InstalledNDKListSingleton _instance; - public List _installedNDKList; - - /// - /// Constructor - /// - private InstalledNDKListSingleton() - { - GetInstalledNDKList(); - } - - /// - /// Public property to retrieve the singleton instance - /// - public static InstalledNDKListSingleton Instance - { - get - { - if (_instance == null) - { - _instance = new InstalledNDKListSingleton(); - } - return _instance; - } - } - - /// - /// Get list of installed APIs - /// - /// - private void GetInstalledNDKList() - { - try - { - _installedNDKList = new List(); - - string dirPaths = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\"; - - string[] filePaths = Directory.GetFiles(dirPaths, "*.xml"); - foreach (string file in filePaths) - { - try - { - XmlDocument xmlDoc = new XmlDocument(); - xmlDoc.Load(file); - XmlNodeList name = xmlDoc.GetElementsByTagName("name"); - XmlNodeList version = xmlDoc.GetElementsByTagName("version"); - XmlNodeList hostpath = xmlDoc.GetElementsByTagName("host"); - XmlNodeList targetpath = xmlDoc.GetElementsByTagName("target"); - - APIClass aclass = new APIClass(name.Item(0).InnerText, hostpath.Item(0).InnerText, targetpath.Item(0).InnerText, version.Item(0) == null ? "2.1.0" : version.Item(0).InnerText); - _installedNDKList.Add(aclass); - } - catch - { - break; - } - } - } - catch (Exception ex) - { - - } - } - } - - /// - /// Class to retrieve API Target List - /// - public class APITargetListSingleton - { - private static APITargetListSingleton _instance; - public List _tempAPITargetList; - private string _error = ""; - - private APITargetListSingleton() - { - GetAvailableAPIList(); - } - - /// - /// Retrieve list of API's from - /// - /// - private void GetAvailableAPIList() - { - if (GlobalFunctions.isOnline()) - { - System.Diagnostics.Process p = new System.Diagnostics.Process(); - System.Diagnostics.ProcessStartInfo startInfo = p.StartInfo; - startInfo.UseShellExecute = false; - startInfo.CreateNoWindow = true; - startInfo.RedirectStandardError = true; - startInfo.RedirectStandardOutput = true; - p.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(ErrorDataReceived); - p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(APIListDataReceived); - - - /// Get Device PIN - startInfo.FileName = "cmd.exe"; - startInfo.Arguments = string.Format(@"/C " + GlobalFunctions.bbndkPathConst + @"\eclipsec --list"); - - try - { - _tempAPITargetList = new List(); - - p.Start(); - p.BeginErrorReadLine(); - p.BeginOutputReadLine(); - p.WaitForExit(); - p.Close(); - } - catch (Exception e) - { - System.Diagnostics.Debug.WriteLine(startInfo.Arguments); - System.Diagnostics.Debug.WriteLine(e.Message); - } - } - - } - - /// - /// On Data Received event handler - /// - /// - /// - private void APIListDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) - { - string name = ""; - string description = ""; - string version = ""; - APITargetClass api = null; - - if (e.Data != null) - { - if ((e.Data.ToLower().Contains("error")) || (_error != "")) - { - _error = _error + e.Data; - } - else if ((e.Data.Contains("Location:")) || (e.Data.Contains("Available"))) - { - // Do Nothing - } - else - { - version = e.Data.Substring(0, e.Data.LastIndexOf(" - ")); - name = e.Data.Substring(e.Data.LastIndexOf(" - ") + 3); - description = "Device Support Unknown."; - - - api = _tempAPITargetList.Find(i => i.TargetName == name); - - if (api == null) - { - api = new APITargetClass(name, description, version); - api.IsInstalled = IsAPIInstalled(version, ""); - _tempAPITargetList.Add(api); - } - else - { - switch (api.IsInstalled) - { - case 0: - api.TargetVersion = version; - api.LatestVersion = version; - break; - case 1: - api.IsUpdate = true; - api.LatestVersion = version; - break; - case 2: - api.TargetVersion = version; - api.LatestVersion = "NDK"; - break; - } - } - - api.IsBeta = name.Contains("Beta"); - - } - } - } - - /// - /// Check to see if API is installed - /// - /// Check version number - /// Check API name - /// true if installed - private int IsAPIInstalled(string version, string name) - { - int success = 0; - - /// Check for 2.1 version - if (version.StartsWith("2.1.0")) - version = "2.1.0"; - - if (InstalledAPIListSingleton.Instance._installedAPIList != null) - { - APIClass result = InstalledAPIListSingleton.Instance._installedAPIList.Find(i => i.Version.Contains(version)); - - if (result != null) - { - success = 1; - } - } - - if (InstalledNDKListSingleton.Instance._installedNDKList != null) - { - APIClass result = InstalledNDKListSingleton.Instance._installedNDKList.Find(i => i.Version.Contains(version)); - - if (result != null) - { - success = 2; - } - } - - return success; - } - - /// - /// On Error received event handler - /// - /// - /// - private void ErrorDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) - { - if (e.Data != null) - { - System.Diagnostics.Debug.WriteLine(e.Data); - - MessageBox.Show(e.Data); - } - } - - /// - /// Public interface for getting the singleton instance - /// - public static APITargetListSingleton Instance - { - get - { - if (_instance == null) - { - _instance = new APITargetListSingleton(); - } - return _instance; - } - } - } - - /// - /// Class to retrieve Installed API List - /// - public class SimulatorListSingleton - { - private static SimulatorListSingleton _instance; - public List _simulatorList; - private string _error = ""; - - /// - /// Constructor - /// - private SimulatorListSingleton() - { - GetSimulatorList(); - } - - /// - /// Public property to retrieve the singleton instance - /// - public static SimulatorListSingleton Instance - { - get - { - if (_instance == null) - { - _instance = new SimulatorListSingleton(); - } - return _instance; - } - } - - /// - /// Retrieve list of Available Simulators - /// - /// - private void GetSimulatorList() - { - if (GlobalFunctions.isOnline()) - { - System.Diagnostics.Process p = new System.Diagnostics.Process(); - System.Diagnostics.ProcessStartInfo startInfo = p.StartInfo; - startInfo.UseShellExecute = false; - startInfo.CreateNoWindow = true; - startInfo.RedirectStandardError = true; - startInfo.RedirectStandardOutput = true; - p.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(ErrorDataReceived); - p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(SimulatorListDataReceived); - - /// Get Device PIN - startInfo.FileName = "cmd.exe"; - startInfo.Arguments = string.Format(@"/C " + GlobalFunctions.bbndkPathConst + @"\eclipsec --list-all --simulator"); - - try - { - _simulatorList = new List(); - - p.Start(); - p.BeginErrorReadLine(); - p.BeginOutputReadLine(); - p.WaitForExit(); - p.Close(); - } - catch (Exception e) - { - System.Diagnostics.Debug.WriteLine(startInfo.Arguments); - System.Diagnostics.Debug.WriteLine(e.Message); - } - } - } - - /// - /// On Error received event handler - /// - /// - /// - private void ErrorDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) - { - if (e.Data != null) - { - System.Diagnostics.Debug.WriteLine(e.Data); - - MessageBox.Show(e.Data); - } - } - - /// - /// On Data Received event handler - /// - /// - /// - private void SimulatorListDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) - { - string apilevel = ""; - string version = ""; - - SimulatorsClass sim = null; - - if (e.Data != null) - { - if ((e.Data.ToLower().Contains("error")) || (_error != "")) - { - _error = _error + e.Data; - } - else if ((e.Data.Contains("Location:")) || (e.Data.Contains("Available"))) - { - // Do Nothing - } - else - { - version = e.Data.Substring(0, e.Data.LastIndexOf(" - ")); - apilevel = version.Split('.')[0] + "." + version.Split('.')[1]; - - sim = _simulatorList.Find(i => i.APILevel == apilevel); - - if (sim == null) - { - sim = new SimulatorsClass(version, apilevel, true); - sim.IsInstalled = IsSimulatorInstalled(version); - _simulatorList.Add(sim); - } - else - { - //sim not the latest... mark it as false - sim.LatestVersion = false; - - //create new sim - SimulatorsClass sim2 = new SimulatorsClass(version, apilevel, true); - sim2.IsInstalled = IsSimulatorInstalled(version); - - // insert before found sim. - _simulatorList.Insert(_simulatorList.IndexOf(sim), sim2); - } - } - } - } - - - /// - /// Check to see if Simulator is installed - /// - /// Check version number - /// true if installed - private bool IsSimulatorInstalled(string version) - { - bool success = false; - - if (InstalledSimulatorListSingleton.Instance.installedSimulatorList != null) - { - string result = InstalledSimulatorListSingleton.Instance.installedSimulatorList.FirstOrDefault(s => s.Contains(version)); - - if (result != null) - { - success = true; - } - } - - return success; - } - - } - - /// - /// Class to retrieve Installed API List - /// - public class InstalledSimulatorListSingleton - { - private static InstalledSimulatorListSingleton _instance; - public List installedSimulatorList; - - /// - /// Constructor - /// - private InstalledSimulatorListSingleton() - { - GetInstalledSimulatorList(); - } - - /// - /// Public property to retrieve the singleton instance - /// - public static InstalledSimulatorListSingleton Instance - { - get - { - if (_instance == null) - { - _instance = new InstalledSimulatorListSingleton(); - } - return _instance; - } - } - - /// - /// Retrieve a list of the installed runtimes on the PC. - /// - /// - public bool GetInstalledSimulatorList() - { - bool success = false; - - installedSimulatorList = new List(); - - string[] directories = Directory.GetFiles(GlobalFunctions.bbndkPathConst, "*.vmxf", SearchOption.AllDirectories); - - foreach (string directory in directories) - { - if (directory.Contains("simulator_")) - { - installedSimulatorList.Add(directory.Substring(0, directory.LastIndexOf("\\")).Substring(directory.IndexOf("simulator_") + 10).Replace('_', '.')); - success = true; - } - else - { - continue; - } - } - - return success; - } - } - - - /// - /// This is the class that implements the package exposed by this assembly. - /// - /// The minimum requirement for a class to be considered a valid package for Visual Studio - /// is to implement the IVsPackage interface and register itself with the shell. - /// This package uses the helper classes defined inside the Managed Package Framework (MPF) - /// to do it: it derives from the Package class that provides the implementation of the - /// IVsPackage interface and uses the registration attributes defined in the framework to - /// register itself and its components with the shell. - /// - // This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is - // a package. - [PackageRegistration(UseManagedResourcesOnly = true)] - - ///Register the editor factory - [XmlEditorDesignerViewRegistration("XML", "xml", LogicalViewID.Designer, 0x60, - DesignerLogicalViewEditor = typeof(EditorFactory), - Namespace = "http://www.qnx.com/schemas/application/1.0", - MatchExtensionAndNamespace = true)] - // And which type of files we want to handle - [ProvideEditorExtension(typeof(EditorFactory), EditorFactory.defaultExtension, 0x40, NameResourceID = 106)] - // We register that our editor supports LOGVIEWID_Designer logical view - [ProvideEditorLogicalView(typeof(EditorFactory), LogicalViewID.Designer)] - - // Microsoft Visual C# Project - [EditorFactoryNotifyForProject("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", EditorFactory.defaultExtension, GuidList.guidVSNDK_PackageEditorFactoryString)] - - // This attribute is used to register the informations needed to show the this package - // in the Help/About dialog of Visual Studio. - [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] - // This attribute is needed to let the shell know that this package exposes some menus. - [ProvideMenuResource("Menus.ctmenu", 1)] - // This attribute registers a tool window exposed by this package. - [ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string)] - [Guid(GuidList.guidVSNDK_PackagePkgString)] - public sealed class VSNDK_PackagePackage : Package - { - - #region private member variables - - private EnvDTE.DTE _dte; - private VSNDKCommandEvents _commandEvents; - private bool _isSimulator; - private BuildEvents _buildEvents; - private List _targetDir = null; - private bool _hitPlay = false; - private int _amountOfProjects = 0; - private string _error = ""; - private bool _isDeploying = false; - private OutputWindowPane _owP; - private bool isDebugConfiguration = true; - - #endregion - - #region Package Members - - /// - /// Default constructor of the package. - /// Inside this method you can place any initialization code that does not require - /// any Visual Studio service because at this point the package object is created but - /// not sited yet inside Visual Studio environment. The place to do all the other - /// initialization is the Initialize method. - /// - public VSNDK_PackagePackage() - { - Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString())); - } - - /// - /// Initialization of the package; this method is called right after the package is sited, so this is the place - /// where you can put all the initilaization code that rely on services provided by VisualStudio. - /// - protected override void Initialize() - { - Trace.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString())); - base.Initialize(); - - //Create Editor Factory. Note that the base Package class will call Dispose on it. - base.RegisterEditorFactory(new EditorFactory(this)); - - _dte = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE)); - - SetNDKPath(); - - APITargetListSingleton api = APITargetListSingleton.Instance; - InstalledAPIListSingleton apiList = InstalledAPIListSingleton.Instance; - InstalledNDKListSingleton ndkList = InstalledNDKListSingleton.Instance; - SimulatorListSingleton simList = SimulatorListSingleton.Instance; - InstalledSimulatorListSingleton installedSimList = InstalledSimulatorListSingleton.Instance; - - _commandEvents = new VSNDKCommandEvents((DTE2)_dte); - _commandEvents.RegisterCommand(GuidList.guidVSStd97String, CommandConstants.cmdidStartDebug, startDebugCommandEvents_AfterExecute, startDebugCommandEvents_BeforeExecute); - _commandEvents.RegisterCommand(GuidList.guidVSStd97String, CommandConstants.cmdidStartDebug, startDebugCommandEvents_AfterExecute, startDebugCommandEvents_BeforeExecute); - _commandEvents.RegisterCommand(GuidList.guidVSStd2KString, CommandConstants.cmdidStartDebugContext, startDebugCommandEvents_AfterExecute, startDebugCommandEvents_BeforeExecute); - - _buildEvents = _dte.Events.BuildEvents; - _buildEvents.OnBuildBegin += new _dispBuildEvents_OnBuildBeginEventHandler(this.OnBuildBegin); - - - - // Add our command handlers for menu (commands must exist in the .vsct file) - OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; - if ( null != mcs ) - { - // Create the command for the tool window - CommandID toolwndCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, (int)PkgCmdIDList.cmdidBlackBerryTools); - MenuCommand menuToolWin = new MenuCommand(ShowToolWindow, toolwndCommandID); - mcs.AddCommand( menuToolWin ); - - // Create the command for the settings window - CommandID wndSettingsCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, (int)PkgCmdIDList.cmdidBlackBerrySettings); - MenuCommand menuSettingsWin = new MenuCommand(ShowSettingsWindow, wndSettingsCommandID); - mcs.AddCommand(menuSettingsWin); - - // Create the command for the Debug Token window - CommandID wndDebugTokenCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, (int)PkgCmdIDList.cmdidBlackBerryDebugToken); - MenuCommand menuDebugTokenWin = new MenuCommand(ShowDebugTokenWindow, wndDebugTokenCommandID); - mcs.AddCommand(menuDebugTokenWin); - - // Create the command for the menu item. - CommandID projCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, (int)PkgCmdIDList.cmdidfooLocalBox); - OleMenuCommand projItem = new OleMenuCommand(MenuItemCallback, projCommandID); - mcs.AddCommand(projItem); - } - - } - #endregion - - #region private methods - - /// - /// Set the NDK path into the registry if not already set. - /// - private void SetNDKPath() - { - //Initialize NDK if possible. - RegistryKey rkHKCU = Registry.CurrentUser; - RegistryKey rkNDKPath = null; - string qnx_target = ""; - string qnx_host = ""; - - try - { - - rkNDKPath = rkHKCU.CreateSubKey("Software\\BlackBerry\\BlackBerryVSPlugin"); - qnx_host = rkNDKPath.GetValue("NDKHostPath").ToString(); - qnx_target = rkNDKPath.GetValue("NDKHostPath").ToString(); - - if (qnx_host == "") - { - string[] filePaths = Directory.GetFiles(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\BlackBerry Native SDK\qconfig\", "*.xml"); - - if (filePaths.Length >= 1) - { - XmlDocument xmlDoc = new XmlDocument(); - xmlDoc.Load(filePaths[0]); - XmlNodeList name = xmlDoc.GetElementsByTagName("name"); - XmlNodeList hostpath = xmlDoc.GetElementsByTagName("host"); - XmlNodeList targetpath = xmlDoc.GetElementsByTagName("target"); - - qnx_target = targetpath[0].InnerText; - qnx_host = hostpath[0].InnerText; - - rkNDKPath.SetValue("NDKHostPath", qnx_host); - rkNDKPath.SetValue("NDKTargetPath", qnx_target); - - } - } - - string qnx_config = GlobalFunctions.bbndkPathConst + @"\features\com.qnx.tools.jre.win32_1.6.0.43\jre\bin"; - - System.Environment.SetEnvironmentVariable("QNX_TARGET", qnx_target); - System.Environment.SetEnvironmentVariable("QNX_HOST", qnx_host); - - string ndkpath = string.Format(@"{0}/usr/bin;{1}", qnx_host, qnx_config) + - System.Environment.GetEnvironmentVariable("PATH"); - System.Environment.SetEnvironmentVariable("PATH", ndkpath); - - - } - catch (Exception ex) - { - string e = ex.ToString(); - } - - rkNDKPath.Close(); - rkHKCU.Close(); - } - - /// - /// Identify the projects to be build and start the build process. - /// - /// TRUE if successful, FALSE if not. - private bool BuildBar() - { - bool success = true; - try - { - Microsoft.Win32.RegistryKey key; - key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("VSNDK"); - key.SetValue("Run", "True"); - key.Close(); - - _buildEvents.OnBuildDone += new _dispBuildEvents_OnBuildDoneEventHandler(this.OnBuildDone); - - try - { - Solution2 soln = (Solution2)_dte.Solution; - List buildThese = new List(); - _targetDir = new List(); - - foreach (String startupProject in (Array)soln.SolutionBuild.StartupProjects) - { - foreach (Project p1 in soln.Projects) - { - if (p1.UniqueName == startupProject) - { - buildThese.Add(p1.FullName); - - ConfigurationManager config = p1.ConfigurationManager; - Configuration active = config.ActiveConfiguration; - - foreach (Property prop in active.Properties) - { - try - { - if (prop.Name == "OutputPath") - { - string[] path = new string[2]; - path[0] = p1.Name + "_" + _isSimulator.ToString(); - path[1] = prop.Value.ToString(); - _targetDir.Add(path); - break; - } - } - catch - { - } - } - - break; - } - } - } - - _hitPlay = true; - _amountOfProjects = buildThese.Count; // OnBuildDone will call build() only after receiving "amountOfProjects" events - foreach (string projectName in buildThese) - soln.SolutionBuild.BuildProject("Debug", projectName, false); - } - catch (Exception ex) - { - Debug.WriteLine(ex.Message); - success = false; - } - } - catch (Exception e) - { - Debug.WriteLine(e.Message); - success = false; - } - return success; - } - - /// - /// Verify if the build process was successful. If so, start deploying the app. - /// - private void Built() - { - string outputText = ""; - - _owP.TextDocument.Selection.SelectAll(); - outputText = _owP.TextDocument.Selection.Text; - - if ((outputText == "") || (System.Text.RegularExpressions.Regex.IsMatch(outputText, ">Build succeeded.\r\n")) || (!outputText.Contains("): error :"))) - { - if (isDebugConfiguration) - { - // Write file to flag the deploy task that it should use the -debugNative option - string fileContent = "Use -debugNative.\r\n"; - string appData = Environment.GetEnvironmentVariable("AppData"); - System.IO.StreamWriter file = new System.IO.StreamWriter(appData + @"\BlackBerry\vsndk-debugNative.txt"); - file.WriteLine(fileContent); - file.Close(); - - _buildEvents.OnBuildDone += new _dispBuildEvents_OnBuildDoneEventHandler(this.OnBuildDone); - } - - foreach (String startupProject in (Array)_dte.Solution.SolutionBuild.StartupProjects) - { - foreach (SolutionContext sc in _dte.Solution.SolutionBuild.ActiveConfiguration.SolutionContexts) - { - if (sc.ProjectName == startupProject) - { - sc.ShouldDeploy = true; - } - else - { - sc.ShouldDeploy = false; - } - } - } - _isDeploying = true; - _dte.Solution.SolutionBuild.Deploy(true); - } - } - - /// - /// Get the process ID and launch an executable using the VSNDK debug engine. - /// - private void Deployed() - { - Microsoft.Win32.RegistryKey key; - key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("VSNDK"); - key.SetValue("Run", "False"); - key.Close(); - - string pidString = ""; - getPID((DTE2)_dte, ref pidString); - - bool CancelDefault = LaunchDebugTarget(pidString); - } - - /// - /// Launch an executable using the VSNDK debug engine. - /// - /// Process ID in string format. - /// TRUE if successful, False if not. - private bool LaunchDebugTarget(string pidString) - { - Microsoft.VisualStudio.Shell.ServiceProvider sp = - new Microsoft.VisualStudio.Shell.ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)_dte); - - IVsDebugger dbg = (IVsDebugger)sp.GetService(typeof(SVsShellDebugger)); - - VsDebugTargetInfo info = new VsDebugTargetInfo(); - - info.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(info); - info.dlo = Microsoft.VisualStudio.Shell.Interop.DEBUG_LAUNCH_OPERATION.DLO_CreateProcess; - - // Read debugger args from a file (it is set when the Deploy task is run) - System.IO.StreamReader argsFile = null; - try - { - string localAppData = Environment.GetEnvironmentVariable("AppData"); - argsFile = new System.IO.StreamReader(localAppData + @"\BlackBerry\vsndk-args-file.txt"); - } - catch (Exception e) - { - Debug.Fail("Unexpected exception in LaunchDebugTarget"); - } - - // Store all debugger arguments in a string - var nvc = new NameValueCollection(); - nvc.Add("pid", pidString); - nvc.Add("targetIP", argsFile.ReadLine()); // The device (IP address) - info.bstrExe = argsFile.ReadLine(); // The executable path - nvc.Add("isSimulator", argsFile.ReadLine()); - nvc.Add("ToolsPath", argsFile.ReadLine()); - nvc.Add("PublicKeyPath", argsFile.ReadLine()); - - // Decrypt stored password. - byte[] data = Convert.FromBase64String(argsFile.ReadLine()); - if (data.Length > 0) - { - byte[] decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.LocalMachine); - nvc.Add("Password", Encoding.Unicode.GetString(decrypted)); - } - - info.bstrArg = NameValueCollectionHelper.DumpToString(nvc); - argsFile.Close(); - - info.bstrRemoteMachine = null; // debug locally - info.fSendStdoutToOutputWindow = 0; // Let stdout stay with the application. - info.clsidCustom = new Guid("{E5A37609-2F43-4830-AA85-D94CFA035DD2}"); // Set the launching engine the VSNDK engine guid - info.grfLaunch = 0; - - IntPtr pInfo = System.Runtime.InteropServices.Marshal.AllocCoTaskMem((int)info.cbSize); - System.Runtime.InteropServices.Marshal.StructureToPtr(info, pInfo, false); - - try - { - int result = dbg.LaunchDebugTargets(1, pInfo); - - if (result != VSConstants.S_OK) - { - string msg; - IVsUIShell sh = (IVsUIShell)sp.GetService(typeof(SVsUIShell)); - sh.GetErrorInfo(out msg); - Debug.WriteLine("LaunchDebugTargets: " + msg); - - return true; - } - } - finally - { - if (pInfo != IntPtr.Zero) - { - System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pInfo); - } - } - - return false; - } - - /// - /// Get the PID of the launched native app by parsing text from the output window. - /// - /// Application Object. - /// Returns the Process ID as a string. - /// TRUE if successful, False if not. - private bool getPID(DTE2 dte, ref string pidString) - { - // Select all of the text - _owP.TextDocument.Selection.SelectAll(); - string outputText = _owP.TextDocument.Selection.Text; - - // Check for successful deployment - if (System.Text.RegularExpressions.Regex.IsMatch(outputText, "Info: done")) - { - string pattern = @"\s+result::(\d+)\r\n.+"; - Regex r = new Regex(pattern, RegexOptions.IgnoreCase); - - // Match the regular expression pattern against a text string. - Match m = r.Match(outputText); - - // Take first match - if (m.Success) - { - Group g = m.Groups[1]; - CaptureCollection cc = g.Captures; - Capture c = cc[0]; - pidString = c.ToString(); - - // Store proccess name and file location into ProcessesPath.txt, so "Attach To Process" would be able to find the - // source code for a running process. - // First read the file. - string processesPaths = ""; - System.IO.StreamReader readProcessesPathsFile = null; - try - { - readProcessesPathsFile = new System.IO.StreamReader(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\ProcessesPath.txt"); - processesPaths = readProcessesPathsFile.ReadToEnd(); - readProcessesPathsFile.Close(); - } - catch (Exception e) - { - processesPaths = ""; - } - - // Updating the contents. - int begin = outputText.IndexOf("Deploy started: Project: ") + 25; - if (begin == -1) - begin = outputText.IndexOf("Project: ") + 9; - int end = outputText.IndexOf(", Configuration:", begin); - string processName = outputText.Substring(begin, end - begin) + "_" + _isSimulator.ToString(); - begin = processesPaths.IndexOf(processName + ":>"); - - // string currentPath = dte.ActiveDocument.Path; - string currentPath = ""; - - foreach (string[] paths in _targetDir) - { - if (paths[0] == processName) - { - currentPath = paths[1]; - break; - } - } - - if (begin != -1) - { - begin += processName.Length + 2; - end = processesPaths.IndexOf("\r\n", begin); - processesPaths = processesPaths.Substring(0, begin) + currentPath + processesPaths.Substring(end); - } - else - { - processesPaths = processesPaths + processName + ":>" + currentPath + "\r\n"; - } - - // Writing contents to file. - System.IO.StreamWriter writeProcessesPathsFile = null; - try - { - writeProcessesPathsFile = new System.IO.StreamWriter(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\ProcessesPath.txt", false); - writeProcessesPathsFile.Write(processesPaths); - writeProcessesPathsFile.Close(); - } - catch (Exception e) - { - } - - return true; - } - else - { - return false; - } - } - return false; - } - - - /// - /// Verify if the app configuration is Debug. - /// - /// True if Debug configuration; False otherwise. - private bool checkDebugConfiguration() - { - Solution2 soln = (Solution2)_dte.Solution; - foreach (String startupProject in (Array)soln.SolutionBuild.StartupProjects) - { - foreach (Project p1 in soln.Projects) - { - if (p1.UniqueName == startupProject) - { - ConfigurationManager config = p1.ConfigurationManager; - Configuration active = config.ActiveConfiguration; - - if (active.ConfigurationName.ToUpper() == "DEBUG") - return (true); - else - return (false); - } - } - } - return (false); - } - - - #endregion - - - - #region Event Handlers - - /// - /// New Start Debug Command Events After Execution Event Handler. - /// - /// Command GUID. - /// Command ID. - /// Custom IN Object. - /// Custom OUT Object. - private void startDebugCommandEvents_AfterExecute(string Guid, int ID, object CustomIn, object CustomOut) - { - Debug.WriteLine("After Start Debug"); - } - - - /// - /// New Start Debug Command Events Before Execution Event Handler. Call the method responsible for building the app. - /// - /// Command GUID. - /// Command ID. - /// Custom IN Object. - /// Custom OUT Object. - /// Cancel the default execution of the command. - private void startDebugCommandEvents_BeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault) - { - - bool bbPlatform = false; - if (_dte.Solution.SolutionBuild.ActiveConfiguration != null) - { - isDebugConfiguration = checkDebugConfiguration(); - - SolutionContexts scCollection = _dte.Solution.SolutionBuild.ActiveConfiguration.SolutionContexts; - foreach (SolutionContext sc in scCollection) - { - if (sc.PlatformName == "BlackBerry" || sc.PlatformName == "BlackBerrySimulator") - { - bbPlatform = true; - if (sc.PlatformName == "BlackBerrySimulator") - _isSimulator = true; - else - _isSimulator = false; - } - } - } - - Debug.WriteLine("Before Start Debug"); - - if (VSNDK.Package.ControlDebugEngine.isDebugEngineRunning || !bbPlatform) - { - // Disable the override of F5 (this allows the debugged process to continue execution) - CancelDefault = false; - } - else - { - // Create a reference to the Output window. - // Create a tool window reference for the Output window - // and window pane. - OutputWindow ow = ((DTE2)_dte).ToolWindows.OutputWindow; - - // Select the Build pane in the Output window. - _owP = ow.OutputWindowPanes.Item("Build"); - _owP.Activate(); - - - if (isDebugConfiguration) - { - UpdateManagerData upData = new UpdateManagerData(); - - if (!upData.validateDeviceVersion(_isSimulator)) - { - CancelDefault = true; - } - else - { - BuildBar(); - CancelDefault = true; - } - } - else - { - BuildBar(); - CancelDefault = true; - } - } - } - - - /// - /// This event is fired only when the build/rebuild/clean process ends. - /// - /// Represents the scope of the build. - /// Represents the type of build action that is occurring, such as a build or a deploy action. - public void OnBuildDone(EnvDTE.vsBuildScope Scope, EnvDTE.vsBuildAction Action) - { - if (Action == vsBuildAction.vsBuildActionBuild) - { - _amountOfProjects -= 1; - if (_amountOfProjects == 0) - { - _buildEvents.OnBuildDone -= new _dispBuildEvents_OnBuildDoneEventHandler(this.OnBuildDone); - Built(); - } - } - else if (Action == vsBuildAction.vsBuildActionDeploy) - { - _buildEvents.OnBuildDone -= new _dispBuildEvents_OnBuildDoneEventHandler(this.OnBuildDone); - _isDeploying = false; - Deployed(); - } - } - - /// - /// This event is fired only when user wants to build, rebuild or clean the project. - /// - /// Represents the scope of the build. - /// Represents the type of build action that is occurring, such as a build or a deploy action. - public void OnBuildBegin(EnvDTE.vsBuildScope Scope, EnvDTE.vsBuildAction Action) - { - if ((Action == vsBuildAction.vsBuildActionBuild) || (Action == vsBuildAction.vsBuildActionRebuildAll)) - { - if ((_hitPlay == false) && (_isDeploying == false)) // means that the "play" building and deploying process was cancelled before, so we have to disable the - // OnBuildDone event to avoid deploying in case user only wants to build. - { - _buildEvents.OnBuildDone -= new _dispBuildEvents_OnBuildDoneEventHandler(this.OnBuildDone); - } - _hitPlay = false; - } - } - - /// - /// This function is called when the user clicks the menu item that shows the - /// tool window. See the Initialize method to see how the menu item is associated to - /// this function using the OleMenuCommandService service and the MenuCommand class. - /// - private void ShowToolWindow(object sender, EventArgs e) - { - // Create the dialog instance without Help support. - var SigningToolDialog = new Signing.SigningDialog(); - // Show the dialog. - var m = SigningToolDialog.ShowDialog(); - } - - /// - /// This function is called when the user clicks the menu item that shows the - /// tool window. See the Initialize method to see how the menu item is associated to - /// this function using the OleMenuCommandService service and the MenuCommand class. - /// - private void ShowSettingsWindow(object sender, EventArgs e) - { - var SettingsDialog = new Settings.SettingsDialog(); - var m = SettingsDialog.ShowModal(); - } - - /// - /// This function is called when the user clicks the menu item that shows the - /// tool window. See the Initialize method to see how the menu item is associated to - /// this function using the OleMenuCommandService service and the MenuCommand class. - /// - private void ShowDebugTokenWindow(object sender, EventArgs e) - { - // Create the dialog instance without Help support. - var DebugTokenDialog = new DebugToken.DebugTokenDialog(); - // Show the dialog. - if (!DebugTokenDialog.IsClosing) - DebugTokenDialog.ShowModal(); - } - - private void MenuItemCallback(object sender, EventArgs e) - { - string filename = ""; - string folderName = ""; - string name = ""; - - Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); - dlg.DefaultExt = ".cproject"; // Default file extension - dlg.Filter = "Native Core Application Project Files (*.cproject, *.project)|*.cproject;*.project;"; - dlg.Title = "Open BlackBerry Core Native Application Project Files"; - dlg.Multiselect = false; - dlg.InitialDirectory = Environment.SpecialFolder.MyComputer.ToString(); - dlg.CheckFileExists = true; - - bool? result = dlg.ShowDialog(); - if (result == true) - { - filename = dlg.FileName; - FileInfo fi = new FileInfo(filename); - folderName = fi.DirectoryName; - - Array projs = (Array)_dte.ActiveSolutionProjects; - Project project = (Project)projs.GetValue(0); - name = project.FullName; - - // Create the dialog instance without Help support. - var ImportSummary = new Import.Import(project, folderName, name); - ImportSummary.ShowModel2(); - } - - } - - #endregion - - } -} diff --git a/src/VSNDK.Package/VSNDKCommandEvents.cs b/src/VSNDK.Package/VSNDKCommandEvents.cs deleted file mode 100644 index b6291609..00000000 --- a/src/VSNDK.Package/VSNDKCommandEvents.cs +++ /dev/null @@ -1,64 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using EnvDTE; -using Microsoft.VisualStudio.Shell; -using EnvDTE80; - -namespace VSNDK.Package -{ - - /// - /// Responsible for customization of VSShell command events for VSNDK. - /// - public class VSNDKCommandEvents - { - private DTE2 dte; - private Dictionary cmdEvents; - - - /// - /// - /// - /// Application Object. - public VSNDKCommandEvents(DTE2 dte) - { - this.dte = dte; - cmdEvents = new Dictionary(); - } - - - /// - /// - /// - /// - /// - /// - /// - public void RegisterCommand( string guid, int cmdId, _dispCommandEvents_AfterExecuteEventHandler afterHandler, _dispCommandEvents_BeforeExecuteEventHandler beforeHandler) - { - cmdEvents[cmdId] = dte.Events.get_CommandEvents(guid, cmdId); - CommandEvents e = cmdEvents[cmdId]; - if ( e != null) - { - e.AfterExecute += afterHandler; - e.BeforeExecute += beforeHandler; - } - } - } -} diff --git a/src/VSNDK.Package/VSNDKConstants.cs b/src/VSNDK.Package/VSNDKConstants.cs deleted file mode 100644 index 7640dbfd..00000000 --- a/src/VSNDK.Package/VSNDKConstants.cs +++ /dev/null @@ -1,44 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace VSNDK.Package -{ - /// - /// Command IDs exposed by VisualStudio. - /// - public static class CommandConstants - { - public const int cmdidAddSolutionSCC = 21016; - public const int cmdidUndoCheckoutSCC = 21009; - public const int cmdidGetLatestVersionSCC = 21011; - public const int cmdidGetSCC = 21501; - public const int cmdidViewHistorySCC = 21508; - public const int cmdidStartDebug = 295; - public const int cmdidStartDebugContext = 356; - public const int cmdidRestartDebug = 296; - public const int cmdidStopDebug = 179; - public const int cmdidPreviewInBrowser = 334; - public const int cmdidBrowseWith = 336; - public const int cmdidStartNoDebug = 368; - public const int cmdidSolutionCfg = 684; - public const int cmdidSolutionPlatform = 1990; - public const int cmdidSolutionPlatformGetList = 1991; - public const int cmdidDebugBreakatFunction = 311; - } -} diff --git a/src/VSNDK.Package/VSPackage.resx b/src/VSNDK.Package/VSPackage.resx deleted file mode 100644 index 7c5753ad..00000000 --- a/src/VSNDK.Package/VSPackage.resx +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - VSNDK.Package - - - Package provides BlackBerry Menu items and editor - - - Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - [Read Only] - - - File has been changed outside the environment. Reload the new file? - - - BarDescriptorEditor - Name of the editor to show for the Keybindings - - - BarDescriptorEditor Files - - - BarDescriptorEditor - - - bar-descriptor - - - BarDescriptorEditor File (xml) - - - Resources\Images_24bit.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - Resources\File.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file diff --git a/src/VSNDK.Package/ViewModel.cs b/src/VSNDK.Package/ViewModel.cs deleted file mode 100644 index 7c12c640..00000000 --- a/src/VSNDK.Package/ViewModel.cs +++ /dev/null @@ -1,1706 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.ComponentModel; -using Microsoft.VisualStudio.Package; -using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; -using Microsoft.VisualStudio; -using System.Runtime.InteropServices; -using System.Xml.Serialization; -using System.Xml.Linq; -using System.Xml; -using Microsoft.VisualStudio.XmlEditor; -using Microsoft.VisualStudio.TextManager.Interop; -using System.Reflection; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.Shell; -using System.Collections; -using System.IO; -using System.Windows.Data; -using System.Collections.ObjectModel; -using RIM.VSNDK_Package.Settings.Models; -using EnvDTE; - -namespace RIM.VSNDK_Package -{ - public class OrientationItemClass - { - private string _name; - - public string Name - { - get { return _name; } - set { _name = value; } - } - - public OrientationItemClass(string name) - { - _name = name; - } - } - - public class ConfigurationItemClass - { - private string _name; - - public string Name - { - get { return _name; } - set { _name = value; } - } - - public ConfigurationItemClass(string name) - { - _name = name; - } - } - - public class AssetTypeItemClass - { - private string _type; - - public string Type - { - get { return _type; } - set { _type = value; } - } - - public AssetTypeItemClass(string type) - { - _type = type; - } - } - - public class PermissionItemClass : INotifyPropertyChanged - { - private bool _isChecked; - private string _permission; - private string _identifier; - private string _permisionImagePath; - - public bool IsChecked - { - get { return _isChecked; } - set { - _isChecked = value; - OnPropertyChanged("IsChecked"); - } - } - - public string Permission - { - get { return _permission; } - set - { - _permission = value; - OnPropertyChanged("Permission"); - } - } - - public string PermissionImagePath - { - get { return _permisionImagePath; } - set - { - _permisionImagePath = value; - OnPropertyChanged("PermissionImagePath"); - } - } - - public string Identifier - { - get { return _identifier; } - set - { - _identifier = value; - OnPropertyChanged("Identifier"); - } - } - - public PermissionItemClass(bool isChecked, string permission, string identifier, string permissionImagePath) - { - _isChecked = isChecked; - _permission = permission; - _identifier = identifier; - _permisionImagePath = permissionImagePath; - } - - public event PropertyChangedEventHandler PropertyChanged; - protected void OnPropertyChanged(string propertyname) - { - var handler = PropertyChanged; - if (handler != null) - handler(this, new PropertyChangedEventArgs(propertyname)); - } - } - - public class ImageItemClass - { - private string _imageName; - private string _imagePath; - private string _imageSize; - - public string ImageName - { - get { return _imageName; } - set { _imageName = value; } - } - - public string ImagePath - { - get { return _imagePath; } - set { _imagePath = value; } - } - - public string ImageSize - { - get { return _imageSize; } - set { _imageSize = value; } - } - - /// - /// Class to store the splashscreen and icon images data. - /// - /// - /// - /// - public ImageItemClass(string imageName, string imagePath, string activeProjectDirectory) - { - _imageName = imageName; - _imagePath = imagePath; - - if (!File.Exists(_imagePath)) - { - if (File.Exists(activeProjectDirectory + "\\" + _imagePath)) - { - _imagePath = activeProjectDirectory + "\\" + _imagePath; - - } - } - - try - { - System.Drawing.Image objImage = System.Drawing.Image.FromFile(_imagePath); - _imageSize = objImage.Width.ToString() + "X" + objImage.Height.ToString(); - } - catch - { - - } - } - } - - /// - /// ViewModel is where the interesting portion of the VsTemplate Designer lives. The View binds to an instance of this class. - /// - /// The View binds the various designer controls to the methods derived from IViewModel that get and set values in the XmlModel. - /// The ViewModel and an underlying XmlModel manage how an IVsTextBuffer is shared between the designer and the XML editor (if opened). - /// - public class ViewModel : IViewModel, IDataErrorInfo, INotifyPropertyChanged - { - private static string _localRIMFolder; - private static string _tmpAuthor = ""; - private static string _tmpAuthorID = ""; - private readonly CollectionView _orientationList; - private OrientationItemClass _orientationItem; - private CollectionView _iconImageList; - private CollectionView _splashScreenImageList; - private CollectionView _assetTypeList; - private CollectionView _permissionList; - private CollectionView _configurationList; - private ConfigurationItemClass _config; - private PermissionItemClass _permission; - private DTE _dte; - private string _activeProjectDirectory; - private Package _pkg; - - long _dirtyTime; - LanguageService _xmlLanguageService; - IServiceProvider _serviceProvider; - qnx _qnxSchema; - bool _synchronizing; - XmlModel _xmlModel; - XmlStore _xmlStore; - IVsTextLines _buffer; - - bool? _canEditFile; - bool _gettingCheckoutStatus; - - EventHandler _editingScopeCompletedHandler; - EventHandler _undoRedoCompletedHandler; - EventHandler _bufferReloadedHandler; - - /// - /// Constructor - /// - /// - /// - /// - /// - public ViewModel(Package pkg, XmlStore xmlStore, XmlModel xmlModel, IServiceProvider provider, IVsTextLines buffer) - { - _pkg = pkg; - /// Initialize Asset Type List - IList AssetTypeListItem = new List(); - AssetTypeItemClass assetType = new AssetTypeItemClass("Other"); - AssetTypeListItem.Add(assetType); - assetType = new AssetTypeItemClass("Entry-point"); - AssetTypeListItem.Add(assetType); - assetType = new AssetTypeItemClass("Library"); - AssetTypeListItem.Add(assetType); - assetType = new AssetTypeItemClass("Executable"); - AssetTypeListItem.Add(assetType); - _assetTypeList = new CollectionView(AssetTypeListItem); - - if (xmlModel == null) - throw new ArgumentNullException("xmlModel"); - if (xmlStore == null) - throw new ArgumentNullException("xmlStore"); - if (provider == null) - throw new ArgumentNullException("provider"); - if (buffer == null) - throw new ArgumentNullException("buffer"); - - this.BufferDirty = false; - this.DesignerDirty = false; - - this._serviceProvider = provider; - this._buffer = buffer; - - _dte = (DTE)_serviceProvider.GetService(typeof(DTE)); - Array activeProjects = (Array)_dte.ActiveSolutionProjects; - Project activeProject = (Project)activeProjects.GetValue(0); - FileInfo activeProjectFileInfo = new FileInfo(activeProject.FullName); - _activeProjectDirectory = activeProjectFileInfo.DirectoryName; - - this._xmlStore = xmlStore; - // OnUnderlyingEditCompleted - _editingScopeCompletedHandler = new EventHandler(OnUnderlyingEditCompleted); - this._xmlStore.EditingScopeCompleted += _editingScopeCompletedHandler; - // OnUndoRedoCompleted - _undoRedoCompletedHandler = new EventHandler(OnUndoRedoCompleted); - this._xmlStore.UndoRedoCompleted += _undoRedoCompletedHandler; - - this._xmlModel = xmlModel; - // BufferReloaded - _bufferReloadedHandler += new EventHandler(BufferReloaded); - this._xmlModel.BufferReloaded += _bufferReloadedHandler; - - _localRIMFolder = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Research In Motion\"; - - LoadModelFromXmlModel(); - - IList IconImageList = new List(); - if ((_qnxSchema.icon != null) && (_qnxSchema.icon.image != null)) - { - string iconPNG_Path = ""; //added to avoid duplication. That's because I didn't find the template to remove teh ICON.PNG. - foreach (string iconImage in _qnxSchema.icon.image) - { - ImageItemClass imageItem = new ImageItemClass(iconImage, getImagePath(iconImage), _activeProjectDirectory); - if (imageItem.ImageName != null) //added because I didn't find the template to remove teh ICON.PNG. - if (imageItem.ImageName == "icon.png") - { - if (iconPNG_Path != imageItem.ImagePath) //added because I didn't find the template to remove teh ICON.PNG. - { - IconImageList.Add(imageItem); - iconPNG_Path = imageItem.ImagePath; - } - } - else - IconImageList.Add(imageItem); - - } - } - _iconImageList = new CollectionView(IconImageList); - - LoadPermissions(); - - IList SplashScreenImageList = new List(); - if ((_qnxSchema.splashScreens != null) && (_qnxSchema.splashScreens.image != null)) - { - foreach (string splashScreenImage in _qnxSchema.splashScreens.image) - { - ImageItemClass imageItem = new ImageItemClass(splashScreenImage, getImagePath(splashScreenImage), _activeProjectDirectory); - SplashScreenImageList.Add(imageItem); - } - } - _splashScreenImageList = new CollectionView(SplashScreenImageList); - - IList ConfigurationList = new List(); - ConfigurationItemClass configItem = new ConfigurationItemClass("All Configurations"); - ConfigurationList.Add(configItem); - foreach (qnxConfiguration config in _qnxSchema.configuration) - { - configItem = new ConfigurationItemClass(config.name); - ConfigurationList.Add(configItem); - } - _configurationList = new CollectionView(ConfigurationList); - - IList OrientationList = new List(); - OrientationItemClass OrientationItem = new OrientationItemClass("Default"); - OrientationList.Add(OrientationItem); - if (_qnxSchema.initialWindow.autoOrients == "") - { - _orientationItem = OrientationItem; - } - - OrientationItem = new OrientationItemClass("Auto-orient"); - OrientationList.Add(OrientationItem); - if (_qnxSchema.initialWindow.autoOrients == "true") - { - _orientationItem = OrientationItem; - } - - - OrientationItem = new OrientationItemClass("Landscape"); - OrientationList.Add(OrientationItem); - if (_qnxSchema.initialWindow.aspectRatio == "landscape") - { - _orientationItem = OrientationItem; - } - - OrientationItem = new OrientationItemClass("Portrait"); - OrientationList.Add(OrientationItem); - if (_qnxSchema.initialWindow.aspectRatio == "portrait") - { - _orientationItem = OrientationItem; - } - - _orientationList = new CollectionView(OrientationList); - } - - private string getImagePath(string imgName) - { - string imagePath = ""; - - foreach (asset assetItem in _qnxSchema.asset) - { - if (assetItem.Value == imgName) - { - imagePath = assetItem.path; - } - } - - return imagePath; - } - - /// - /// Close View Model - /// - public void Close() - { - //Unhook the events from the underlying XmlStore/XmlModel - if (_xmlStore != null) - { - this._xmlStore.EditingScopeCompleted -= _editingScopeCompletedHandler; - this._xmlStore.UndoRedoCompleted -= _undoRedoCompletedHandler; - } - if (this._xmlModel != null) - { - this._xmlModel.BufferReloaded -= _bufferReloadedHandler; - } - } - - /// - /// Given the permission ID return the appropriate Icon - /// - /// - /// - private string getPermissionIcon(string ID) - { - string retVal = ""; - - switch (ID) - { - case "bbm_connect": - retVal = "/VSNDK.Package;component/Resources/BlackBerryMessager.bmp"; - break; - case "access_pimdomain_calendars": - retVal = "/VSNDK.Package;component/Resources/Calendar.bmp"; - break; - case "use_camera": - retVal = "/VSNDK.Package;component/Resources/Camera.bmp"; - break; - case "access_pimdomain_contacts": - retVal = "/VSNDK.Package;component/Resources/Contacts.bmp"; - break; - case "read_device_identifying_information": - retVal = "/VSNDK.Package;component/Resources/DeviceIdentifyingInfo.bmp"; - break; - case "access_pimdomain_messages": - retVal = "/VSNDK.Package;component/Resources/EmailPINMessages.bmp"; - break; - case "access_internet": - retVal = "/VSNDK.Package;component/Resources/Internet.bmp"; - break; - case "read_geolocation": - retVal = "/VSNDK.Package;component/Resources/GPSLocation.bmp"; - break; - case "access_location_services": - retVal = "/VSNDK.Package;component/Resources/Location.bmp"; - break; - case "record_audio": - retVal = "/VSNDK.Package;component/Resources/Mircrophone.bmp"; - break; - case "access_pimdomain_notebooks": - retVal = "/VSNDK.Package;component/Resources/Notebooks.bmp"; - break; - case "post_notification": - retVal = "/VSNDK.Package;component/Resources/PostNotifications.bmp"; - break; - case "run_when_backgrounded": - retVal = "/VSNDK.Package;component/Resources/RunBackgrounded.bmp"; - break; - case "access_shared": - retVal = "/VSNDK.Package;component/Resources/SharedFiles.bmp"; - break; - case "access_sms_mms": - retVal = "/VSNDK.Package;component/Resources/TextMessages.bmp"; - break; - case "read_personally_identifiable_information": - retVal = "/VSNDK.Package;component/Resources/MyContactInfo.bmp"; - break; - case "access_phone": - retVal = "/VSNDK.Package;component/Resources/Phone.bmp"; - break; - case "control_phone": - retVal = "/VSNDK.Package;component/Resources/PhoneControl.bmp"; - break; - case "_sys_use_consumer_push": - retVal = "/VSNDK.Package;component/Resources/Push.bmp"; - break; - case "use_camera_desktop": - retVal = "/VSNDK.Package;component/Resources/CaptureScreen.bmp"; - break; - case "use_gamepad": - retVal = "/VSNDK.Package;component/Resources/Gamepad.bmp"; - break; - } - - return retVal; - } - - /// - /// Load the permissions list - /// - private void LoadPermissions() - { - SettingsData settingsData = new SettingsData(); - bool oldListMethod = true; - XmlNodeList pList = null; - - if (settingsData.TargetPath != "") - { - XmlDocument xmlDoc = new XmlDocument(); - xmlDoc.Load(settingsData.TargetPath + @"\..\blackberry-sdk-descriptor.xml"); - pList = xmlDoc.GetElementsByTagName("permission"); - oldListMethod = false; - } - - IList PermissionList = new List(); - - if (oldListMethod) // Old Listing Method - { - PermissionItemClass permissionItem = new PermissionItemClass(isPermissionChecked("bbm_connect"), "BlackBerry Messenger", "bbm_connect", getPermissionIcon("bbm_connect")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_pimdomain_calendars"), "Calendar", "access_pimdomain_calendars", getPermissionIcon("access_pimdomain_calendars")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("use_camera"), "Camera", "use_camera", getPermissionIcon("use_camera")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_pimdomain_contacts"), "Contacts", "access_pimdomain_contacts", getPermissionIcon("access_pimdomain_contacts")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("read_device_identifying_information"), "Device Identifying Information", "read_device_identifying_information", getPermissionIcon("read_device_identifying_information")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_pimdomain_messages"), "Email and PIN Message", "access_pimdomain_messages", getPermissionIcon("access_pimdomain_messages")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_internet"), "Internet", "access_internet", getPermissionIcon("access_internet")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("read_geolocation"), "GPS Location", "read_geolocation", getPermissionIcon("read_geolocation")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_location_services"), "Location", "access_location_services", getPermissionIcon("access_location_services")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("record_audio"), "Microphone", "record_audio", getPermissionIcon("record_audio")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_pimdomain_notebooks"), "Notebooks", "access_pimdomain_notebooks", getPermissionIcon("access_pimdomain_notebooks")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("post_notification"), "Post Notifications", "post_notification", getPermissionIcon("post_notification")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("run_when_backgrounded"), "Run When Backgrounded", "run_when_backgrounded", getPermissionIcon("run_when_backgrounded")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_shared"), "Shared Files", "access_shared", getPermissionIcon("access_shared")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_sms_mms"), "Text Messages", "access_sms_mms", getPermissionIcon("access_sms_mms")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("_sys_use_consumer_push"), "Consumer Push", "_sys_use_consumer_push", getPermissionIcon("_sys_use_consumer_push")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("narrow_landscape_exit"), "Narrow Swipe Up", "narrow_landscape_exit", getPermissionIcon("narrow_landscape_exit")); - PermissionList.Add(permissionItem); - permissionItem = new PermissionItemClass(isPermissionChecked("access_phone"), "Phone", "access_phone", getPermissionIcon("access_phone")); - PermissionList.Add(permissionItem); - } - else - { - foreach (XmlNode p in pList) - { - PermissionItemClass permissionItem = new PermissionItemClass(isPermissionChecked(p["id"].InnerText), p["name"].InnerText, p["id"].InnerText, getPermissionIcon(p["id"].InnerText)); - PermissionList.Add(permissionItem); - } - } - - _permissionList = new CollectionView(PermissionList); - } - - /// - /// Called on idle time. This is when we check if the designer is out of sync with the underlying text buffer. - /// - public void DoIdle() - { - if (BufferDirty || DesignerDirty) - { - int delay = 100; - - if ((Environment.TickCount - _dirtyTime) > delay) - { - // Must not try and sync while XML editor is parsing otherwise we just confuse matters. - if (IsXmlEditorParsing) - { - _dirtyTime = System.Environment.TickCount; - return; - } - - //If there is contention, give the preference to the designer. - if (DesignerDirty) - { - SaveModelToXmlModel(Resources.SynchronizeBuffer); - //We don't do any merging, so just overwrite whatever was in the buffer. - BufferDirty = false; - } - else if (BufferDirty) - { - LoadModelFromXmlModel(); - } - } - } - } - - /// - /// We must not try and update the XDocument while the XML Editor is parsing as this may cause - /// a deadlock in the XML Editor! - /// - /// - bool IsXmlEditorParsing - { - get - { - LanguageService langsvc = GetXmlLanguageService(); - return langsvc != null ? langsvc.IsParsing : false; - } - } - - /// - /// Get the XML Editor language service - /// - /// - LanguageService GetXmlLanguageService() - { - if (_xmlLanguageService == null) - { - IOleServiceProvider vssp = _serviceProvider.GetService(typeof(IOleServiceProvider)) as IOleServiceProvider; - Guid xmlEditorGuid = new Guid("f6819a78-a205-47b5-be1c-675b3c7f0b8e"); - Guid iunknown = new Guid("00000000-0000-0000-C000-000000000046"); - IntPtr ptr; - if (ErrorHandler.Succeeded(vssp.QueryService(ref xmlEditorGuid, ref iunknown, out ptr))) - { - try - { - _xmlLanguageService = Marshal.GetObjectForIUnknown(ptr) as LanguageService; - } - finally - { - Marshal.Release(ptr); - } - } - } - return _xmlLanguageService; - } - - /// - /// This method is called when it is time to save the designer values to the - /// underlying buffer. - /// - /// - void SaveModelToXmlModel(string undoEntry) - { - LanguageService langsvc = GetXmlLanguageService(); - - try - { - //We can't edit this file (perhaps the user cancelled a SCC prompt, etc...) - if (!CanEditFile()) - { - DesignerDirty = false; - BufferDirty = true; - throw new Exception(); - } - - XmlSerializer serializer = new XmlSerializer(typeof(qnx)); - XDocument documentFromDesignerState = new XDocument(); - using (XmlWriter w = documentFromDesignerState.CreateWriter()) - { - serializer.Serialize(w, _qnxSchema); - } - - _synchronizing = true; - XDocument document = GetParseTree(); - Source src = GetSource(); - if (src == null || langsvc == null) - { - return; - } - - langsvc.IsParsing = true; // lock out the background parse thread. - - // Wrap the buffer sync and the formatting in one undo unit. - using (CompoundAction ca = new CompoundAction(src, Resources.SynchronizeBuffer)) - { - using (XmlEditingScope scope = _xmlStore.BeginEditingScope(Resources.SynchronizeBuffer, this)) - { - //Replace the existing XDocument with the new one we just generated. - document.Root.ReplaceWith(documentFromDesignerState.Root); - scope.Complete(); - } - ca.FlushEditActions(); - FormatBuffer(src); - } - DesignerDirty = false; - } - catch (Exception) - { - // if the synchronization fails then we'll just try again in a second. - _dirtyTime = Environment.TickCount; - } - finally - { - langsvc.IsParsing = false; - _synchronizing = false; - - LoadPermissions(); - } - } - - /// - /// Reformat the text buffer - /// - void FormatBuffer(Source src) - { - using (EditArray edits = new EditArray(src, null, false, Resources.ReformatBuffer)) - { - TextSpan span = src.GetDocumentSpan(); - src.ReformatSpan(edits, span); - } - } - - /// - /// Get the XML Editor Source object for this document. - /// - /// - Source GetSource() - { - LanguageService langsvc = GetXmlLanguageService(); - if (langsvc == null) - { - return null; - } - Source src = langsvc.GetSource(_buffer); - return src; - } - - /// - /// Get an up to date XML parse tree from the XML Editor. - /// - XDocument GetParseTree() - { - LanguageService langsvc = this.GetXmlLanguageService(); - - // don't crash if the language service is not available - if (langsvc != null) - { - Source src = langsvc.GetSource(_buffer); - - // We need to access this method to get the most up to date parse tree. - // public virtual XmlDocument GetParseTree(Source source, IVsTextView view, int line, int col, ParseReason reason) { - MethodInfo mi = langsvc.GetType().GetMethod("GetParseTree"); - int line = 0, col = 0; - mi.Invoke(langsvc, new object[] { src, null, line, col, ParseReason.Check }); - } - - // Now the XmlDocument should be up to date also. - return _xmlModel.Document; - } - - /// - /// This function asks the QueryEditQuerySave service if it is possible to edit the file. - /// This can result in an automatic checkout of the file and may even prompt the user for - /// permission to checkout the file. If the user says no or the file cannot be edited - /// this returns false. - /// - private bool CanEditFile() - { - // Cache the value so we don't keep asking the user over and over. - if (_canEditFile.HasValue) - { - return (bool)_canEditFile; - } - - // Check the status of the recursion guard - if (_gettingCheckoutStatus) - return false; - - _canEditFile = false; // assume the worst - try - { - // Set the recursion guard - _gettingCheckoutStatus = true; - - // Get the QueryEditQuerySave service - IVsQueryEditQuerySave2 queryEditQuerySave = _serviceProvider.GetService(typeof(SVsQueryEditQuerySave)) as IVsQueryEditQuerySave2; - - string filename = _xmlModel.Name; - - // Now call the QueryEdit method to find the edit status of this file - string[] documents = { filename }; - uint result; - uint outFlags; - - // Note that this function can popup a dialog to ask the user to checkout the file. - // When this dialog is visible, it is possible to receive other request to change - // the file and this is the reason for the recursion guard - int hr = queryEditQuerySave.QueryEditFiles( - 0, // Flags - 1, // Number of elements in the array - documents, // Files to edit - null, // Input flags - null, // Input array of VSQEQS_FILE_ATTRIBUTE_DATA - out result, // result of the checkout - out outFlags // Additional flags - ); - if (ErrorHandler.Succeeded(hr) && (result == (uint)tagVSQueryEditResult.QER_EditOK)) - { - // In this case (and only in this case) we can return true from this function - _canEditFile = true; - } - } - finally - { - _gettingCheckoutStatus = false; - } - return (bool)_canEditFile; - } - - /// - /// Load the model from the underlying text buffer. - /// - private void LoadModelFromXmlModel() - { - try - { - XmlSerializer serializer = new XmlSerializer(typeof(qnx)); - - using (XmlReader reader = GetParseTree().CreateReader()) - { - _qnxSchema = (qnx)serializer.Deserialize(reader); - } - - if (_qnxSchema == null) - { - throw new Exception(Resources.InvalidVsTemplateData); - } - } - catch (Exception e) - { - //Display error message - ErrorHandler.ThrowOnFailure(VsShellUtilities.ShowMessageBox(_serviceProvider, - Resources.InvalidVsTemplateData + e.Message, - Resources.ErrorMessageBoxTitle, - OLEMSGICON.OLEMSGICON_CRITICAL, - OLEMSGBUTTON.OLEMSGBUTTON_OK, - OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST)); - } - - BufferDirty = false; - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - - LoadPermissions(); - } - } - - /// - /// BufferDirty Property - /// - public bool BufferDirty { get; set; } - - /// - /// DesignerDirty Property - /// - public bool DesignerDirty { get; set; } - - - /// - /// Fired when all controls should be re-bound. - /// - public event EventHandler ViewModelChanged; - - /// - /// Handle edit scope completion event. This happens when the XML editor buffer decides to update - /// it's XDocument parse tree. - /// - /// - /// - void OnUnderlyingEditCompleted(object sender, XmlEditingScopeEventArgs e) - { - if (e.EditingScope.UserState != this && !_synchronizing) - { - BufferDirty = true; - _dirtyTime = Environment.TickCount; - } - } - - /// - /// Handle undo/redo completion event. This happens when the user invokes Undo/Redo on a buffer edit operation. - /// We need to resync when this happens. - /// - /// - /// - void OnUndoRedoCompleted(object sender, XmlEditingScopeEventArgs e) - { - if (!_synchronizing) - { - BufferDirty = true; - _dirtyTime = Environment.TickCount; - } - } - - /// - /// BufferReloaded event handler - /// - /// - /// - private void BufferReloaded(object sender, EventArgs e) - { - if (!_synchronizing) - { - BufferDirty = true; - _dirtyTime = Environment.TickCount; - } - } - - /// - /// Read the author information from the debug token and update the appropriate boxes. - /// - public void setAuthorInfo() - { - if (!File.Exists(_localRIMFolder + "DebugToken.bar")) - { - // Create the dialog instance without Help support. - var DebugTokenDialog = new DebugToken.DebugTokenDialog(); - // Show the dialog. - if (!DebugTokenDialog.IsClosing) - DebugTokenDialog.ShowModal(); - } - - System.Diagnostics.Process p = new System.Diagnostics.Process(); - System.Diagnostics.ProcessStartInfo startInfo = p.StartInfo; - startInfo.UseShellExecute = false; - startInfo.CreateNoWindow = true; - startInfo.RedirectStandardError = true; - startInfo.RedirectStandardOutput = true; - p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(p_OutputDataReceived); - - - /// Get Device PIN - startInfo.FileName = "cmd.exe"; - startInfo.Arguments = string.Format(@"/C blackberry-airpackager.bat -listManifest ""{0}""", _localRIMFolder + "DebugToken.bar"); - - try - { - p.Start(); - p.BeginErrorReadLine(); - p.BeginOutputReadLine(); - p.WaitForExit(); - p.Close(); - } - catch (Exception e) - { - System.Diagnostics.Debug.WriteLine(startInfo.Arguments); - System.Diagnostics.Debug.WriteLine(e.Message); - } - } - - /// - /// Get the author ID - /// - /// REturns the author ID - public string getAuthorID() - { - return _tmpAuthorID; - } - - /// - /// Get the author ID - /// - /// REturns the author ID - public string getAuthor() - { - return _tmpAuthor; - } - - /// - /// On Data Received event handler - /// - /// - /// - private void p_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) - { - if (e.Data != null) - { - if (e.Data.Contains("Package-Author-Id:")) - AuthorID = e.Data.Substring(e.Data.LastIndexOf(": ") + 2); - else if (e.Data.Contains("Package-Author:")) - Author = e.Data.Substring(e.Data.LastIndexOf(": ") + 2); - } - } - - #region IViewModel - - /// - /// Name property - /// - public string Name - { - get - { - return _qnxSchema.id; - } - set - { - if (_qnxSchema.id != value) - { - _qnxSchema.id = value; - DesignerDirty = true; - NotifyPropertyChanged("Name"); - } - } - } - - /// - /// AppName property - /// - public string AppName - { - get - { - return _qnxSchema.name; - } - set - { - if (_qnxSchema.name != value) - { - _qnxSchema.name = value; - DesignerDirty = true; - NotifyPropertyChanged("AppName"); - } - } - } - - /// - /// Description property - /// - public string Description - { - get - { - return _qnxSchema.description.Trim(); - } - set - { - if (_qnxSchema.description != value) - { - _qnxSchema.description = value; - DesignerDirty = true; - NotifyPropertyChanged("Description"); - } - } - } - - /// - /// Version property - /// - public string Version - { - get - { - return _qnxSchema.versionNumber; - } - set - { - if (_qnxSchema.versionNumber != value) - { - _qnxSchema.versionNumber = value; - DesignerDirty = true; - NotifyPropertyChanged("Version"); - } - } - } - - /// - /// Build ID property - /// - public string BuildID - { - get - { - return _qnxSchema.buildId; - } - set - { - if (_qnxSchema.buildId != value) - { - _qnxSchema.buildId = value; - DesignerDirty = true; - NotifyPropertyChanged("BuildID"); - } - } - } - - /// - /// Author property - /// - public string Author - { - get - { - return _qnxSchema.author; - } - set - { - if (_qnxSchema.author != value) - { - _qnxSchema.author = value; - DesignerDirty = true; - NotifyPropertyChanged("Author"); - } - } - } - - /// - /// Build ID property - /// - public string AuthorID - { - get - { - return _qnxSchema.authorId; - } - set - { - if (_qnxSchema.authorId != value) - { - _qnxSchema.authorId = value; - DesignerDirty = true; - NotifyPropertyChanged("AuthorID"); - } - } - } - - /// - /// Chrome property - /// - public string Chrome - { - get - { - return _qnxSchema.initialWindow.systemChrome; - } - set - { - if (_qnxSchema.initialWindow.systemChrome != value) - { - _qnxSchema.initialWindow.systemChrome = value; - DesignerDirty = true; - NotifyPropertyChanged("Chrome"); - } - } - } - - /// - /// Return the AssetList - /// - public List AssetList - { - get - { - if (_config == null) - { - if (_qnxSchema.asset == null) - return null; - return _qnxSchema.asset.ToList(); - } - - if (_config.Name == "All Configurations") - { - if (_qnxSchema.asset == null) - return null; - return _qnxSchema.asset.ToList(); - } - else - { - foreach (qnxConfiguration config in _qnxSchema.configuration) - { - if (config.name == _config.Name) - { - if (config.asset == null) - return null; - return config.asset.ToList(); - } - } - - return null; - } - } - } - - - public void AddLocalAsset(string assetPath) - { - asset newAsset = new asset(); - - FileInfo fileInfo = new FileInfo(assetPath); - newAsset.Value = fileInfo.Name; - - string activeDir = _activeProjectDirectory; - string back = ""; - - // generating the relative path for the asset. - do - { - if (assetPath.Contains(activeDir + "\\")) - { - newAsset.path = back + assetPath.Replace(activeDir + "\\", ""); - break; - } - else - { - int pos = activeDir.LastIndexOf('\\', activeDir.Length - 1); - if (pos < 0) - { // file is located in a different driver. Copy the entire assetPath. - newAsset.path = assetPath; - break; - } - else - { - back += "..\\"; - activeDir = activeDir.Remove(pos); - } - } - } - while (true); - - if (_config.Name == "All Configurations") - _qnxSchema.AddLocalAsset(newAsset); - else - { - foreach (qnxConfiguration config in _qnxSchema.configuration) - { - if (config.name == _config.Name) - { - config.AddAsset(newAsset); - } - } - } - - DesignerDirty = true; - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - } - - public void DeleteLocalAsset(object asset) - { - if (_config.Name == "All Configurations") - _qnxSchema.DeleteLocalAsset(asset as asset); - else - { - foreach (qnxConfiguration config in _qnxSchema.configuration) - { - if (config.name == _config.Name) - { - config.DeleteAsset(asset as asset); - } - } - } - - DesignerDirty = true; - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - } - - public void EditLocalAsset(string identifier, bool? isPublic, string assetType) - { - if (_config.Name == "All Configurations") - { - foreach (asset assetItem in _qnxSchema.asset) - { - if (assetItem.Value == identifier) - { - if (isPublic == true) - { - assetItem.publicAsset = "true"; - } - else if (isPublic == false) - { - assetItem.publicAsset = "false"; - } - - if (assetType == "Other") - { - assetItem.type = ""; - assetItem.entry = ""; - assetItem.Value = assetItem.Value.Replace(@"lib/", ""); - } - else if (assetType == "Entry-point") - { - assetItem.type = "Qnx/Elf"; - assetItem.entry = "true"; - assetItem.Value = assetItem.Value.Replace(@"lib/", ""); - } - else if (assetType == "Executable") - { - assetItem.type = "Qnx/Elf"; - assetItem.entry = ""; - assetItem.Value = assetItem.Value.Replace(@"lib/", ""); - } - else if (assetType == "Library") - { - assetItem.type = ""; - assetItem.entry = ""; - assetItem.Value = @"lib/" + assetItem.Value; - } - } - } - } - else - { - foreach (qnxConfiguration config in _qnxSchema.configuration) - { - if (config.name == _config.Name) - { - foreach (asset assetItem in config.asset) - { - if (assetItem.Value == identifier) - { - if (isPublic == true) - { - assetItem.publicAsset = "true"; - } - else if (isPublic == false) - { - assetItem.publicAsset = "false"; - } - - if (assetType == "Other") - { - assetItem.type = ""; - assetItem.entry = ""; - assetItem.Value = assetItem.Value.Replace(@"lib/", ""); - } - else if (assetType == "Entry-point") - { - assetItem.type = "Qnx/Elf"; - assetItem.entry = "true"; - assetItem.Value = assetItem.Value.Replace(@"lib/", ""); - } - else if (assetType == "Executable") - { - assetItem.type = "Qnx/Elf"; - assetItem.entry = ""; - assetItem.Value = assetItem.Value.Replace(@"lib/", ""); - } - else if (assetType == "Library") - { - assetItem.type = ""; - assetItem.entry = ""; - assetItem.Value = @"lib/" + assetItem.Value; - } - } - } - } - } - } - - DesignerDirty = true; - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - } - - public void AddIcon(FileInfo icon) - { - _qnxSchema.icon.AddIconImage(icon.Name); - DesignerDirty = true; - IList source = (IList)_iconImageList.SourceCollection; - ImageItemClass image = new ImageItemClass(icon.Name, icon.ToString(), _activeProjectDirectory); - source.Add(image); - _iconImageList = new CollectionView(source); - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - } - - public void DeleteIcon(object iconName) - { - ImageItemClass item = (ImageItemClass)iconName; - _qnxSchema.icon.DeleteIconImage(item.ImageName); - DesignerDirty = true; - IList source = (IList)_iconImageList.SourceCollection; - source.Remove(item); - _iconImageList = new CollectionView(source); - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - } - - public void AddSplashScreen(FileInfo splashScreen) - { - qnxSplashScreens qnxSS; - - if (_qnxSchema.splashScreens == null) - { - qnxSS = new qnxSplashScreens(); - _qnxSchema.splashScreens = qnxSS; - } - else - { - qnxSS = _qnxSchema.splashScreens; - } - - qnxSS.AddSplashScreenImage(splashScreen.Name); - DesignerDirty = true; - IList source = (IList)_splashScreenImageList.SourceCollection; - ImageItemClass image = new ImageItemClass(splashScreen.Name, splashScreen.ToString(), _activeProjectDirectory); - source.Add(image); - _splashScreenImageList = new CollectionView(source); - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - } - - public void DeleteSplashScreen(object splashScreenName) - { - ImageItemClass item = (ImageItemClass)splashScreenName; - _qnxSchema.splashScreens.DeleteSplashScreenImage(item.ImageName); - DesignerDirty = true; - IList source = (IList)_splashScreenImageList.SourceCollection; - source.Remove(item); - _splashScreenImageList = new CollectionView(source); - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - } - - public void CheckPermission(string identifier) - { - - /// add new perm to xml - qnxPermission perm = new qnxPermission(); - perm.Value = identifier; - _qnxSchema.AddPermission(perm); - DesignerDirty = true; - } - - public void UnCheckPermission(string identifier) - { - /// add new perm to xml - qnxPermission perm = new qnxPermission(); - perm.Value = identifier; - _qnxSchema.DeletePermission(perm); - DesignerDirty = true; - } - - public bool isPermissionChecked(string identifier) - { - bool result = false; - - if (_qnxSchema.permission != null) - { - foreach (qnxPermission permEntry in _qnxSchema.permission) - { - if (permEntry.Value == identifier) - { - result = true; - } - } - } - return result; - } - - - public CollectionView OrientationList - { - get { return _orientationList; } - } - - public CollectionView ConfigurationList - { - get { return _configurationList; } - } - - public CollectionView PermissionList - { - get { return _permissionList; } - } - - public CollectionView IconImageList - { - get { return _iconImageList; } - } - - - public CollectionView SplashScreenImageList - { - get { return _splashScreenImageList; } - } - - public PermissionItemClass PermissionItem - { - get - { - return _permission; - } - set - { - _permission = value; - NotifyPropertyChanged("permission"); - } - } - - public ConfigurationItemClass ConfigurationItemClass - { - get - { - return _config; - } - set - { - if (_config == value) return; - _config = value; - - - if (ViewModelChanged != null) - { - // Update the Designer View - ViewModelChanged(this, new EventArgs()); - } - - NotifyPropertyChanged("ConfigurationItemClass"); - } - } - - public OrientationItemClass OrientationItemClass - { - get { - return _orientationItem; } - set - { - if (_orientationItem == value) return; - _orientationItem = value; - - if (_orientationItem.Name == "Default") - { - _qnxSchema.initialWindow.autoOrients = ""; - _qnxSchema.initialWindow.aspectRatio = ""; - } - else if (_orientationItem.Name == "Auto-orient") - { - _qnxSchema.initialWindow.autoOrients = "true"; - _qnxSchema.initialWindow.aspectRatio = ""; - } - else if (_orientationItem.Name == "Landscape") - { - _qnxSchema.initialWindow.autoOrients = "false"; - _qnxSchema.initialWindow.aspectRatio = "landscape"; - } - else if (_orientationItem.Name == "Portrait") - { - _qnxSchema.initialWindow.autoOrients = "false"; - _qnxSchema.initialWindow.aspectRatio = "portrait"; - } - - DesignerDirty = true; - NotifyPropertyChanged("OrientationItemClass"); - } - } - - public XmlModel Model - { - get - { - return _xmlModel; - } - } - /// - /// Transparent property - /// - public bool Transparent - { - get - { - if (_qnxSchema.initialWindow.transparent == "true") - { - return true; - } - else - { - return false; - } - } - set - { - if (value) - { - if (_qnxSchema.initialWindow.transparent != "true") - { - _qnxSchema.initialWindow.transparent = "true"; - DesignerDirty = true; - NotifyPropertyChanged("Chrome"); - } - } - else - { - if (_qnxSchema.initialWindow.transparent == "true") - { - _qnxSchema.initialWindow.transparent = "false"; - DesignerDirty = true; - NotifyPropertyChanged("Chrome"); - } - } - } - } - - #endregion - - #region IDataErrorInfo - - /// - /// Error Property - /// - public string Error - { - get - { - throw new NotImplementedException(); - } - } - - /// - /// - /// - /// - /// - public string this[string columnName] - { - get - { - string error = null; - return error; - } - } - - - #endregion - - #region INotifyPropertyChanged - - public event PropertyChangedEventHandler PropertyChanged; - - protected void NotifyPropertyChanged(string propertyName) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } - } - - #endregion - - #region TreeView SelectionChanged - - private ITrackSelection trackSel; - private ITrackSelection TrackSelection - { - get - { - if (trackSel == null) - trackSel = _serviceProvider.GetService(typeof(STrackSelection)) as ITrackSelection; - return trackSel; - } - } - - private Microsoft.VisualStudio.Shell.SelectionContainer selContainer; - public void OnSelectChanged(object p) - { - selContainer = new Microsoft.VisualStudio.Shell.SelectionContainer(true, false); - ArrayList items = new ArrayList(); - items.Add(p); - selContainer.SelectableObjects = items; - selContainer.SelectedObjects = items; - - ITrackSelection track = TrackSelection; - if (track != null) - track.OnSelectChange((ISelectionContainer)selContainer); - } - - #endregion - - } -} diff --git a/src/VSNDK.Package/VsDesignerControl.xaml b/src/VSNDK.Package/VsDesignerControl.xaml deleted file mode 100644 index 2095cb83..00000000 --- a/src/VSNDK.Package/VsDesignerControl.xaml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Package/VsDesignerControl.xaml.cs b/src/VSNDK.Package/VsDesignerControl.xaml.cs deleted file mode 100644 index 7de1ae8c..00000000 --- a/src/VSNDK.Package/VsDesignerControl.xaml.cs +++ /dev/null @@ -1,323 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using EnvDTE; -using Microsoft.VisualStudio.Shell; -using System.IO; - -namespace RIM.VSNDK_Package -{ - /// - /// Interaction logic for VsDesignerControl.xaml - /// - public partial class VsDesignerControl : UserControl - { - private ServiceProvider _serviceProvider; - /// - /// Primary Constructor - /// - public VsDesignerControl() - { - InitializeComponent(); - } - - /// - /// Overloaded Constructor - /// - /// - public VsDesignerControl(ServiceProvider serviceProvider, IViewModel viewModel) - { - _serviceProvider = serviceProvider; - DataContext = viewModel; - InitializeComponent(); - // wait until we're initialized to handle events - viewModel.ViewModelChanged += new EventHandler(ViewModelChanged); - } - - internal void DoIdle() - { - // only call the view model DoIdle if this control has focus - // otherwise, we should skip and this will be called again - // once focus is regained - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null && this.IsKeyboardFocusWithin) - { - viewModel.DoIdle(); - } - } - - /// - /// ViewModel Changerd Event - /// - /// - /// - private void ViewModelChanged(object sender, EventArgs e) - { - // this gets called when the view model is updated because the Xml Document was updated - // since we don't get individual PropertyChanged events, just re-set the DataContext - IViewModel viewModel = DataContext as IViewModel; - DataContext = null; // first, set to null so that we see the change and rebind - DataContext = viewModel; - } - - /// - /// Check to see if the inputed text is allowed - /// - /// - /// - private Boolean IsTextAllowed(String text) - { - return Array.TrueForAll(text.ToCharArray(), - delegate(Char c) { return Char.IsDigit(c) || Char.IsControl(c); }); - } - - /// - /// Use the PreviewTextInputHandler to respond to key presses - /// - /// - /// - - private void PreviewTextInputHandler(object sender, TextCompositionEventArgs e) - { - e.Handled = !IsTextAllowed(e.Text); - } - - /// - /// Use the DataObject.Pasting Handler - /// - /// - /// - private void PastingHandler(object sender, DataObjectPastingEventArgs e) - { - if (e.DataObject.GetDataPresent(typeof(String))) - { - String text = (String)e.DataObject.GetData(typeof(String)); - if (!IsTextAllowed(text)) e.CancelCommand(); - } - else e.CancelCommand(); - } - - /// - /// GetAuthor Button Click Event - /// - /// - /// - private void btGetAuthor_Click(object sender, RoutedEventArgs e) - { - IViewModel viewModel = DataContext as IViewModel; - viewModel.setAuthorInfo(); - } - - private void btnAddIC_Click(object sender, RoutedEventArgs e) - { - string filename = string.Empty; - Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); - dlg.DefaultExt = ".png"; // Default file extension - dlg.Filter = "Image Files (*.png, *.jpg, *.gif)|*.png;*.jpg;*.gif"; - bool? result = dlg.ShowDialog(); - if (result == true) - { - filename = dlg.FileName; - - AddIconToProject(filename); - - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - FileInfo fileInfo = new FileInfo(filename); - viewModel.AddIcon(fileInfo); - } - } - } - - private void AddIconToProject(string path) - { - try - { - DTE dte = (DTE)_serviceProvider.GetService(typeof(DTE)); - string solutionDir = System.IO.Path.GetDirectoryName(dte.Solution.FullName); - - - Projects projs = dte.Solution.Projects; - foreach (Project proj in projs) - { - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - - FileInfo fileInfo1 = new FileInfo(proj.FullName); - FileInfo fileInfo2 = new FileInfo(viewModel.Model.Name); - FileInfo fileInfo3 = new FileInfo(path); - - if (viewModel.AppName == proj.Name) - { - proj.ProjectItems.AddFromFile(path); - viewModel.AddLocalAsset(path); - } - } - } - } - catch (Exception e) - { - - } - } - - private void btnRemoveIC_Click(object sender, RoutedEventArgs e) - { - if (grdIcon.SelectedItem != null) - { - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - viewModel.DeleteIcon(grdIcon.SelectedItem); - } - } - } - - - private void btnAddSS_Click(object sender, RoutedEventArgs e) - { - string filename = string.Empty; - Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); - dlg.DefaultExt = ".png"; // Default file extension - dlg.Filter = "Image Files (*.png, *.jpg, *.gif)|*.png;*.jpg;*.gif"; - bool? result = dlg.ShowDialog(); - if (result == true) - { - filename = dlg.FileName; - - AddIconToProject(filename); - - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - FileInfo fileInfo = new FileInfo(filename); - viewModel.AddSplashScreen(fileInfo); - } - } - - } - - private void btnRemoveSS_Click(object sender, RoutedEventArgs e) - { - if (grdSplashScreen.SelectedItem != null) - { - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - viewModel.DeleteSplashScreen(grdSplashScreen.SelectedItem); - } - } - } - - private void CheckBox_Click(object sender, RoutedEventArgs e) - { - if ((sender as CheckBox).IsChecked == true) - { - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - viewModel.CheckPermission((grdPermissions.SelectedItem as PermissionItemClass).Identifier); - }; - } - else - { - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - viewModel.UnCheckPermission((grdPermissions.SelectedItem as PermissionItemClass).Identifier); - }; - } - - } - - private void btnAddAsset_Click(object sender, RoutedEventArgs e) - { - string filename = string.Empty; - Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); - - bool? result = dlg.ShowDialog(); - if (result == true) - { - filename = dlg.FileName; - - - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - viewModel.AddLocalAsset(filename); - } - } - - } - - private void btnRemoveAsset_Click(object sender, RoutedEventArgs e) - { - if (grdAssets.SelectedItem != null) - { - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - viewModel.DeleteLocalAsset(grdAssets.SelectedItem); - } - } - } - - private void CheckBox_Click_1(object sender, RoutedEventArgs e) - { - bool isPublic = false; - - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - isPublic = (sender as CheckBox).IsChecked == true; - viewModel.EditLocalAsset((grdAssets.SelectedItem as asset).Value, isPublic, ""); - } - } - - private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) - { - string assetType = ""; - - if (e.RemovedItems.Count != 0) - { - if (grdAssets.SelectedItems.Count != 0) - { - IViewModel viewModel = DataContext as IViewModel; - if (viewModel != null) - { - assetType = (sender as ComboBox).SelectedValue.ToString(); - viewModel.EditLocalAsset((grdAssets.SelectedItem as asset).Value, null, assetType); - } - } - } - } - - - } -} diff --git a/src/VSNDK.Package/XmlEditorDesignerViewRegistration.cs b/src/VSNDK.Package/XmlEditorDesignerViewRegistration.cs deleted file mode 100644 index aa8f25ac..00000000 --- a/src/VSNDK.Package/XmlEditorDesignerViewRegistration.cs +++ /dev/null @@ -1,205 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.VisualStudio.Shell; -using System.IO; -using Microsoft.VisualStudio; - -namespace RIM.VSNDK_Package -{ - /// - /// Register our bardescriptor.xml custom editor - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] - public sealed class XmlEditorDesignerViewRegistrationAttribute : RegistrationAttribute - { - /// Declare Constants - const string XmlChooserFactory = "XmlChooserFactory"; - const string XmlChooserEditorExtensionsKeyPath = @"Editors\{32CC8DFA-2D70-49b2-94CD-22D57349B778}\Extensions"; - const string XmlEditorFactoryGuid = "{FA3CD31E-987B-443A-9B81-186104E8DAC1}"; - - /// Declare Private Member Variables - private string keyName; - private string defaultExtension; - private Guid defaultLogicalView; - private int xmlChooserPriority; - - /// - /// Construtor - /// - /// Registry key name - /// Default extension for editor - /// Default Editor Factory - /// XML Priority - public XmlEditorDesignerViewRegistrationAttribute(string keyName, string defaultExtension, object defaultLogicalViewEditorFactory, int xmlChooserPriority) - { - /// Validate parameter input - if (string.IsNullOrWhiteSpace(keyName)) - { - throw new ArgumentException("Editor description cannot be null or empty.", "editorDescription"); - } - if (string.IsNullOrWhiteSpace(defaultExtension)) - { - throw new ArgumentException("Extension cannot be null or empty.", "extension"); - } - if (defaultLogicalViewEditorFactory == null) - { - throw new ArgumentNullException("defaultLogicalViewEditorFactory"); - } - - /// Set Member Variables - this.keyName = keyName; - this.defaultExtension = defaultExtension; - this.defaultLogicalView = TryGetGuidFromObject(defaultLogicalViewEditorFactory); - this.xmlChooserPriority = xmlChooserPriority; - - this.CodeLogicalViewEditor = XmlEditorFactoryGuid; - this.DebuggingLogicalViewEditor = XmlEditorFactoryGuid; - this.DesignerLogicalViewEditor = XmlEditorFactoryGuid; - this.TextLogicalViewEditor = XmlEditorFactoryGuid; - } - - /// - /// Register the custom editor - /// - /// - public override void Register(RegistrationAttribute.RegistrationContext context) - { - /// Validate parameter input - if (context == null) - { - throw new ArgumentNullException("context"); - } - - /// Set extension key - Key extensionKey = context.CreateKey(XmlChooserEditorExtensionsKeyPath); - extensionKey.SetValue(defaultExtension, xmlChooserPriority); - extensionKey.Close(); - - /// set editor key - Key editorKey = context.CreateKey(Path.Combine(XmlChooserFactory, keyName)); - editorKey.SetValue("DefaultLogicalView", defaultLogicalView.ToString("B").ToUpperInvariant()); - editorKey.SetValue("Extension", defaultExtension); - if (!string.IsNullOrWhiteSpace(Namespace)) - { - editorKey.SetValue("Namespace", Namespace); - } - if (MatchExtensionAndNamespace) - { - editorKey.SetValue("Match", "both"); - } - if (IsDataSet.HasValue) - { - editorKey.SetValue("IsDataSet", Convert.ToInt32(IsDataSet.Value)); - } - /// Set DebuggingLogicalViewEditor Mapping - if (DebuggingLogicalViewEditor != null) - { - editorKey.SetValue(VSConstants.LOGVIEWID_Debugging.ToString("B").ToUpperInvariant(), TryGetGuidFromObject(DebuggingLogicalViewEditor).ToString("B").ToUpperInvariant()); - } - /// Set CodeLogicalViewEditor Mapping - if (CodeLogicalViewEditor != null) - { - editorKey.SetValue(VSConstants.LOGVIEWID_Code.ToString("B").ToUpperInvariant(), TryGetGuidFromObject(CodeLogicalViewEditor).ToString("B").ToUpperInvariant()); - } - /// Set DesignerLogicalViewEditor Mapping - if (DesignerLogicalViewEditor != null) - { - editorKey.SetValue(VSConstants.LOGVIEWID_Designer.ToString("B").ToUpperInvariant(), TryGetGuidFromObject(DesignerLogicalViewEditor).ToString("B").ToUpperInvariant()); - } - /// Set TextLogicalViewEditor Mapping - if (TextLogicalViewEditor != null) - { - editorKey.SetValue(VSConstants.LOGVIEWID_TextView.ToString("B").ToUpperInvariant(), TryGetGuidFromObject(TextLogicalViewEditor).ToString("B").ToUpperInvariant()); - } - editorKey.Close(); - } - - /// - /// Unregister the custom editor - /// - /// - public override void Unregister(RegistrationContext context) - { - /// Validate parameter input - if (context == null) - { - throw new ArgumentNullException("context"); - } - - /// Remove Key - context.RemoveKey(Path.Combine(XmlChooserFactory, keyName)); - context.RemoveValue(XmlChooserEditorExtensionsKeyPath, defaultExtension); - context.RemoveKeyIfEmpty(XmlChooserEditorExtensionsKeyPath); - } - - - /// - /// Private member function to return the GUID of an object. - /// - /// - /// - private Guid TryGetGuidFromObject(object guidObject) - { - // figure out what type of object they passed in and get the GUID from it - if (guidObject is string) - return new Guid((string)guidObject); - else if (guidObject is Type) - return ((Type)guidObject).GUID; - else if (guidObject is Guid) - return (Guid)guidObject; - else - throw new ArgumentException("Could not determine Guid from supplied object.", "guidObject"); - } - - /// - /// The editor factor for the Code View Editor - /// - public object CodeLogicalViewEditor { get; set; } - - /// - /// The editor factory for the Debugging View Editor - /// - public object DebuggingLogicalViewEditor { get; set; } - - /// - /// The editor factor for the Designer View Editor - /// - public object DesignerLogicalViewEditor { get; set; } - - /// - /// The edtior factgory for the Text View Editor - /// - public object TextLogicalViewEditor { get; set; } - - /// - /// Namespace property - /// - public string Namespace { get; set; } - - /// - /// Property - /// - public bool MatchExtensionAndNamespace { get; set; } - - /// - /// Special value used only by the DataSet designer. - /// - public bool? IsDataSet { get; set; } - } -} diff --git a/src/VSNDK.Package/bar-descriptor.cs b/src/VSNDK.Package/bar-descriptor.cs deleted file mode 100644 index 5ab7560d..00000000 --- a/src/VSNDK.Package/bar-descriptor.cs +++ /dev/null @@ -1,919 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -namespace RIM.VSNDK_Package -{ - using System.Xml.Serialization; - using System; - using System.Collections; - using System.Collections.Generic; - - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.qnx.com/schemas/application/1.0", IsNullable=true)] - public partial class asset : object, System.ComponentModel.INotifyPropertyChanged { - - private string pathField; - - private string publicAssetField; - - private string entryField; - - private string typeField; - - private string[] _assettypeList = {"Other", "Library", "Executable", "Entry-point"}; - - private string _assettype = "Other"; - - private string valueField; - - [System.Xml.Serialization.XmlIgnore] - public string assettype - { - get - { - _assettype = getAssetType(); - return _assettype; - } - set - { - if (value != _assettype) - _assettype = value; - } - } - - [System.Xml.Serialization.XmlIgnore] - public string[] assettypelist - { - get - { - return this._assettypeList; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string path { - get { - return this.pathField; - } - set { - this.pathField = value; - this.RaisePropertyChanged("path"); - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute("public")] - public string publicAsset - { - get - { - return this.publicAssetField; - } - set - { - this.publicAssetField = value; - this.RaisePropertyChanged("publicAsset"); - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string entry { - get { - return this.entryField; - } - set { - this.entryField = value; - this.RaisePropertyChanged("entry"); - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string type { - get { - return this.typeField; - } - set { - this.typeField = value; - this.RaisePropertyChanged("type"); - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value { - get { - return this.valueField; - } - set { - this.valueField = value; - this.RaisePropertyChanged("Value"); - } - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) - { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - - private string getAssetType() - { - if (this.valueField.StartsWith("lib/")) - { - return "Library"; - } - else if (this.typeField == "Qnx/Elf") - { - if (this.entry == "true") - { - return "Entry-point"; - } - else - { - return "Executable"; - } - } - else - { - return "Other"; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.qnx.com/schemas/application/1.0", IsNullable=false)] - public partial class qnx : object, System.ComponentModel.INotifyPropertyChanged { - - private string idField; - - private string nameField; - - private string versionNumberField; - - private string buildIdField; - - private string descriptionField; - - private string authorField; - - private string authorIdField; - - private string categoryField; - - private qnxInitialWindow initialWindowField; - - private asset[] assetField; - - private qnxConfiguration[] configurationField; - - private qnxPermission[] permissionField; - - private qnxIcon iconField; - - private qnxSplashScreens splashScreenField; - - private qnxAction[] actionField; - - private qnxEnv[] envField; - - /// - public string id { - get { - return this.idField; - } - set { - this.idField = value; - this.RaisePropertyChanged("id"); - } - } - - /// - public string name { - get { - return this.nameField; - } - set { - this.nameField = value; - this.RaisePropertyChanged("name"); - } - } - - /// - public string versionNumber { - get { - return this.versionNumberField; - } - set { - this.versionNumberField = value; - this.RaisePropertyChanged("versionNumber"); - } - } - - /// - public string buildId { - get { - return this.buildIdField; - } - set { - this.buildIdField = value; - this.RaisePropertyChanged("buildId"); - } - } - - /// - public string description { - get { - return this.descriptionField; - } - set { - this.descriptionField = value; - this.RaisePropertyChanged("description"); - } - } - - /// - public string author { - get { - return this.authorField; - } - set { - this.authorField = value; - this.RaisePropertyChanged("author"); - } - } - - /// - public string authorId - { - get - { - return this.authorIdField; - } - set - { - this.authorIdField = value; - this.RaisePropertyChanged("authorId"); - } - } - - /// - public string category { - get { - return this.categoryField; - } - set { - this.categoryField = value; - this.RaisePropertyChanged("category"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("initialWindow")] - public qnxInitialWindow initialWindow { - get { - return this.initialWindowField; - } - set { - this.initialWindowField = value; - this.RaisePropertyChanged("initialWindow"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("asset", IsNullable=true)] - public asset[] asset { - get { - return this.assetField; - } - set { - this.assetField = value; - this.RaisePropertyChanged("asset"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("configuration")] - public qnxConfiguration[] configuration { - get { - return this.configurationField; - } - set { - this.configurationField = value; - this.RaisePropertyChanged("configuration"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("permission", IsNullable = true)] - public qnxPermission[] permission - { - get - { - return this.permissionField; - } - set - { - this.permissionField = value; - this.RaisePropertyChanged("permission"); - } - } - - public void AddPermission(qnxPermission newPermission) - { - if (permission == null) - { - permission = new qnxPermission[0]; - } - - var newPermissionsList = permission; - Array.Resize(ref newPermissionsList, newPermissionsList.Length + 1); - newPermissionsList[newPermissionsList.Length - 1] = newPermission; - permission = newPermissionsList; - } - - public void DeletePermission(qnxPermission oldPermission) - { - foreach (qnxPermission perm in permission) - { - if (perm.Value == oldPermission.Value) - { - List permissionList = new List(permission); - permissionList.Remove(perm); - permission = permissionList.ToArray(); - } - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("icon")] - public qnxIcon icon { - get { - return this.iconField; - } - set { - this.iconField = value; - this.RaisePropertyChanged("icon"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("splashScreens")] - public qnxSplashScreens splashScreens - { - get - { - return this.splashScreenField; - } - set - { - this.splashScreenField = value; - this.RaisePropertyChanged("splashScreens"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("action", IsNullable=true)] - public qnxAction[] action { - get { - return this.actionField; - } - set { - this.actionField = value; - this.RaisePropertyChanged("action"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("env")] - public qnxEnv[] env { - get { - return this.envField; - } - set { - this.envField = value; - this.RaisePropertyChanged("env"); - } - } - - public void AddLocalAsset(asset newAsset) - { - if (asset == null) - { - asset = new asset[0]; - } - - var local_asset = asset; - Array.Resize(ref local_asset, local_asset.Length + 1); - local_asset[local_asset.Length - 1] = newAsset; - asset = local_asset; - } - - public void DeleteLocalAsset(asset removeAsset) - { - List assetList = new List(asset); - assetList.Remove(removeAsset); - asset = assetList.ToArray(); - } - - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxInitialWindow : object, System.ComponentModel.INotifyPropertyChanged { - - private string autoOrientsField; - - private string aspectRatioField; - - private string systemChromeField; - - private string transparentField; - - /// - [System.Xml.Serialization.XmlElementAttribute("autoOrients", IsNullable = true)] - public string autoOrients - { - get - { - return this.autoOrientsField; - } - set - { - this.autoOrientsField = value; - this.RaisePropertyChanged("autoOrients"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("aspectRatio", IsNullable = true)] - public string aspectRatio - { - get - { - return this.aspectRatioField; - } - set - { - this.aspectRatioField = value; - this.RaisePropertyChanged("aspectRatio"); - } - } - - /// - public string systemChrome { - get { - return this.systemChromeField; - } - set { - this.systemChromeField = value; - this.RaisePropertyChanged("systemChrome"); - } - } - - /// - public string transparent { - get { - return this.transparentField; - } - set { - this.transparentField = value; - this.RaisePropertyChanged("transparent"); - } - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxConfiguration : object, System.ComponentModel.INotifyPropertyChanged { - - private string platformArchitectureField; - - private asset[] assetField; - - private string idField; - - private string nameField; - - /// - public string platformArchitecture { - get { - return this.platformArchitectureField; - } - set { - this.platformArchitectureField = value; - this.RaisePropertyChanged("platformArchitecture"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("asset", IsNullable=true)] - public asset[] asset { - get { - return this.assetField; - } - set { - this.assetField = value; - this.RaisePropertyChanged("asset"); - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string id { - get { - return this.idField; - } - set { - this.idField = value; - this.RaisePropertyChanged("id"); - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name { - get { - return this.nameField; - } - set { - this.nameField = value; - this.RaisePropertyChanged("name"); - } - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - - public void AddAsset(asset newAsset) - { - if (asset == null) - { - asset = new asset[0]; - } - - var local_asset = asset; - Array.Resize(ref local_asset, local_asset.Length + 1); - local_asset[local_asset.Length - 1] = newAsset; - asset = local_asset; - } - - public void DeleteAsset(asset removeAsset) - { - List assetList = new List(asset); - assetList.Remove(removeAsset); - asset = assetList.ToArray(); - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.qnx.com/schemas/application/1.0")] - public partial class qnxPermission : object, System.ComponentModel.INotifyPropertyChanged - { - - private string systemField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string system - { - get - { - return this.systemField; - } - set - { - this.systemField = value; - this.RaisePropertyChanged("system"); - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - this.RaisePropertyChanged("Value"); - } - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) - { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) - { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxIcon : object, System.ComponentModel.INotifyPropertyChanged { - - private string[] imageField; - - /// - [System.Xml.Serialization.XmlElementAttribute("image", IsNullable = true)] - public string[] image { - get { - return this.imageField; - } - set { - this.imageField = value; - this.RaisePropertyChanged("image"); - } - } - - public void AddIconImage(string iconImage) - { - if (image == null) - { - image = new string[0]; - } - - var iconImages = image; - Array.Resize(ref iconImages, iconImages.Length + 1); - iconImages[iconImages.Length - 1] = iconImage; - image = iconImages; - } - - public void DeleteIconImage(string iconImage) - { - List iconList = new List(image); - iconList.Remove(iconImage); - image = iconList.ToArray(); - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.qnx.com/schemas/application/1.0")] - public partial class qnxSplashScreens : object, System.ComponentModel.INotifyPropertyChanged - { - - private string[] imageField; - - [System.Xml.Serialization.XmlElementAttribute("image", IsNullable = true)] - public string[] image - { - get - { - return this.imageField; - } - set - { - this.imageField = value; - this.RaisePropertyChanged("image"); - } - } - - public void AddSplashScreenImage(string iconImage) - { - if (image == null) - { - image = new string[0]; - } - - var iconImages = image; - Array.Resize(ref iconImages, iconImages.Length + 1); - iconImages[iconImages.Length - 1] = iconImage; - image = iconImages; - } - - public void DeleteSplashScreenImage(string iconImage) - { - List iconList = new List(image); - iconList.Remove(iconImage); - image = iconList.ToArray(); - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) - { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) - { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } - - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxAction : object, System.ComponentModel.INotifyPropertyChanged { - - private string systemField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string system { - get { - return this.systemField; - } - set { - this.systemField = value; - this.RaisePropertyChanged("system"); - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value { - get { - return this.valueField; - } - set { - this.valueField = value; - this.RaisePropertyChanged("Value"); - } - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxEnv : object, System.ComponentModel.INotifyPropertyChanged { - - private string varField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string var { - get { - return this.varField; - } - set { - this.varField = value; - this.RaisePropertyChanged("var"); - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value { - get { - return this.valueField; - } - set { - this.valueField = value; - this.RaisePropertyChanged("value"); - } - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.qnx.com/schemas/application/1.0", IsNullable=false)] - public partial class NewDataSet : object, System.ComponentModel.INotifyPropertyChanged { - - private object[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("asset", typeof(asset), IsNullable=true)] - [System.Xml.Serialization.XmlElementAttribute("qnx", typeof(qnx))] - public object[] Items { - get { - return this.itemsField; - } - set { - this.itemsField = value; - this.RaisePropertyChanged("Items"); - } - } - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - protected void RaisePropertyChanged(string propertyName) { - System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; - if ((propertyChanged != null)) { - propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); - } - } - } -} diff --git a/src/VSNDK.Package/source.extension.vsixmanifest b/src/VSNDK.Package/source.extension.vsixmanifest deleted file mode 100644 index fab92149..00000000 --- a/src/VSNDK.Package/source.extension.vsixmanifest +++ /dev/null @@ -1,25 +0,0 @@ - - - - VSNDK.Package - Research In Motion Ltd. - 1.0.0031 - Package provides BlackBerry Menu items and editor - 1033 - false - - - Pro - - - - - - - Visual Studio MPF - - - - |%CurrentProject%;PkgdefProjectOutputGroup| - - diff --git a/src/VSNDK.Tasks.Test/MakeAllAndFormatOutputMessagesTestClass.cs b/src/VSNDK.Tasks.Test/MakeAllAndFormatOutputMessagesTestClass.cs deleted file mode 100644 index 9893878c..00000000 --- a/src/VSNDK.Tasks.Test/MakeAllAndFormatOutputMessagesTestClass.cs +++ /dev/null @@ -1,36 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using VSNDK.Tasks; -using Microsoft.Build.Framework; -using NUnit.Framework; - -namespace VSNDK.Tasks.Test -{ - [TestFixture] - public class MakeAllAndFormatOutputMessagesTestClass - { - [TestCase] - public void MakeAllAndFormatOutputMessagesConstructorTest() - { - MakeAllAndFormatOutputMessages target = new MakeAllAndFormatOutputMessages(); - Assert.IsNotNull(target); - } - - } -} diff --git a/src/VSNDK.Tasks.Test/Properties/AssemblyInfo.cs b/src/VSNDK.Tasks.Test/Properties/AssemblyInfo.cs deleted file mode 100644 index 884a1d76..00000000 --- a/src/VSNDK.Tasks.Test/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("VSNDK.Tasks.Test")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("VSNDK.Tasks.Test")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("de27a838-9bb2-4ffc-b350-8cba94994fdd")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/VSNDK.Tasks.Test/VSNDK.Tasks.Test.csproj b/src/VSNDK.Tasks.Test/VSNDK.Tasks.Test.csproj deleted file mode 100644 index fb0a0c4a..00000000 --- a/src/VSNDK.Tasks.Test/VSNDK.Tasks.Test.csproj +++ /dev/null @@ -1,63 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E} - Library - Properties - VSNDK.Tasks.Test - VSNDK.Tasks.Test - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C} - VSNDK.Tasks - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks.Test/WriteDebuggerArgsTestClass.cs b/src/VSNDK.Tasks.Test/WriteDebuggerArgsTestClass.cs deleted file mode 100644 index f4c8b30d..00000000 --- a/src/VSNDK.Tasks.Test/WriteDebuggerArgsTestClass.cs +++ /dev/null @@ -1,81 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using VSNDK.Tasks; -using System.IO; - -namespace VSNDK.Tasks.Test -{ - [TestFixture] - class WriteDebuggerArgsTestClass - { -/* private WriteDebuggerArgs target; - - [SetUp] - public void setup() - { - target = new WriteDebuggerArgs(); - target.AppName = "HelloWorld"; - target.Device = "169.254.0.1"; - target.isSimulator = false; - target.OutDir = @"\Device-Debug"; - target.Password = "AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA7fSRRS7m1Em+yoK0ioAYhwQAAAACAAAAAAADZgAAwAAAABAAAABtBZa+ZRR0uoriYLDYxqPlAAAAAASAAACgAAAAEAAAAGJAoUM+qvmrXoLeokZQinMQAAAAS1JPN9qlZFQbSZmgaa509xQAAADKl++zEjFNnrI1aKXGrvvmgLRkeQ=="; - target.ProjectDir = @"C:\Users\dburgess\Desktop\HelloWorld\HelloWorld"; - target.PublicKeyPath = @"C:\Users\dburgess\AppData\Local/Research In Motion/bbt_id_rsa.pub"; - target.ToolsPath = @"C:\bbndk-2.0.0\host\win32\x86usr\bin"; - } - - /// - /// Constructor Test - /// - [TestCase] - public void WriteDebuggerArgsConstructorTest() - { - Assert.IsNotNull(target); - } - - /// - /// Perform Task Execute test case - /// - [TestCase] - public void ExecuteTest() - { - /// Prepare test case - bool result = target.Execute(); - - /// Verify test case - Assert.IsTrue(result); - } - - /// - /// Perform Task Execute test case - /// - [TestCase] - public void ExecuteFileExistsTest() - { - /// Prepare test case - WriteDebuggerArgs target = new WriteDebuggerArgs(); - bool targetResult = target.Execute(); - bool result = File.Exists(target.AppData); - - /// Verify test case - Assert. IsTrue(result); - }*/ - } -} diff --git a/src/VSNDK.Tasks/AsyncExec.cs b/src/VSNDK.Tasks/AsyncExec.cs deleted file mode 100644 index 27156d93..00000000 --- a/src/VSNDK.Tasks/AsyncExec.cs +++ /dev/null @@ -1,116 +0,0 @@ -//* Copyright 2010-2011 BlackBerry Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.Tasks; -using System.Diagnostics; -using System.Collections; -using System.Collections.Specialized; -using Microsoft.Build.Framework; -using System.Security.Cryptography; - -namespace VSNDK.Tasks -{ - // This task overrides Exec in order to run commands such as blackberry-connect asynchronously. - public class AsyncExec : Exec - { - private int _processId; - - /// - /// Execute given command asynchronously. - /// - /// Path of executable to be run. - /// Response file commands - /// Command Line Arguments - /// - protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) - { - string comm = "/Q /C " + Command + " -password " + Decrypt(Password); - - Process process = new Process(); - process.StartInfo = GetProcessStartInfo(pathToTool, comm); - process.StartInfo.UseShellExecute = false; - process.Start(); - _processId = process.Id; - return 0; - } - - /// - /// Helper function to create the ProcessStartInfo object for the running process. - /// - /// Path of executable to be run. - /// Command Line Arguments - /// - protected virtual ProcessStartInfo GetProcessStartInfo(string executable, string arguments) - { - if (arguments.Length > 0x7d00) - { - this.Log.LogWarningWithCodeFromResources("ToolTask.CommandTooLong", new object[] { base.GetType().Name }); - } - - ProcessStartInfo startInfo = new ProcessStartInfo(executable, arguments); - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.CreateNoWindow = true; - startInfo.UseShellExecute = true; - - string workingDirectory = this.GetWorkingDirectory(); - if (workingDirectory != null) - { - startInfo.WorkingDirectory = workingDirectory; - } - - StringDictionary environmentOverride = this.EnvironmentOverride; - if (environmentOverride != null) - { - foreach (DictionaryEntry entry in environmentOverride) - { - startInfo.EnvironmentVariables.Remove(entry.Key.ToString()); - startInfo.EnvironmentVariables.Add(entry.Key.ToString(), entry.Value.ToString()); - } - } - - return startInfo; - } - - /// - /// Getter/Setter for Password Property - /// - public virtual string Password - { - set; - get; - } - - /// - /// Helper Function to Decrypt Password - /// - /// - /// - public string Decrypt(string cipher) - { - if (cipher == null) throw new ArgumentNullException("cipher"); - - //parse base64 string - byte[] data = Convert.FromBase64String(cipher); - - //decrypt data - byte[] decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.LocalMachine); - - return Encoding.Unicode.GetString(decrypted); - } - } -} diff --git a/src/VSNDK.Tasks/BBDeploy.cs b/src/VSNDK.Tasks/BBDeploy.cs deleted file mode 100644 index 41bd1e26..00000000 --- a/src/VSNDK.Tasks/BBDeploy.cs +++ /dev/null @@ -1,700 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Reflection; -using System.Resources; -using Microsoft.Build.CPPTasks; -using System.Collections; -using Microsoft.Build.Framework; -using System.IO; -using Microsoft.Build.Utilities; -using System.Security.Cryptography; - -namespace VSNDK.Tasks -{ - public class BBDeploy : TrackedVCToolTask - { - #region Member Variable Declaration - protected ArrayList switchOrderList; - private string _localManifest; - private const string TRACKER_LOG_DIRECTORY = "TrackerLogDirectory"; - private const string GET_FILE = "GetFile"; - private const string GET_FILE_SAVE_AS = "GetFileSaveAs"; - private const string PUT_FILE = "PutFile"; - private const string PUT_FILE_SAVE_AS = "PutFileSaveAs"; - private const string DEVICE = "Device"; - private const string PASSWORD = "Password"; - private const string PACKAGE_ID = "PackageId"; - private const string PACKAGE_NAME = "PackageName"; - private const string LAUNCH_APP = "LaunchApp"; - private const string INSTALL_APP = "InstallApp"; - private const string LIST_INSTALLED_APPS = "ListInstalledApps"; - private const string DEBUG_NATIVE = "DebugNative"; - private const string PACKAGE = "Package"; - private const string WORKSPACE_LOC = "${workspace_loc:/"; - private string _flagFile; - - #endregion - - /// - /// BBDeploy Constructor - /// - public BBDeploy() - : base(new ResourceManager("VSNDK.Tasks.Properties.Resources", Assembly.GetExecutingAssembly())) - { - this.switchOrderList = new ArrayList(); - this.switchOrderList.Add(INSTALL_APP); - this.switchOrderList.Add(LAUNCH_APP); - this.switchOrderList.Add(LIST_INSTALLED_APPS); - this.switchOrderList.Add(DEBUG_NATIVE); - this.switchOrderList.Add(DEVICE); - this.switchOrderList.Add(PASSWORD); - this.switchOrderList.Add(PACKAGE); - this.switchOrderList.Add(PACKAGE_ID); - this.switchOrderList.Add(PACKAGE_NAME); - this.switchOrderList.Add(GET_FILE); - this.switchOrderList.Add(GET_FILE_SAVE_AS); - this.switchOrderList.Add(PUT_FILE); - this.switchOrderList.Add(PUT_FILE_SAVE_AS); - } - - #region overrides - - /// - /// Helper function to return Response File Switch - /// - /// Path to response file. - /// Return response file switch - protected override string GetResponseFileSwitch(string responseFilePath) - { - return string.Empty; - } - - /// - /// Helper function to generte the command line argument string. - /// - /// command line argument string - protected override string GenerateCommandLineCommands() - { - return GenerateResponseFileCommands(); - } - - /// - /// Helper function to generate response file string - /// - /// response file command line string - protected override string GenerateResponseFileCommands() - { - string cmd = base.GenerateResponseFileCommands(); - - if (ListInstalledApps) - { - cmd += " > installedApps.txt"; - } - - return cmd; - } - - /// - /// Getter for the SwitchOrderList property - /// - protected override ArrayList SwitchOrderList - { - get - { - return this.switchOrderList; - } - } - - /// - /// Getter for the CommandTLogName property - /// - protected override string CommandTLogName - { - get { return "BBDeploy.command.1.tlog"; } - } - - /// - /// Getter for the ReadTLogNames property - /// - protected override string[] ReadTLogNames - { - get { return new string[] { "BBDeploy.read.1.tlog", "BBDeploy.*.read.1.tlog" }; } - } - - /// - /// Getter for the WriteTLogNames property - /// - protected override string[] WriteTLogNames - { - get - { - return new string[] { "BBDeploy.write.1.tlog", "BBDeploy.*.write.1.tlog" }; - } - } - - /// - /// Getter for the TrackedInputFiles property - /// - protected override Microsoft.Build.Framework.ITaskItem[] TrackedInputFiles - { - get - { - // I don't know what this method does but we need to return something other than 'null' or the task doesn't run, - // and adding something like "localManifest.mf" to the list of items causes other problems. - ITaskItem[] items = new ITaskItem[1]; - return items; - } - } - - /// - /// Getter for the ToolName property - /// - protected override string ToolName - { - get - { - return ToolExe; - } - } - - /// - /// Getter for the TrackerIntermediateDirectory property - /// - protected override string TrackerIntermediateDirectory - { - get - { - if (this.TrackerLogDirectory != null) - { - return this.TrackerLogDirectory; - } - return string.Empty; - } - } - - /// - /// Function to return the full path to the tool. - /// - /// - protected override string GenerateFullPathToTool() - { - return this.ToolName; - } - - #endregion overrides - - #region properties - - /// - /// Getter/Setter for the GetFile property - /// Retrieve specified file from default application directory - /// - public virtual string GetFile - { - get - { - if (base.IsPropertySet(GET_FILE)) - { - return base.ActiveToolSwitches[GET_FILE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(GET_FILE); - - // Value passed in is the file to get, relative to our app's directory. - // We determine the app's directory from the PackageName and PackageId. - String toolValue = "../../../../apps/" + PackageName + "." + PackageId + "/" + value; - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = GET_FILE, - DisplayName = "GetFile", - Description = "Get the given file from the application's directory.", - SwitchValue = "-getFile ", - Value = toolValue - }; - base.ActiveToolSwitches.Add(GET_FILE, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the GetFileSaveAs property - /// Retrieve specified file from location. - /// - public virtual string GetFileSaveAs - { - get - { - if (base.IsPropertySet(GET_FILE_SAVE_AS)) - { - return base.ActiveToolSwitches[GET_FILE_SAVE_AS].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(GET_FILE_SAVE_AS); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = GET_FILE_SAVE_AS, - DisplayName = "GetFileSaveAs", - Description = "Save a file retrieved using GetFile to the given location.", - Value = value - }; - base.ActiveToolSwitches.Add(GET_FILE_SAVE_AS, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the PutFile property - /// Save given file to default application directory. - /// - public virtual string PutFile - { - get - { - if (base.IsPropertySet(PUT_FILE)) - { - return base.ActiveToolSwitches[PUT_FILE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PUT_FILE); - //value = value.Replace(".exe", ""); - - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PUT_FILE, - DisplayName = "PutFile", - Description = "Put the given file into the application's directory.", - SwitchValue = "-putFile ", - Value = value - }; - base.ActiveToolSwitches.Add(PUT_FILE, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the PutFileSaveAs property - /// Save given file to specified location - /// - public virtual string PutFileSaveAs - { - get - { - if (base.IsPropertySet(PUT_FILE_SAVE_AS)) - { - return base.ActiveToolSwitches[PUT_FILE_SAVE_AS].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PUT_FILE_SAVE_AS); - - // We determine the app's directory from the PackageName and PackageId. - String toolValue = "../../../../apps/" + PackageName + "." + PackageId + "/" + value; - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PUT_FILE_SAVE_AS, - DisplayName = "PutFileSaveAs", - Description = "Save a file retrieved using PutFile to the given location.", - Value = toolValue - }; - base.ActiveToolSwitches.Add(PUT_FILE_SAVE_AS, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the InstallApp property - Switch to cause deploy to install a given application - /// - public virtual bool InstallApp - { - get - { - return (base.IsPropertySet(INSTALL_APP) && base.ActiveToolSwitches[INSTALL_APP].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(INSTALL_APP); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) - { - Name = INSTALL_APP, - DisplayName = "Install App", - Description = "The -installApp option installs an app from a given package.", - SwitchValue = "-installApp", - BooleanValue = value - }; - base.ActiveToolSwitches.Add(INSTALL_APP, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the LaunchApp Property - Switch to launch given application. - /// - public virtual bool LaunchApp - { - get - { - return (base.IsPropertySet(LAUNCH_APP) && base.ActiveToolSwitches[LAUNCH_APP].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(LAUNCH_APP); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) - { - Name = LAUNCH_APP, - DisplayName = "Launch App", - Description = "The -launchApp option allows an app to be launched with or without being installed.", - SwitchValue = "-launchApp ", - BooleanValue = value - }; - base.ActiveToolSwitches.Add(LAUNCH_APP, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for ListInstalledApps Property. - /// Switch for command to retrieve the list of installed apps. - /// - public virtual bool ListInstalledApps - { - get - { - return (base.IsPropertySet(LIST_INSTALLED_APPS) && base.ActiveToolSwitches[LIST_INSTALLED_APPS].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(LIST_INSTALLED_APPS); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) - { - Name = LIST_INSTALLED_APPS, - DisplayName = "List Installed Apps", - Description = "The -listInstalledApps option does just that.", - SwitchValue = "-listInstalledApps ", - BooleanValue = value - }; - base.ActiveToolSwitches.Add(LIST_INSTALLED_APPS, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Setter for FlagFile property - /// - public string FlagFile - { - set - { - _flagFile = value; - } - } - - /// - /// Getter/Setter for DebugNative property - /// Switch to cause task to install application in debug configuration. - /// - public virtual bool DebugNative - { - get - { - return (base.IsPropertySet(DEBUG_NATIVE) && base.ActiveToolSwitches[DEBUG_NATIVE].BooleanValue); - } - - set - { - if (File.Exists(_flagFile)) - value = true; - - base.ActiveToolSwitches.Remove(DEBUG_NATIVE); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) - { - Name = DEBUG_NATIVE, - DisplayName = "Launch for debugging", - Description = "The -debugNative option launches the app in suspended, ready-to-debug state.", - SwitchValue = "-debugNative ", - BooleanValue = value - }; - base.ActiveToolSwitches.Add(DEBUG_NATIVE, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for Device property. - /// Device property designates the IP of the target device. - /// - public virtual string Device - { - get - { - if (base.IsPropertySet(DEVICE)) - { - return base.ActiveToolSwitches[DEVICE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(DEVICE); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = DEVICE, - DisplayName = "Device IP", - Description = "The -device option specifies the target device's IP address.", - SwitchValue = "-device ", - Value = value - }; - base.ActiveToolSwitches.Add(DEVICE, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for Password property. - /// Password property specifies the target device password. - /// - public virtual string Password - { - get - { - if (base.IsPropertySet(PASSWORD)) - { - return base.ActiveToolSwitches[PASSWORD].Value; - } - return null; - } - set - { - - base.ActiveToolSwitches.Remove(PASSWORD); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PASSWORD, - DisplayName = "Device Password", - Description = "The -password option specifies the target device's password.", - SwitchValue = "-password ", - Value = Decrypt(value) - }; - - base.ActiveToolSwitches.Add(PASSWORD, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for Package property. - /// Package property specified package to be installed/launched on task execution. - /// - public virtual string Package - { - get - { - if (base.IsPropertySet(PACKAGE)) - { - return base.ActiveToolSwitches[PACKAGE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PACKAGE); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PACKAGE, - DisplayName = "Package", - Description = "The -package option specifies a .bar package.", - SwitchValue = "-package ", - Value = value - }; - base.ActiveToolSwitches.Add(PACKAGE, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for PackageId property - /// - [Output] - public virtual string PackageId - { - get - { - if (base.IsPropertySet(PACKAGE_ID)) - { - return base.ActiveToolSwitches[PACKAGE_ID].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PACKAGE_ID); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PACKAGE_ID, - DisplayName = "Package ID", - Description = "The -package-id option specifies the application's package id.", - SwitchValue = "-package-id ", - Value = value - }; - base.ActiveToolSwitches.Add(PACKAGE_ID, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for PackageName property - /// - [Output] - public virtual string PackageName - { - get - { - if (base.IsPropertySet(PACKAGE_NAME)) - { - return base.ActiveToolSwitches[PACKAGE_NAME].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PACKAGE_NAME); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PACKAGE_NAME, - DisplayName = "Package Name", - Description = "The -package-name option specifies the application's package name.", - SwitchValue = "-package-name ", - Value = value - }; - base.ActiveToolSwitches.Add(PACKAGE_NAME, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for LocalManifestFile property - /// We need the local manifest in order to determine PackageId and PackageName. - /// - public virtual string LocalManifestFile - { - get - { - return _localManifest; - } - set - { - _localManifest = value; - - string[] lines = File.ReadAllLines(_localManifest); - - for (int i = 0; i < lines.Length; i++) - { - if (lines[i].StartsWith("Package-Name: ")) - { - string name = lines[i].Substring(14); - if (PackageName != name) - PackageName = name; - } - else if (lines[i].StartsWith("Package-Id: ")) - { - string id = lines[i].Substring(12); - if (PackageId != id) - PackageId = id; - } - } - } - } - - /// - /// Getter/Setter for the TargetManifestFile - /// - [Output] - public virtual string TargetManifestFile - { - get - { - return null; - } - } - - /// - /// Getter/Setter for the TrackerLogDirectory property - /// - public virtual string TrackerLogDirectory - { - get - { - if (base.IsPropertySet(TRACKER_LOG_DIRECTORY)) - { - return base.ActiveToolSwitches[TRACKER_LOG_DIRECTORY].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(TRACKER_LOG_DIRECTORY); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Directory) - { - DisplayName = "Tracker Log Directory", - Description = "Tracker Log Directory.", - Value = VCToolTask.EnsureTrailingSlash(value) - }; - base.ActiveToolSwitches.Add(TRACKER_LOG_DIRECTORY, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - #endregion - - /// - /// Decrypts a given string. - /// - /// A base64 encoded string that was created - /// through the or - /// extension methods. - /// The decrypted string. - /// Keep in mind that the decrypted string remains in memory - /// and makes your application vulnerable per se. If runtime protection - /// is essential, should be used. - /// If - /// is a null reference. - public string Decrypt(string cipher) - { - if (cipher == null) throw new ArgumentNullException("cipher"); - - //parse base64 string - byte[] data = Convert.FromBase64String(cipher); - - //decrypt data - byte[] decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.LocalMachine); - - return Encoding.Unicode.GetString(decrypted); - } - } -} diff --git a/src/VSNDK.Tasks/BBNativePackager.cs b/src/VSNDK.Tasks/BBNativePackager.cs deleted file mode 100644 index 5d02c207..00000000 --- a/src/VSNDK.Tasks/BBNativePackager.cs +++ /dev/null @@ -1,739 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Reflection; -using System.Resources; -using Microsoft.Build.CPPTasks; -using System.Collections; -using Microsoft.Build.Framework; -using System.IO; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - public class BBNativePackager : TrackedVCToolTask - { - #region Member Variable and Constant Declarations - protected ArrayList switchOrderList; - private static BarDescriptor.qnx _descriptor = null; - private string _projDir; - private string _appName; - private string _barDescriptorPath = ""; - private const string OUTPUT_FILE = "OutputFiles"; - private const string APP_DESCRIPTOR = "ApplicationDescriptorXml"; - private const string TARGET_FORMAT = "TargetFormat"; - private const string BUILD_ID = "BuildId"; - private const string BUILD_ID_FILE = "BuildIdFile"; - private const string DEV_MODE = "DevMode"; - private const string PACKAGE_MANIFEST_ONLY = "PackageManifestOnly"; - private const string DEBUG_TOKEN = "DebugToken"; - private const string SOURCES = "Sources"; - private const string TRACKER_LOG_DIRECTORY = "TrackerLogDirectory"; - private const string GET_TARGET_FILE_MAP = "GetTargetFileMap"; - private const string WORKSPACE_LOC = "${workspace_loc:/"; - #endregion - - /// - /// BBNativePackager Constructor - /// - public BBNativePackager() - : base(new ResourceManager("VSNDK.Tasks.Properties.Resources", Assembly.GetExecutingAssembly())) - { - this.switchOrderList = new ArrayList(); - this.switchOrderList.Add(TARGET_FORMAT); - this.switchOrderList.Add(BUILD_ID); - this.switchOrderList.Add(BUILD_ID_FILE); - this.switchOrderList.Add(DEV_MODE); - this.switchOrderList.Add(GET_TARGET_FILE_MAP); - this.switchOrderList.Add(PACKAGE_MANIFEST_ONLY); - this.switchOrderList.Add(OUTPUT_FILE); - this.switchOrderList.Add(APP_DESCRIPTOR); - this.switchOrderList.Add(TRACKER_LOG_DIRECTORY); - } - - #region overrides - - - /// - /// Return the response file switch. - /// Note: Don't use response file for msbuild because it is removed before qcc to run GCC compiler - /// - /// Response File Path - /// Response File Switch - protected override string GetResponseFileSwitch(string responseFilePath) - { - return string.Empty; - } - - /// - /// Return the Command Line String. - /// Note: pass the response file to command line commands - /// - /// Command Line String - protected override string GenerateCommandLineCommands() - { - return GenerateResponseFileCommands(); - } - - /// - /// Return the Response File Command String - /// - /// - protected override string GenerateResponseFileCommands() - { - string cmd = base.GenerateResponseFileCommands(); - PackagerCmdBuilder clb = new PackagerCmdBuilder(); - AppendResources(clb); - cmd += " " + clb.ToString(); - - // Output the .bar file's manifest to a file so we can parse it. - if (PackageManifestOnly) - { - cmd += " > localManifest.mf"; - } - else if (GetTargetFileMap) - { - cmd += " > targetFileMap.txt"; - } - - return cmd; - } - - /// - /// Helper function to read the assets from the bar-descriptor.xml file and - /// generate the command line listing the resources to be packaged into the bar file. - /// - /// Command Line Builder object - private void AppendResources(CommandLineBuilder clb) - { - ITaskItem[] sources = GetAssetsFile(); - foreach (ITaskItem item in sources) - { - string target = item.GetMetadata("target"); - if (item.ItemSpec == target) - clb.AppendFileNameIfNotNull(item); - else - { - clb.AppendSwitchIfNotNull("-e ", item); - clb.AppendFileNameIfNotNull(target); - } - } - } - - /// - /// Return the assets from the bardescriptor.xml - /// - /// - private ITaskItem[] GetAssetsFile() - { - - //make sure the _descriptor is loaded - if (_descriptor == null) - { - _descriptor = BarDescriptor.Parser.Load(Path.Combine(ProjectDir, ApplicationDescriptorXml)); - } - BarDescriptor.asset[] globalAssets = _descriptor.assets; - BarDescriptor.asset[] configAssets = null; - - // You can call a configuration whatever you like, but these are the ones Momentics uses for its various - // platform + configuration combinations. Usually this is the same as the output directory, but asset paths - // don't have anything to do with the configuration name. I've based the config names on the platform - // + configuration combination, not the output directory. - BarDescriptor.qnxConfiguration[] configs = _descriptor.configurations; - foreach (BarDescriptor.qnxConfiguration config in configs) - { - if (Configuration == "Debug" && Platform == "BlackBerry" && config.name == "Device-Debug") - { - configAssets = config.asset; - break; - } - else if (Configuration == "Release" && Platform == "BlackBerry" && config.name == "Device-Release") - { - configAssets = config.asset; - break; - } - else if (Configuration == "Profile" && Platform == "BlackBerry" && config.name == "Device-Profile") - { - configAssets = config.asset; - break; - } - else if (Configuration == "Coverage" && Platform == "BlackBerry" && config.name == "Device-Coverage") - { - configAssets = config.asset; - break; - } - else if (Configuration == "Debug" && Platform == "BlackBerrySimulator" && (config.name == "Simulator" || config.name == "Simulator-Debug")) - { - configAssets = config.asset; - break; - } - else if (Configuration == "Profile" && Platform == "BlackBerrySimulator" && config.name == "Simulator-Profile") - { - configAssets = config.asset; - break; - } - else if (Configuration == "Coverage" && Platform == "BlackBerrySimulator" && config.name == "Simulator-Coverage") - { - configAssets = config.asset; - break; - } - else if (Configuration == "Release" && Platform == "BlackBerrySimulator" && config.name == "Simulator-Release") - { - configAssets = config.asset; - break; - } - } - - ITaskItem[] items = null; - - - int clen = (configAssets == null) ? 0 : configAssets.Length; - int glen = (globalAssets == null) ? 0 : globalAssets.Length; - - items = new ITaskItem[glen + clen]; - - for (int i = 0; i < glen; i++) - { - string path = globalAssets[i].path; - path = path.Replace("}", string.Empty).Replace(WORKSPACE_LOC, SolutionDir); - string target = globalAssets[i].Value; - items[i] = new TaskItem(path); - items[i].SetMetadata("target", target); - } - - - if (configAssets != null) - { - for (int i = 0; i < configAssets.Length; i++) - { - string path = configAssets[i].path; - path = path.Replace("}", string.Empty).Replace(WORKSPACE_LOC, SolutionDir); - string target = configAssets[i].Value; - items[i + glen] = new TaskItem(path); - items[i + glen].SetMetadata("target", target); - } - } - - return items; - - } - - /// - /// Getter for the SwitchOrderList property - /// - protected override ArrayList SwitchOrderList - { - get - { - return this.switchOrderList; - } - } - - /// - /// Getter for the CommandTLogName property - /// - protected override string CommandTLogName - { - get { return "BBNativePackager.command.1.tlog"; } - } - - /// - /// Getter for the ReadTLogNames property. - /// - protected override string[] ReadTLogNames - { - get { return new string[] { "BBNativePackager.read.1.tlog", "BBNativePackager.*.read.1.tlog" }; } - } - - /// - /// Getter for the WriteTLogNames property - /// - protected override string[] WriteTLogNames - { - get - { - return new string[] { "BBNativePackager.write.1.tlog", "BBNativePackager.*.write.1.tlog" }; - } - } - - /// - /// Getter for the ToolName property - /// - protected override string ToolName - { - get - { - return ToolExe; - } - } - - #endregion overrides - - #region properties - - /// - /// Getter/Setter for Device property - /// - [Output] - public virtual string Device { get; set; } - - /// - /// Getter/Setter for Password property - /// - [Output] - public virtual string Password { get; set;} - - /// - /// Getter/Setter for BarDeploy property - /// - [Output] - public virtual string BarDeploy { get; set; } - - /// - /// Getter/Setter for OutputFile property - /// - [Required] - [Output] - public virtual string OutputFile - { - get - { - if (base.IsPropertySet(OUTPUT_FILE) && base.IsExplicitlySetToFalse(PACKAGE_MANIFEST_ONLY)) - { - return base.ActiveToolSwitches[OUTPUT_FILE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(OUTPUT_FILE); - - String switchValue = ""; - if (base.IsPropertySet(OUTPUT_FILE) && base.IsExplicitlySetToFalse(PACKAGE_MANIFEST_ONLY)) - { - switchValue = "-package "; - } - - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Output bar file name, for example, out.bar", - Description = "The -package option specifies the bar file name.", - ArgumentRelationList = new ArrayList(), - SwitchValue = switchValue, - Name = OUTPUT_FILE, - Value = value - }; - base.ActiveToolSwitches.Add(OUTPUT_FILE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for ProjectDir property - /// - [Required] - public virtual string ProjectDir - { - get - { - return _projDir; - } - set - { - _projDir = value; - _descriptor = BarDescriptor.Parser.Load(Path.Combine(ProjectDir, ApplicationDescriptorXml)); - } - } - - /// - /// Getter/Setter for AppName property - /// - [Required] - public virtual string AppName - { - get - { - return _appName; - } - set - { - _appName = value; - - if (_barDescriptorPath == "") - { - // Default location of bar-descriptor file, if not specified in the Properties Configurations. - _barDescriptorPath = "BlackBerry-" + _appName + "\\bar-descriptor.xml"; - if (!File.Exists(_barDescriptorPath)) - { - // Just to support the default locations of bar-descriptor from previous versions of the plug-in. - _barDescriptorPath = _appName + "_barDescriptor\\bar-descriptor.xml"; - if (!File.Exists(_barDescriptorPath)) - { - _barDescriptorPath = "bar-descriptor.xml"; - } - } - } - - base.ActiveToolSwitches.Remove(APP_DESCRIPTOR); - - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Application descriptor file name, for example, bar-descriptor.xml", - Description = "Application descriptor file name, for example, bar-descriptor.xml, it must follows the out.bar file", - ArgumentRelationList = new ArrayList(), - Name = APP_DESCRIPTOR, - Value = _barDescriptorPath - }; - base.ActiveToolSwitches.Add(APP_DESCRIPTOR, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for SolutionDir property - /// - [Required] - public virtual string SolutionDir { get; set; } - - public virtual string ApplicationDescriptorXml - { - get - { - if (base.IsPropertySet(APP_DESCRIPTOR)) - { - return base.ActiveToolSwitches[APP_DESCRIPTOR].Value; - } - return null; - } - set - { - _barDescriptorPath = value; - } - } - - /// - /// Getter/Setter for TargetFormat property - /// - public virtual string TargetFormat - { - get - { - if (base.IsPropertySet(TARGET_FORMAT)) - { - return base.ActiveToolSwitches[TARGET_FORMAT].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(TARGET_FORMAT); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Target format", - Description = "Select the build target format( -target bar -target bar-debug)", - ArgumentRelationList = new ArrayList() - }; - string[][] switchMap = new string[][] - { - new string[] { "bar", "-target bar" }, - new string[] { "bar-debug", "-target bar-debug" } - }; - switch2.SwitchValue = base.ReadSwitchMap(TARGET_FORMAT, switchMap, value); - switch2.Name = TARGET_FORMAT; - switch2.Value = value; - switch2.MultiValues = true; - base.ActiveToolSwitches.Add(TARGET_FORMAT, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for BuildID property - /// - public virtual int BuildID - { - get - { - if (base.IsPropertySet(BUILD_ID)) - { - return base.ActiveToolSwitches[BUILD_ID].Number; - } - return 0; - } - set - { - base.ActiveToolSwitches.Remove(BUILD_ID); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Integer) - { - DisplayName = "Build Id", - Description = "set the build id ( the fourth segment of the version ). Must be a number from 0 to 65535" - }; - switch2.ArgumentRelationList = new ArrayList(); - switch2.IsValid = base.ValidateInteger(BUILD_ID, 0, 65535, value); - switch2.Name = BUILD_ID; - switch2.Number = value; - switch2.SwitchValue = "-buildId "; - base.ActiveToolSwitches.Add(BUILD_ID, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for BuildIDFile property - /// - public virtual string BuildIDFile - { - get - { - if (base.IsPropertySet(BUILD_ID_FILE)) - { - return base.ActiveToolSwitches[BUILD_ID_FILE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(BUILD_ID_FILE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Build ID File", - Description = "set the build ID from an existing file", - ArgumentRelationList = new ArrayList(), - Name = BUILD_ID_FILE, - SwitchValue = "-buildIdFile ", - Value = value - }; - base.ActiveToolSwitches.Add(BUILD_ID_FILE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for DevMode property - /// - public virtual bool DevMode - { - get - { - return (base.IsPropertySet(DEV_MODE) && base.ActiveToolSwitches[DEV_MODE].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(DEV_MODE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - Name = DEV_MODE, - DisplayName = "Development mode", - Description = "Package in development mode ( -devMode)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-devMode", - BooleanValue = value - }; - base.ActiveToolSwitches.Add(DEV_MODE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for PackageManifestOnly property - /// - public virtual bool PackageManifestOnly - { - get - { - return (base.IsPropertySet(PACKAGE_MANIFEST_ONLY) && base.ActiveToolSwitches[PACKAGE_MANIFEST_ONLY].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(PACKAGE_MANIFEST_ONLY); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Package manifest only.", - Description = "Package only the manifest file ( -packageManifest)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-packageManifest -listManifest ", - Name = PACKAGE_MANIFEST_ONLY, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(PACKAGE_MANIFEST_ONLY, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for GetTargetFileMap property - /// - public virtual bool GetTargetFileMap - { - get - { - return (base.IsPropertySet(GET_TARGET_FILE_MAP) && base.ActiveToolSwitches[GET_TARGET_FILE_MAP].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(GET_TARGET_FILE_MAP); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) - { - Name = GET_TARGET_FILE_MAP, - DisplayName = "Get target file map", - Description = "Get the mapping between local and target files with the -targetFileMap option.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-targetFileMap ", - BooleanValue = value - }; - base.ActiveToolSwitches.Add(GET_TARGET_FILE_MAP, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for DebugToken property - /// - public virtual string DebugToken - { - get - { - if (base.IsPropertySet(DEBUG_TOKEN)) - { - return base.ActiveToolSwitches[DEBUG_TOKEN].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(DEBUG_TOKEN); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Directory) - { - DisplayName = "Debug Token", - Description = "Use debug token to generate author and author id ( -debugToken only usable with -devMode)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-debugToken ", - Value = value - }; - switch2.Parents.AddLast(DEV_MODE); - base.ActiveToolSwitches.Add(DEBUG_TOKEN, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for TrackerLogDirectory property. - /// - public virtual string TrackerLogDirectory - { - get - { - if (base.IsPropertySet(TRACKER_LOG_DIRECTORY)) - { - return base.ActiveToolSwitches[TRACKER_LOG_DIRECTORY].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(TRACKER_LOG_DIRECTORY); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Directory) - { - DisplayName = "Tracker Log Directory", - Description = "Tracker Log Directory.", - ArgumentRelationList = new ArrayList(), - Value = VCToolTask.EnsureTrailingSlash(value) - }; - base.ActiveToolSwitches.Add(TRACKER_LOG_DIRECTORY, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - #endregion properties - - /// - /// Getter for the TrackedInputFiles - /// - protected override Microsoft.Build.Framework.ITaskItem[] TrackedInputFiles - { - get - { - return Sources; - } - } - - /// - /// Getter for the TrackerIntermediateDirectory - /// - protected override string TrackerIntermediateDirectory - { - get - { - if (this.TrackerLogDirectory != null) - { - return this.TrackerLogDirectory; - } - return string.Empty; - } - } - - /// - /// Getter/Seter for the Sources property - /// - [Required] - public virtual ITaskItem[] Sources - { - get - { - if (base.IsPropertySet(SOURCES)) - { - return base.ActiveToolSwitches[SOURCES].TaskItemArray; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(SOURCES); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.ITaskItemArray) - { - Separator = " ", - Required = true, - ArgumentRelationList = new ArrayList(), - TaskItemArray = value - }; - base.ActiveToolSwitches.Add(SOURCES, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the Configuration property - /// - [Required] - public string Configuration - { - get; - set; - } - - /// - /// Getter/Setter for the Platform property - /// - [Required] - public string Platform - { - get; - set; - } - } -} diff --git a/src/VSNDK.Tasks/BBSigner.cs b/src/VSNDK.Tasks/BBSigner.cs deleted file mode 100644 index 5a1cc04a..00000000 --- a/src/VSNDK.Tasks/BBSigner.cs +++ /dev/null @@ -1,411 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Reflection; -using System.Resources; -using Microsoft.Build.CPPTasks; -using System.Collections; -using Microsoft.Build.Framework; -using System.IO; -using Microsoft.Build.Utilities; -using System.Security.Cryptography; - -namespace VSNDK.Tasks -{ - /// - /// MSBuild Task responsible for the signing of the BlackBerry Bar files - /// for deploy to a secure device not in development mode. - /// - public class BBSigner : TrackedVCToolTask - { - #region Member Variables and Constants Declaration - protected ArrayList switchOrderList; - private const string REGISTER = "Register"; - private const string KEYSTOREPASSWORD = "KeyStorePassword"; - private const string CSJPIN = "CSJPin"; - private const string CSJFILES = "Signing_AND_DEBUGTOKEN_CSJFiles"; - private const string SOURCES = "Sources"; - private const string OUTPUT_FILE = "OutputFiles"; - private const string TRACKER_LOG_DIRECTORY = "TrackerLogDirectory"; - #endregion - - /// - /// BBSigner Constructor Fuction - /// - public BBSigner() - : base(new ResourceManager("VSNDK.Tasks.Properties.Resources", Assembly.GetExecutingAssembly())) - { - this.switchOrderList = new ArrayList(); - this.switchOrderList.Add("AlwaysAppend"); - this.switchOrderList.Add(REGISTER); - this.switchOrderList.Add(CSJPIN); - this.switchOrderList.Add(KEYSTOREPASSWORD); - this.switchOrderList.Add(CSJFILES); - this.switchOrderList.Add(OUTPUT_FILE); - this.switchOrderList.Add(TRACKER_LOG_DIRECTORY); - } - - - #region overrides - - /// - /// Return the GetResposeFile Switch - /// Note: don't use response file for msbuild because it is removed before qcc to run GCC compiler - /// - /// - /// - protected override string GetResponseFileSwitch(string responseFilePath) - { - return string.Empty; - } - - /// - /// Return the command line argument string - /// Note: pass the response file to command line commands - /// - /// - protected override string GenerateCommandLineCommands() - { - return GenerateResponseFileCommands(); - } - - /// - /// Return the Response File Commands string. - /// - /// - protected override string GenerateResponseFileCommands() - { - if (!Register) - { - switchOrderList.Remove(REGISTER); - switchOrderList.Remove(CSJPIN); - switchOrderList.Remove(CSJFILES); - } - else - switchOrderList.Remove(OUTPUT_FILE); - return base.GenerateResponseFileCommands(); - } - - /// - /// Getter for the SwitchOrderList property - /// - protected override ArrayList SwitchOrderList - { - get - { - return this.switchOrderList; - } - } - - /// - /// Getter for the CommandTLogName property - /// - protected override string CommandTLogName - { - get { return "BBSigner.command.1.tlog"; } - } - - /// - /// Getter for the ReadTLogNames property - /// - protected override string[] ReadTLogNames - { - get { return new string[] { "BBSigner.read.1.tlog", "BBSigner.*.read.1.tlog" }; } - } - protected override string[] WriteTLogNames - { - get - { - return new string[] { "BBSigner.write.1.tlog", "BBSigner.*.write.1.tlog" }; - } - } - - /// - /// Getter for the ToolName property - /// - protected override string ToolName - { - get - { - return ToolExe; - } - } - - /// - /// Getter for the TrackerIntermediateDirectory property - /// - protected override string TrackerIntermediateDirectory - { - get - { - if (this.TrackerLogDirectory != null) - { - return this.TrackerLogDirectory; - } - return string.Empty; - } - } - - /// - /// Getter for the TrackedInputFiles property - /// - protected override ITaskItem[] TrackedInputFiles - { - get { return Sources; } - } - - #endregion overrides - - #region properties - - /// - /// Getter/Setter for the Register property - /// - [Required] - public virtual bool Register - { - get - { - return (base.IsPropertySet(REGISTER) && base.ActiveToolSwitches[REGISTER].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(REGISTER); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Register", - Description = "Register the computer with CSJ file to sign application( -register)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-register", - Name = REGISTER, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(REGISTER, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the Sources property - /// - [Required] - public virtual ITaskItem[] Sources - { - get - { - if (base.IsPropertySet(SOURCES)) - { - return base.ActiveToolSwitches[SOURCES].TaskItemArray; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(SOURCES); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.ITaskItemArray) - { - Separator = " ", - Required = true, - ArgumentRelationList = new ArrayList(), - TaskItemArray = value - }; - base.ActiveToolSwitches.Add(SOURCES, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the CSJFiles property - /// - public virtual ITaskItem[] CSJFiles - { - get - { - if (base.IsPropertySet(CSJFILES)) - { - return base.ActiveToolSwitches[CSJFILES].TaskItemArray; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(CSJFILES); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.ITaskItemArray) - { - Separator = " ", - Required = true, - ArgumentRelationList = new ArrayList(), - Name = CSJFILES, - TaskItemArray = value - }; - base.ActiveToolSwitches.Add(CSJFILES, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the KeyStorePassword property - /// - public virtual string KeyStorePassword - { - get - { - if (base.IsPropertySet(KEYSTOREPASSWORD)) - { - return base.ActiveToolSwitches[KEYSTOREPASSWORD].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(KEYSTOREPASSWORD); - - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Keystore password", - Description = "The -storepass option specifies the password.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-storepass ", - Name = KEYSTOREPASSWORD, - Value = Decrypt(value) - }; - - base.ActiveToolSwitches.Add(KEYSTOREPASSWORD, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Decrypts a given string. - /// - /// A base64 encoded string that was created - /// through the or - /// extension methods. - /// The decrypted string. - /// Keep in mind that the decrypted string remains in memory - /// and makes your application vulnerable per se. If runtime protection - /// is essential, should be used. - /// If - /// is a null reference. - public string Decrypt(string cipher) - { - if (cipher == null) throw new ArgumentNullException("cipher"); - - //parse base64 string - byte[] data = Convert.FromBase64String(cipher); - - //decrypt data - byte[] decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.LocalMachine); - - return Encoding.Unicode.GetString(decrypted); - } - - /// - /// Getter/Setter for the CSJPin property - /// - public virtual string CSJPin - { - get - { - if (base.IsPropertySet(CSJPIN)) - { - return base.ActiveToolSwitches[CSJPIN].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(CSJPIN); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Keystore password", - Description = "The -csjpin option specifies the password.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-csjpin ", - Name = CSJPIN, - Value = value - }; - base.ActiveToolSwitches.Add(CSJPIN, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the OutputFile property - /// - [Required] - [Output] - public virtual string OutputFile - { - get - { - if (base.IsPropertySet(OUTPUT_FILE)) - { - return base.ActiveToolSwitches[OUTPUT_FILE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(OUTPUT_FILE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Output bar file name to be signed", - Description = "Specifies the bar file name to be signed", - ArgumentRelationList = new ArrayList(), - Name = OUTPUT_FILE, - Value = value - }; - base.ActiveToolSwitches.Add(OUTPUT_FILE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the TrackerLogDirectory property - /// - public virtual string TrackerLogDirectory - { - get - { - if (base.IsPropertySet(TRACKER_LOG_DIRECTORY)) - { - return base.ActiveToolSwitches[TRACKER_LOG_DIRECTORY].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(TRACKER_LOG_DIRECTORY); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Directory) - { - DisplayName = "Tracker Log Directory", - Description = "Tracker Log Directory.", - ArgumentRelationList = new ArrayList(), - Value = VCToolTask.EnsureTrailingSlash(value) - }; - base.ActiveToolSwitches.Add(TRACKER_LOG_DIRECTORY, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - #endregion properties - - } -} - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BarDescriptor/Parser.cs b/src/VSNDK.Tasks/BarDescriptor/Parser.cs deleted file mode 100644 index a3ed76de..00000000 --- a/src/VSNDK.Tasks/BarDescriptor/Parser.cs +++ /dev/null @@ -1,54 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Xml; -using System.Xml.Serialization; -using System.Diagnostics; - -namespace VSNDK.Tasks.BarDescriptor -{ - public class Parser - { - /// - /// Helper function to to deserialize the bar-descriptor.xml file for read. - /// - /// Path to the bar-descriptor.xml file - /// BarDescriptor.qnx object containing the deserialized data from the bar-descriptor. - public static BarDescriptor.qnx Load(string filename) - { - if (!string.IsNullOrEmpty(filename)) - { - try - { - using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) - { - XmlTextReader reader = new XmlTextReader(fs); - XmlSerializer serializer = new XmlSerializer(typeof(BarDescriptor.qnx)); - return serializer.Deserialize(reader) as BarDescriptor.qnx; - } - } - catch (Exception ex) - { - Debug.WriteLine(ex.Message); - } - } - return null; - } - } -} diff --git a/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.cs b/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.cs deleted file mode 100644 index 75f4b3a0..00000000 --- a/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.cs +++ /dev/null @@ -1,459 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.239 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -// -// This source code was auto-generated by xsd, Version=4.0.30319.1. -// -namespace VSNDK.Tasks.BarDescriptor { - using System.Xml.Serialization; - - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.qnx.com/schemas/application/1.0", IsNullable=true)] - public partial class asset { - - private string pathField; - - private string entryField; - - private string typeField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string path { - get { - return this.pathField; - } - set { - this.pathField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string entry { - get { - return this.entryField; - } - set { - this.entryField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string type { - get { - return this.typeField; - } - set { - this.typeField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value { - get { - return this.valueField; - } - set { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.qnx.com/schemas/application/1.0", IsNullable=false)] - public partial class qnx { - - private string idField; - - private string nameField; - - private string versionNumberField; - - private string buildIdField; - - private string descriptionField; - - private string authorField; - - private string categoryField; - - private qnxInitialWindow[] initialWindowField; - - private asset[] assetField; - - private qnxConfiguration[] configurationField; - - private qnxIcon[] iconField; - - private qnxAction[] actionField; - - private qnxEnv[] envField; - - /// - public string id { - get { - return this.idField; - } - set { - this.idField = value; - } - } - - /// - public string name { - get { - return this.nameField; - } - set { - this.nameField = value; - } - } - - /// - public string versionNumber { - get { - return this.versionNumberField; - } - set { - this.versionNumberField = value; - } - } - - /// - public string buildId { - get { - return this.buildIdField; - } - set { - this.buildIdField = value; - } - } - - /// - public string description { - get { - return this.descriptionField; - } - set { - this.descriptionField = value; - } - } - - /// - public string author { - get { - return this.authorField; - } - set { - this.authorField = value; - } - } - - /// - public string category { - get { - return this.categoryField; - } - set { - this.categoryField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("initialWindow")] - public qnxInitialWindow[] initialWindows { - get { - return this.initialWindowField; - } - set { - this.initialWindowField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("asset", IsNullable=true)] - public asset[] assets { - get { - return this.assetField; - } - set { - this.assetField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("configuration")] - public qnxConfiguration[] configurations { - get { - return this.configurationField; - } - set { - this.configurationField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("icon")] - public qnxIcon[] icons { - get { - return this.iconField; - } - set { - this.iconField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("action", IsNullable=true)] - public qnxAction[] actions { - get { - return this.actionField; - } - set { - this.actionField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("env")] - public qnxEnv[] envs { - get { - return this.envField; - } - set { - this.envField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxInitialWindow { - - private string aspectRatioField; - - private string autoOrientsField; - - private string systemChromeField; - - private string transparentField; - - /// - public string aspectRatio { - get { - return this.aspectRatioField; - } - set { - this.aspectRatioField = value; - } - } - - /// - public string autoOrients { - get { - return this.autoOrientsField; - } - set { - this.autoOrientsField = value; - } - } - - /// - public string systemChrome { - get { - return this.systemChromeField; - } - set { - this.systemChromeField = value; - } - } - - /// - public string transparent { - get { - return this.transparentField; - } - set { - this.transparentField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxConfiguration { - - private string platformArchitectureField; - - private asset[] assetField; - - private string idField; - - private string nameField; - - /// - public string platformArchitecture { - get { - return this.platformArchitectureField; - } - set { - this.platformArchitectureField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("asset", IsNullable=true)] - public asset[] asset { - get { - return this.assetField; - } - set { - this.assetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string id { - get { - return this.idField; - } - set { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name { - get { - return this.nameField; - } - set { - this.nameField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxIcon { - - private string imageField; - - /// - public string image { - get { - return this.imageField; - } - set { - this.imageField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxAction { - - private string systemField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string system { - get { - return this.systemField; - } - set { - this.systemField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value { - get { - return this.valueField; - } - set { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] - public partial class qnxEnv { - - private string varField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string var { - get { - return this.varField; - } - set { - this.varField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value { - get { - return this.valueField; - } - set { - this.valueField = value; - } - } - } -} diff --git a/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.xml b/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.xml deleted file mode 100644 index 3255bb8c..00000000 --- a/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - com.rim.sample00_mesh - - - Mesh - - - 1.0.0 - - - 1 - - - - - - Mesh Sample - - - - - - BlackBerry - - - - - - landscape - false - none - false - - - - core.games - - res - res/shaders/diffuse-specular.fsh - res/shaders/diffuse-specular.vsh - - - armle-v7 - sample00-mesh - - - armle-v7 - sample00-mesh - - - armle-v7 - sample00-mesh - - - armle-v7 - sample00-mesh - - - x86 - sample00-mesh - - - x86 - sample00-mesh - - - x86 - sample00-mesh - - - - - - - - - - - run_native - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.xsd b/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.xsd deleted file mode 100644 index 5601be8a..00000000 --- a/src/VSNDK.Tasks/BarDescriptor/Schema/bar-descriptor.xsd +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.bak b/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.bak deleted file mode 100644 index 9b820843..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.bak +++ /dev/null @@ -1,422 +0,0 @@ - - - - - - - - - - - - - - - - - - true - - - - true - - - - true - - - - - $(BuildLinkTargets); - - $(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets) - - - - - - - - - - - - - - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - false - false - - - - - - - - - - - - - - - - - - - - - - - false - true - $(BuildBarToolPath) - $(OptimizedDeployToolPath) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets b/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets deleted file mode 100644 index 5eb31d68..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets +++ /dev/null @@ -1,412 +0,0 @@ - - - - - - - - - - - - - - - - - - true - - - - true - - - - true - - - - - $(BuildLinkTargets); - - $(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets) - - - - - - - - - - - - - - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - false - false - - - - - - - - - - - - - - - - - - - - - - - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.bak b/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.bak deleted file mode 100644 index 5d62f2b8..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.bak +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - QCC;__QCC__;__QNX__ - false - - - - - true - false - - - - - true - .a - lib - - - - true - - - - - - true - .so - true - lib - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - - - - - - $(IntDir)%(FileName).o - $(QccDefines) - WIN32;_WINDOWS - NormalWarnings - false - false - - true - - false - false - Default - true - - - - - - - O2 - true - - - - - - - O2 - false - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - $(TargetPath) - - - false - false - true - false - true - Default - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - false - - - - - - - $(IntDir) - true - $(OutDir)$(TargetName).bar - true - false - bar-debug - bar - true - false - None - Install - false - 1 - - - - - 169.254.0.1 - - bar-descriptor.xml - $(AppData) - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.bak b/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.bak deleted file mode 100644 index 40c79c30..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.bak +++ /dev/null @@ -1,23 +0,0 @@ - - - - - BlackBerry - qcc - - $(IntermediateOutputPath) - Device-$(Configuration)\ - Device-$(Configuration)\ - $(IntDir) - - diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props b/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props deleted file mode 100644 index 40c79c30..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props +++ /dev/null @@ -1,23 +0,0 @@ - - - - - BlackBerry - qcc - - $(IntermediateOutputPath) - Device-$(Configuration)\ - Device-$(Configuration)\ - $(IntDir) - - diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.props b/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.props deleted file mode 100644 index 5d62f2b8..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.props +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - QCC;__QCC__;__QNX__ - false - - - - - true - false - - - - - true - .a - lib - - - - true - - - - - - true - .so - true - lib - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - - - - - - $(IntDir)%(FileName).o - $(QccDefines) - WIN32;_WINDOWS - NormalWarnings - false - false - - true - - false - false - Default - true - - - - - - - O2 - true - - - - - - - O2 - false - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - $(TargetPath) - - - false - false - true - false - true - Default - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - false - - - - - - - $(IntDir) - true - $(OutDir)$(TargetName).bar - true - false - bar-debug - bar - true - false - None - Install - false - 1 - - - - - 169.254.0.1 - - bar-descriptor.xml - $(AppData) - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets b/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets deleted file mode 100644 index 8ed03106..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets +++ /dev/null @@ -1,188 +0,0 @@ - - - - - - - - - - - - - true - - - - - - - CompileAsC - CompileAsCpp - false - - - - - - - $(DefaultToolArchitecture) - - - - - - - - - - - - - - - - - - false - - - - - $(DefaultToolArchitecture) - - - - - - - - - - - - - false - false - true - $(DefaultToolArchitecture) - true - - - - - - CompileAsC - CompileAsCpp - - - - - - - - - - - - - - - $(CleanDependsOn); - MakeClean; - - - - - - - - - - - - PlatformPrepareForBuild;$(PrepareForBuildDependsOn) - PlatformPrepareForBuild;$(PrepareForBuildDependsOn) - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Microsoft.CppBuild.BlackBerry.targets b/src/VSNDK.Tasks/BlackBerry/Microsoft.CppBuild.BlackBerry.targets deleted file mode 100644 index 196ff386..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Microsoft.CppBuild.BlackBerry.targets +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - false - false - false - - - - - - - - - - - - - - - - - - PropertySheet - - - - - - - - - - - - - - - - Project - - - PropertySheet - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.bak b/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.bak deleted file mode 100644 index 0f92e06d..00000000 --- a/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.bak +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - $(Registry:HKEY_CURRENT_USER\SOFTWARE\Research In Motion\BlackBerryVSPlugin@NDKPath) - $(NativeSDKDir)\target\qnx6 - $(NativeSDKDir)\host\win32\x86 - $(QNX_HOST)\etc\qcc\gcc - armle-v7 - 4.6.3 - gcc_ntoarmv7le - $(QNX_TARGET)\$(CPUVARDIR)\lib - - - - qcc2.0 - $(QNX_HOST)\usr\bin - qcc.exe - qcc.exe - qcc.exe - blackberry-nativepackager.bat - blackberry-signer.bat - blackberry-deploy.bat - $(QccToolsPath) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework@InstallRoot) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework@InstallRoot) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(QNX_HOST)\usr\bin;$(PATH); - $(QNX_TARGET)\usr\include;$(QNX_TARGET)\usr\include\freetype2;$(QNX_TARGET)\..\target-override\usr\include; - $(QccLibPath);$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\lib;$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\usr\lib; - $(ExecutablePath) - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props b/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props deleted file mode 100644 index 3ae3e8c3..00000000 --- a/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin@NDKTargetPath) - $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin@NDKHostPath) - $([System.IO.File]::ReadAllText("$(QNX_HOST)\etc\qcc\gcc\default").Substring(4,5)) - $(QNX_HOST)\etc\qcc\gcc - armle-v7 - $(from_file) - gcc_ntoarmv7le - $(QNX_TARGET)\$(CPUVARDIR)\lib - $(AppData) - $(AppDataPath)/BlackBerry/bbt_id_rsa.pub - $(AppDataPath)/BlackBerry/bbt_id_rsa - - - - VSNDKDebugEngine - - - - qcc2.0 - $(QNX_HOST)\usr\bin - qcc.exe - qcc.exe - qcc.exe - blackberry-nativepackager.bat - $(MSBuildProgramFiles32)\BlackBerry\VSPlugin-NDK\qnxtools\bin\blackberry-signer.bat - blackberry-deploy.bat - $(QccToolsPath) - ssh.exe - $(QccToolsPath) - $(QccToolsPath)\ssh-keygen.exe - $(QccToolsPath)\blackberry-connect.bat - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework@InstallRoot) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework@InstallRoot) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(QNX_HOST)\usr\bin;$(PATH); - $(QNX_TARGET)\usr\include;$(QNX_TARGET)\usr\include\freetype2;$(QNX_TARGET)\..\target-override\usr\include;$(QNX_TARGET)\usr\include\cpp;$(QNX_TARGET)\usr\include\cpp\c - $(QccLibPath);$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\lib;$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\usr\lib; - - $(ExecutablePath) - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.targets b/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.targets deleted file mode 100644 index 55b83ab2..00000000 --- a/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.targets +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/debugger_ndk.xml b/src/VSNDK.Tasks/BlackBerry/Rules/debugger_ndk.xml deleted file mode 100644 index cb53a5b7..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Rules/debugger_ndk.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/ndk_general.xml b/src/VSNDK.Tasks/BlackBerry/Rules/ndk_general.xml deleted file mode 100644 index 2b834759..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Rules/ndk_general.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/ndk_general_ps.xml b/src/VSNDK.Tasks/BlackBerry/Rules/ndk_general_ps.xml deleted file mode 100644 index d7389bc0..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Rules/ndk_general_ps.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/packager.xml b/src/VSNDK.Tasks/BlackBerry/Rules/packager.xml deleted file mode 100644 index 22e801e8..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Rules/packager.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/qcc_cl.xml b/src/VSNDK.Tasks/BlackBerry/Rules/qcc_cl.xml deleted file mode 100644 index 90de68d9..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Rules/qcc_cl.xml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/qcc_lib.xml b/src/VSNDK.Tasks/BlackBerry/Rules/qcc_lib.xml deleted file mode 100644 index aa53f443..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Rules/qcc_lib.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/qcc_link.xml b/src/VSNDK.Tasks/BlackBerry/Rules/qcc_link.xml deleted file mode 100644 index c35bcb63..00000000 --- a/src/VSNDK.Tasks/BlackBerry/Rules/qcc_link.xml +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.Packager.bak b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.Packager.bak deleted file mode 100644 index daea93ed..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.Packager.bak +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - - - - - - - - - - - true - - - - true - - - - true - - - - - $(BuildLinkTargets); - - $(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets) - - - - - - - - - - - - - - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - false - - - - - - - - - - - - - - - - - - - - - - false - true - $(BuildBarToolPath) - $(OptimizedDeployToolPath) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.Packager.targets b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.Packager.targets deleted file mode 100644 index 1fa145fb..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.Packager.targets +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - - - - - - true - - - - true - - - - true - - - - - $(BuildLinkTargets); - - $(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets) - - - - - - - - - - - - - - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - false - - - - - - - - - - - - - - - - - - - - - - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.bak b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.bak deleted file mode 100644 index 4c83562c..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.bak +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - - QCC;__QCC__;__QNX__ - false - - - - - true - false - - - - - true - .a - lib - - - - true - - - - - - true - .so - true - lib - - - - x86 - - - armle-v7 - - - - $(from_file) - gcc_ntox86 - gcc_ntoarmv7le - $(QNX_TARGET)\$(CPUVARDIR)\lib - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - - - - - - $(IntDir)%(FileName).o - $(QccDefines) - WIN32;_WINDOWS - NormalWarnings - false - false - - true - - false - false - Default - true - - - - - - - O2 - true - - - - - - - O2 - false - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - $(TargetPath) - - - false - false - true - false - true - Default - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - false - - - - - - - $(IntDir) - true - $(OutDir)$(TargetName).bar - true - false - bar-debug - bar - true - false - None - Install - false - 1 - - - - - 169.254.0.1 - - bar-descriptor.xml - $(AppData) - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.default.bak b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.default.bak deleted file mode 100644 index 9f18d577..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.default.bak +++ /dev/null @@ -1,23 +0,0 @@ - - - - - BlackBerrySimulator - qcc - - $(IntermediateOutputPath) - Simulator-$(Configuration)\ - Simulator-$(Configuration)\ - $(IntDir) - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.default.props b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.default.props deleted file mode 100644 index 9f18d577..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.default.props +++ /dev/null @@ -1,23 +0,0 @@ - - - - - BlackBerrySimulator - qcc - - $(IntermediateOutputPath) - Simulator-$(Configuration)\ - Simulator-$(Configuration)\ - $(IntDir) - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.props b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.props deleted file mode 100644 index 4c83562c..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.props +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - - QCC;__QCC__;__QNX__ - false - - - - - true - false - - - - - true - .a - lib - - - - true - - - - - - true - .so - true - lib - - - - x86 - - - armle-v7 - - - - $(from_file) - gcc_ntox86 - gcc_ntoarmv7le - $(QNX_TARGET)\$(CPUVARDIR)\lib - - - - - $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) - $([System.IO.Path]::GetFileName('$(TargetPath)')) - $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) - $(LibPrefix)$(ProjectName) - - - - - - $(IntDir)%(FileName).o - $(QccDefines) - WIN32;_WINDOWS - NormalWarnings - false - false - - true - - false - false - Default - true - - - - - - - O2 - true - - - - - - - O2 - false - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - $(TargetPath) - - - false - false - true - false - true - Default - - - - - - - $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) - false - - - - - - - $(IntDir) - true - $(OutDir)$(TargetName).bar - true - false - bar-debug - bar - true - false - None - Install - false - 1 - - - - - 169.254.0.1 - - bar-descriptor.xml - $(AppData) - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.targets b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.targets deleted file mode 100644 index 78ba5e84..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.Cpp.BlackBerrySimulator.targets +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - true - - - - - - - CompileAsC - CompileAsCpp - false - - - - - - - $(DefaultToolArchitecture) - - - - - - - - - - - - - - - - - - false - - - - - $(DefaultToolArchitecture) - - - - - - - - - - - - - - - - false - false - true - $(DefaultToolArchitecture) - true - - - - - - CompileAsC - CompileAsCpp - - - - - - - - - - - - - - - - - - $(CleanDependsOn); - MakeClean; - - - - - - - - - - - - - PlatformPrepareForBuild;$(PrepareForBuildDependsOn) - PlatformPrepareForBuild;$(PrepareForBuildDependsOn) - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.CppBuild.BlackBerrySimulator.targets b/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.CppBuild.BlackBerrySimulator.targets deleted file mode 100644 index 4ab9e314..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Microsoft.CppBuild.BlackBerrySimulator.targets +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - false - false - false - - - - - - - - - - - - - - - - - - PropertySheet - - - - - - - - - - - - - - - - Project - - - PropertySheet - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.bak b/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.bak deleted file mode 100644 index a83fb376..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.bak +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - $(Registry:HKEY_CURRENT_USER\SOFTWARE\Research In Motion\BlackBerryVSPlugin@NDKPath) - $(NativeSDKDir)\target\qnx6 - $(NativeSDKDir)\host\win32\x86 - $(QNX_HOST)\etc\qcc\gcc - x86 - 4.6.3 - gcc_ntox86 - $(QNX_TARGET)\$(CPUVARDIR)\lib - - - - qcc2.0 - $(QNX_HOST)\usr\bin - qcc.exe - qcc.exe - qcc.exe - blackberry-nativepackager.bat - blackberry-deploy.bat - $(QccToolsPath) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework@InstallRoot) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework@InstallRoot) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(QNX_HOST)\usr\bin;$(PATH); - $(QNX_TARGET)\usr\include;$(QNX_TARGET)\usr\include\freetype2;$(QNX_TARGET)\..\target-override\usr\include; - $(QccLibPath);$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\lib;$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\usr\lib; - $(ExecutablePath) - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.props b/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.props deleted file mode 100644 index 1d95dcea..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.props +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin@NDKTargetPath) - $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\BlackBerryVSPlugin@NDKHostPath) - $([System.IO.File]::ReadAllText("$(QNX_HOST)\etc\qcc\gcc\default").Substring(4,5)) - $(QNX_HOST)\etc\qcc\gcc - x86 - $(from_file) - gcc_ntox86 - $(QNX_TARGET)\$(CPUVARDIR)\lib - $(AppData) - $(AppDataPath)/BlackBerry/bbt_id_rsa.pub - $(AppDataPath)/BlackBerry/bbt_id_rsa - - - - VSNDKDebugEngine - - - - qcc2.0 - $(QNX_HOST)\usr\bin - qcc.exe - qcc.exe - qcc.exe - blackberry-nativepackager.bat - $(MSBuildProgramFiles32)\BlackBerry\VSPlugin-NDK\qnxtools\bin\blackberry-signer.bat - blackberry-deploy.bat - $(QccToolsPath) - $(QccToolsPath) - $(QccToolsPath) - ssh.exe - $(QccToolsPath) - $(QccToolsPath)\ssh-keygen.exe - $(QccToolsPath)\blackberry-connect.bat - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework@InstallRoot) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework@InstallRoot) - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) - - $(QNX_HOST)\usr\bin;$(PATH); - $(QNX_TARGET)\usr\include;$(QNX_TARGET)\usr\include\freetype2;$(QNX_TARGET)\..\target-override\usr\include; - $(QccLibPath);$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\lib;$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\usr\lib; - - $(ExecutablePath) - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.targets b/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.targets deleted file mode 100644 index 55b83ab2..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerrySimulator.qcc.targets +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/debugger_ndk.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/debugger_ndk.xml deleted file mode 100644 index cb53a5b7..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/debugger_ndk.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndkProjectItemsSchema.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndkProjectItemsSchema.xml deleted file mode 100644 index ec753493..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndkProjectItemsSchema.xml +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_directories.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_directories.xml deleted file mode 100644 index ed52f452..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_directories.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_general.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_general.xml deleted file mode 100644 index 4a7e8cb8..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_general.xml +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_general_ps.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_general_ps.xml deleted file mode 100644 index 5b40a328..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/ndk_general_ps.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/packager.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/packager.xml deleted file mode 100644 index 22e801e8..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/packager.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_cl.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_cl.xml deleted file mode 100644 index 9a799fa8..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_cl.xml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_lib.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_lib.xml deleted file mode 100644 index aa53f443..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_lib.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_link.xml b/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_link.xml deleted file mode 100644 index c35bcb63..00000000 --- a/src/VSNDK.Tasks/BlackBerrySimulator/Rules/qcc_link.xml +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VSNDK.Tasks/CheckIfInstalled.cs b/src/VSNDK.Tasks/CheckIfInstalled.cs deleted file mode 100644 index 88266c3d..00000000 --- a/src/VSNDK.Tasks/CheckIfInstalled.cs +++ /dev/null @@ -1,104 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Collections; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - /// - /// MSBuild Task to check to see if the application was previously installed. - /// - public class CheckIfInstalled : Task - { - #region Member Variables and Constants - private string _listFile; - private string _appName; - private bool _isAppInstalled; - #endregion - - /// - /// Execute the MSBuild task - /// - /// True on successful execution - public override bool Execute() - { - - try - { - _isAppInstalled = false; - - string[] installedApps = File.ReadAllLines(_listFile); - foreach (string app in installedApps) - { - if (app.Contains(_appName)) - { - _isAppInstalled = true; - break; - } - } - - return true; - } - catch (Exception ex) - { - return false; - } - - - } - - /// - /// Setter for the ListFile property - /// - [Required] - public string ListFile - { - set - { - _listFile = value; - } - } - - /// - /// Setter for the AppName property - /// - [Required] - public string AppName - { - set - { - _appName = value; - } - } - - /// - /// Getter for the IsAppInstalled property - /// - [Output] - public bool IsAppInstalled - { - get - { - return _isAppInstalled; - } - } - } -} diff --git a/src/VSNDK.Tasks/DiffManifests.cs b/src/VSNDK.Tasks/DiffManifests.cs deleted file mode 100644 index bb0ede14..00000000 --- a/src/VSNDK.Tasks/DiffManifests.cs +++ /dev/null @@ -1,239 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Collections; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - /// - /// MSBuild task to compare the manifest file from the bar file being uploaded against the one already installed on the device. - /// - public class DiffManifests : Task - { - #region Member Variables and Constants - private string _localManifestFile; - private string _targetManifestFile; - private string _targetFileMap; - private ArrayList _modifiedFiles; - private ArrayList _deletedFiles; - private int _modifiedFilesCount; - private int _deletedFilesCount; - #endregion - - /// - /// Execute the MSBuild Task. - /// - /// - public override bool Execute() - { - _modifiedFiles = new ArrayList(); - _deletedFiles = new ArrayList(); - - // Parse local manifest to retrieve list of files and their hashes. - string[] localManifest = File.ReadAllLines(_localManifestFile); - Dictionary localFiles = new Dictionary(); - for (int i = 0; i < localManifest.Length; i++) - { - if (localManifest[i].StartsWith("Archive-Asset-Name: ")) - { - string assetName = localManifest[i].Substring(20); - i++; - if (localManifest[i].StartsWith("Archive-Asset-SHA-512-Digest: ")) - { - string assetHash = localManifest[i].Substring(30); - localFiles.Add(assetName, assetHash); - } - else - { - return false; - } - } - } - - // Do the same for the target manifest. - string[] targetManifest = File.ReadAllLines(_targetManifestFile); - Dictionary targetFiles = new Dictionary(); - for (int i = 0; i < targetManifest.Length; i++) - { - if (targetManifest[i].StartsWith("Archive-Asset-Name: ")) - { - string assetName = targetManifest[i].Substring(20); - i++; - if (targetManifest[i].StartsWith("Archive-Asset-SHA-512-Digest: ")) - { - string assetHash = targetManifest[i].Substring(30); - targetFiles.Add(assetName, assetHash); - } - else - { - return false; - } - } - } - - // Compare hashes and populate the lists of modified and deleted files. - string[] targetFileMap = File.ReadAllLines(_targetFileMap); - foreach (KeyValuePair file in localFiles) - { - // For some reason this MANIFEST.bbr file appears in the manifest, even though - // it doesn't actually exist anywhere...? It doesn't seem to correspond to - // MANIFEST.MF either. - if (file.Key == "META-INF/MANIFEST.bbr") - { - continue; - } - - // If the target manifest doesn't contain the same key/value pair, - // that means the local file has been either added or modified. - if (!targetFiles.Contains(file)) - { - TaskItem item = new TaskItem(file.Key); - item.SetMetadata("SourcePath", getSourcePath(file.Key, targetFileMap)); - _modifiedFiles.Add(item); - } - } - - IDictionaryEnumerator targetEnum = targetFiles.GetEnumerator(); - while (targetEnum.MoveNext()) - { - // If the local manifest doesn't contain the same key, - // that means the target file has been deleted from the project. - if (!localFiles.ContainsKey((string)targetEnum.Key)) - { - TaskItem item = new TaskItem((string)targetEnum.Key); - _deletedFiles.Add(item); - } - } - - // For some reason the manifest file doesn't show up in the target file map - // or the manifest itself, so we add it manually here and always upload it. - TaskItem manifestItem = new TaskItem("META-INF/MANIFEST.MF"); - manifestItem.SetMetadata("SourcePath", "localManifest.mf"); - _modifiedFiles.Add(manifestItem); - - return true; - } - - /// - /// Helper function to parse the target file map to add the source path of each modified file as metadata. - /// - /// Path to the source file - /// Target file map - /// - private string getSourcePath(string sourcePath, string[] targetFileMap) - { - foreach (string line in targetFileMap) - { - if (line.Contains(sourcePath)) - { - int startIndex = line.IndexOf('='); - return line.Substring(startIndex + 1); - } - } - - return ""; - } - - /// - /// Getter for the ModifiedFiles property. - /// - [Output] - public ITaskItem[] ModifiedFiles - { - get - { - ITaskItem[] items = (ITaskItem[])_modifiedFiles.ToArray(typeof(ITaskItem)); - _modifiedFilesCount = items.Length; - return items; - } - } - - /// - /// Getter for the ModifiedFilesCount property - /// - [Output] - public int ModifiedFilesCount - { - get { return _modifiedFilesCount; } - set { _modifiedFilesCount = value; } - } - - /// - /// Getter for the DeletedFiles property - /// - [Output] - public ITaskItem[] DeletedFiles - { - get - { - ITaskItem[] items = (ITaskItem[])_deletedFiles.ToArray(typeof(ITaskItem)); - _deletedFilesCount = items.Length; - return items; - } - } - - /// - /// Getter/Setter for the DeletedFilesCount property - /// - [Output] - public int DeletedFilesCount - { - get { return _deletedFilesCount; } - set { _deletedFilesCount = value; } - } - - /// - /// Setter for the LocalManifestFile property - /// - [Required] - public string LocalManifestFile - { - set - { - _localManifestFile = value; - } - } - - /// - /// Setter for the TargetManifestFile property - /// - [Required] - public string TargetManifestFile - { - set - { - _targetManifestFile = value; - } - } - - /// - /// Setter for the targetFileMap property - /// - [Required] - public string targetFileMap - { - set - { - _targetFileMap = value; - } - } - } -} diff --git a/src/VSNDK.Tasks/GenerateMakefile.cs b/src/VSNDK.Tasks/GenerateMakefile.cs deleted file mode 100644 index 9f523095..00000000 --- a/src/VSNDK.Tasks/GenerateMakefile.cs +++ /dev/null @@ -1,521 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Collections; -using System.IO; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using System.Runtime.InteropServices; - -namespace VSNDK.Tasks -{ - /// - /// MSBuild Task for generating a make file for packaging the bar file. - /// - public class GenerateMakefile : Task - { - #region Member Variables and Constants - private string _projectDir; - private string _intDir; - private string _outDir; - - private const string INITIAL_DEFINITIONS = - "RM := rm -rf\n\n" + - - "# Empty variable definitions.\n" + - "O_SRCS := \n" + - "CPP_SRCS := \n" + - "C_UPPER_SRCS := \n" + - "C_SRCS := \n" + - "S_UPPER_SRCS := \n" + - "OBJ_SRCS := \n" + - "II_SRCS := \n" + - "ASM_SRCS := \n" + - "CXX_SRCS := \n" + - "I_SRCS := \n" + - "CC_SRCS := \n" + - "OBJS := \n" + - "C_DEPS := \n" + - "CC_DEPS := \n" + - "ARCHIVES := \n" + - "CPP_DEPS := \n" + - "I_DEPS := \n" + - "CXX_DEPS := \n" + - "C_UPPER_DEPS := \n" + - "II_DEPS := \n\n" + - - "USER_OBJS := \n" + - "LIBS := \n\n"; - - private const string DEPENDENCY_INCLUDES = - "# Include all dependency files\n" + - "ifneq ($(MAKECMDGOALS),clean)\n" + - "ifneq ($(strip $(C_DEPS)),)\n" + - "-include $(C_DEPS)\n" + - "endif\n" + - "ifneq ($(strip $(CC_DEPS)),)\n" + - "-include $(CC_DEPS)\n" + - "endif\n" + - "ifneq ($(strip $(CPP_DEPS)),)\n" + - "-include $(CPP_DEPS)\n" + - "endif\n" + - "ifneq ($(strip $(I_DEPS)),)\n" + - "-include $(I_DEPS)\n" + - "endif\n" + - "ifneq ($(strip $(CXX_DEPS)),)\n" + - "-include $(CXX_DEPS)\n" + - "endif\n" + - "ifneq ($(strip $(C_UPPER_DEPS)),)\n" + - "-include $(C_UPPER_DEPS)\n" + - "endif\n" + - "ifneq ($(strip $(II_DEPS)),)\n" + - "-include $(II_DEPS)\n" + - "endif\n" + - "endif\n\n"; - #endregion - - #region properties - - /// - /// Getter/Setter for CompileItems property - /// - public ITaskItem[] CompileItems - { - set; - get; - } - - /// - /// Getter/Setter for LinkItems - /// - public ITaskItem[] LinkItems - { - set; - get; - } - - /// - /// Getter/Setter for ProjectDir property - /// - public string ProjectDir - { - set { _projectDir = value.Replace('\\', '/'); } - get { return _projectDir; } - } - - /// - /// Getter/Setter for IntDir property - /// - public string IntDir - { - set { _intDir = value.Replace('\\', '/'); } - get { return _intDir; } - } - - /// - /// Getter/Setter for OutDir property - /// - public string OutDir - { - set { _outDir = value.Replace('\\', '/'); } - get { return _outDir; } - } - - /// - /// Getter/Setter for AdditionalIncludeDirectories property - /// - public string[] AdditionalIncludeDirectories - { - set; - get; - } - - /// - /// Getter/Setter for AdditionLibraryDirectories - /// - public string[] AdditionalLibraryDirectories - { - set; - get; - } - - /// - /// Getter/Setter for ExcludeDirectories - /// - public string[] ExcludeDirectories - { - set; - get; - } - - - /// - /// Getter/Setter for TargetName property - /// - public string TargetName - { - set; - get; - } - - /// - /// Getter/Setter for TargetExtension property - /// - public string TargetExtension - { - set; - get; - } - - /// - /// Getter/Setter for ConfigurationType property - /// - public string ConfigurationType - { - set; - get; - } - - /// - /// Getter/Setter for CompilerVersion property - /// - public string CompilerVersion - { - set; - get; - } - - /// - /// Getter/Setter for Platform property - /// - public string Platform - { - set; - get; - } - - #endregion - - /// - /// Interface to unmanaged code for getting the SHortPathName for a given directory. - /// - /// Path to be converted - /// Returned ShortPathName - /// Length of the ShortPathName - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern int GetShortPathName( - [MarshalAs(UnmanagedType.LPTStr)] - string path, - [MarshalAs(UnmanagedType.LPTStr)] - StringBuilder shortPath, - int shortPathLength - ); - - /// - /// Execute MSBuild Task - /// - /// - public override bool Execute() - { - string targetString = TargetName + TargetExtension; - targetString = targetString.Replace(".exe", ""); - string compilerFlag = "-V\"" + CompilerVersion; - - if (Platform == "BlackBerry") - compilerFlag += ",gcc_ntoarmv7le\""; - else if (Platform == "BlackBerrySimulator") - compilerFlag += ",gcc_ntox86\""; - - using (StreamWriter outFile = new StreamWriter(IntDir + "makefile")) - { - outFile.Write(INITIAL_DEFINITIONS); - // System.Diagnostics.Debugger.Launch(); - foreach (ITaskItem compileItem in CompileItems) - { - // Get the metadata we need from this compile item. - string id = compileItem.GetMetadata("Identity").Replace('\\', '/'); - string filename = compileItem.GetMetadata("Filename"); - string extension = compileItem.GetMetadata("Extension"); - string relativeDir = compileItem.GetMetadata("RelativeDir").Replace('\\', '/'); - string compileAs = compileItem.GetMetadata("CompileAs"); - string warningLevel = compileItem.GetMetadata("WarningLevel"); - string ansi = compileItem.GetMetadata("Ansi"); - string optimizationLevel = compileItem.GetMetadata("OptimizationLevel"); - string generateDebugInfo = compileItem.GetMetadata("GenerateDebugInformation"); - string runtimeTypeInfo = compileItem.GetMetadata("RuntimeTypeInfo"); - string enhancedSecurity = compileItem.GetMetadata("EnhancedSecurity"); - string additionalOptions = compileItem.GetMetadata("AdditionalOptions"); - string fullPath = compileItem.GetMetadata("FullPath").Replace('\\', '/'); - - /// if CompileItem is in the ExcludedPath then continue. - if (isExcludedPath(fullPath)) - { - - continue; - } - - StringBuilder shortPath = new StringBuilder(1024); - GetShortPathName(fullPath, shortPath, shortPath.Capacity); - string fullPathShortened = shortPath.ToString(); - - string handleExceptions = compileItem.GetMetadata("GccExceptionHandling"); - - string[] preprocessorDefs = compileItem.GetMetadata("PreprocessorDefinitions").Split(';'); - string[] preprocessorUndefs = compileItem.GetMetadata("UndefinePreprocessorDefinitions").Split(';'); - - string[] additionalIncludeDirs = compileItem.GetMetadata("AdditionalIncludeDirectories").Split(';'); - for (int i = 0; i < additionalIncludeDirs.Length; i++) - { - // Prepend ProjectDir to relative paths -- otherwise they will be interpreted - // as being relative to the build dir, e.g. ProjectDir/BlackBerry/Debug - if (additionalIncludeDirs[i] != "" && !additionalIncludeDirs[i].Contains(':')) - additionalIncludeDirs[i] = ProjectDir + additionalIncludeDirs[i]; - } - - // Add this compile item to the source definition. - if (compileAs == "CompileAsC") - outFile.Write("C_SRCS += "); - else if (compileAs == "CompileAsCpp") - outFile.Write("CPP_SRCS += "); - - // Source file location. - outFile.WriteLine(fullPathShortened); - - // Add this compile item's dependency file to the DEPS definition. - if (compileAs == "CompileAsC") - outFile.Write("C_DEPS += "); - else if (compileAs == "CompileAsCpp") - outFile.Write("CPP_DEPS += "); - - outFile.WriteLine("./" + filename + ".d"); - - // Add the object file to the OBJS definition. - outFile.WriteLine("OBJS += ./" + filename + ".o\n"); - - // Now add a compile rule for this item. - outFile.WriteLine(filename + ".o: " + fullPathShortened); - outFile.Write("\tqcc -o $@ " + fullPathShortened + " " + compilerFlag + " -c -Wp,-MMD,$(basename $@).d -Wp,-MT,$@ "); - - if (generateDebugInfo == "true") - outFile.Write("-g "); - - Dictionary warningMap = new Dictionary(); - warningMap.Add("TurnOffAllWarnings", "-w0 "); - warningMap.Add("Level1", "-w1 "); - warningMap.Add("Level2", "-w2 "); - warningMap.Add("Level3", "-w3 "); - warningMap.Add("Level4", "-w4 "); - warningMap.Add("Level5", "-w5 "); - warningMap.Add("Level6", "-w6 "); - warningMap.Add("Level7", "-w7 "); - warningMap.Add("Level8", "-w8 "); - warningMap.Add("Level9", "-w9 "); - warningMap.Add("EnableAllWarnings", "-Wall "); - - string warningLevelSwitch; - warningMap.TryGetValue(warningLevel, out warningLevelSwitch); - outFile.Write(warningLevelSwitch); - - if (compileAs == "CompileAsC") - outFile.Write("-lang-c "); - else if (compileAs == "CompileAsCpp") - outFile.Write("-lang-c++ "); - - if (runtimeTypeInfo == "false" && compileAs == "CompileAsCpp") - outFile.Write("-fno-rtti "); - - if (handleExceptions == "true") - outFile.Write("-fexceptions "); - else - outFile.Write("-fno-exceptions "); - - if (enhancedSecurity == "true") - outFile.Write("-fstack-protector-all "); - - // Note: Consider letting user decide between "-fpic" and "-fPIC" - // For now we use the safe, cross-platform "-fPIC" - if (ConfigurationType == "DynamicLibrary") - outFile.Write("-fPIC "); - - foreach (string includeDir in AdditionalIncludeDirectories) - { - if (includeDir != "") - outFile.Write("-I\"" + includeDir + "\" "); - } - - foreach (string includeDir in additionalIncludeDirs) - { - if (includeDir != "") - outFile.Write("-I\"" + includeDir + "\" "); - } - - foreach (string def in preprocessorDefs) - { - if (def != "") - outFile.Write("-D" + def + " "); - } - - foreach (string undef in preprocessorUndefs) - { - if (undef != "") - outFile.Write("-U" + undef + " "); - } - - outFile.WriteLine(additionalOptions); - outFile.WriteLine(); - } - - outFile.Write(DEPENDENCY_INCLUDES); - - // Now write out all the targets. - outFile.WriteLine("all: " + targetString); - outFile.WriteLine(); - outFile.Write(targetString + ": $(OBJS) $(USER_OBJS) $(LIB_DEPS) "); - outFile.WriteLine(); - - string rootedOutDir = (Path.IsPathRooted(OutDir)) ? OutDir : ProjectDir + OutDir; - - StringBuilder shortOutPath = new StringBuilder(1024); - GetShortPathName(rootedOutDir, shortOutPath, shortOutPath.Capacity); - rootedOutDir = shortOutPath.ToString(); - - if (ConfigurationType == "StaticLibrary") - { - outFile.Write("\tqcc -A " + rootedOutDir + targetString + " $(OBJS) $(USER_OBJS) $(LIBS) " + compilerFlag + " -w1"); - } - else if (ConfigurationType == "DynamicLibrary") - { - // In case of reverse dependencies, may need to add "-Wl,-export-dynamic" - // Also note that the soname is currently the same as the target name, and no version information is added. - outFile.Write("\tqcc -shared -Wl,-soname," + targetString + - " -o " + rootedOutDir + targetString + - " $(OBJS) $(USER_OBJS) $(LIBS) " + compilerFlag); - } - else if (ConfigurationType == "Utility") - { - // As far as I know, we don't support utilities. - } - else if (ConfigurationType == "Application") - { - // For now, collect linker metadata from the first link item. - // (Why do we have multiple link items anyhow?) - string[] libs = LinkItems[0].GetMetadata("AdditionalDependencies").Split(';'); - string generateDebugInfo = LinkItems[0].GetMetadata("GenerateDebugInformation"); - string compileAs = LinkItems[0].GetMetadata("CompileAs"); - - string[] libDirs = LinkItems[0].GetMetadata("AdditionalLibraryDirectories").Split(';'); - for (int i = 0; i < libDirs.Length; i++) - { - // Prepend ProjectDir to relative paths. - if (libDirs[i] != "" && !libDirs[i].Contains(':')) - libDirs[i] = ProjectDir + libDirs[i]; - } - - // This is the linker's tool invocation. - outFile.Write("\tqcc -o " + rootedOutDir + targetString + " $(OBJS) $(USER_OBJS) $(LIBS) " + compilerFlag + " "); - - if (compileAs == "CompileAsCpp") - outFile.Write("-lang-c++ "); - else if (compileAs == "CompileAsC") - outFile.Write("-lang-c "); - - if (generateDebugInfo == "true") - outFile.Write("-g "); - - // For added security, remap some sections of ELF as read-only. - outFile.Write("-Wl,-z,relro,-z,now "); - - // Visual Studio doesn't have separate lists for static vs. dynamic dependencies. - // To differentiate between the two, include the extension in the list. - // (.a for static, .so for dynamic) - // If no extension is included in the name it will be treated as the same type - // as the last declared type, and the default type is static. This is the way - // qcc would work if you were using it from the command line with the - // "-Bstatic" and "-Bdynamic" flags. - for (int i = 0; i < libs.Length; i++) - { - if (libs[i].EndsWith(".so")) - { - outFile.Write("-Bdynamic "); - libs[i] = libs[i].Remove(libs[i].Length - 3); - } - else if (libs[i].EndsWith(".a")) - { - outFile.Write("-Bstatic "); - libs[i] = libs[i].Remove(libs[i].Length - 2); - } - - if (libs[i] != "") - outFile.Write("-l" + libs[i] + " "); - } - - foreach (string libDir in libDirs) - { - if (libDir != "") - outFile.Write("-L\"" + libDir + "\" "); - } - - foreach (string libDir in AdditionalLibraryDirectories) - { - if (libDir != "") - outFile.Write("-L\"" + libDir + "\" "); - } - } - - outFile.WriteLine("\n"); - outFile.WriteLine("clean:"); - outFile.Write("\t-$(RM) $(OBJS)$(C_DEPS)$(CC_DEPS)$(COM_QNX_QCC_OUTPUTTYPE_LINKER_OUTPUTS)$(CPP_DEPS)$(I_DEPS)$(CXX_DEPS)$(C_UPPER_DEPS)$(II_DEPS) " + rootedOutDir + targetString); - - if (ConfigurationType == "Application") - { - outFile.WriteLine(" " + rootedOutDir + TargetName + ".bar"); - } - - outFile.WriteLine(); - outFile.WriteLine(".PHONY: all clean dependents\n"); - } - - return true; - } - - /// - /// Check to see if path is in the excluded list - /// - /// - /// - private bool isExcludedPath(string path) - { - if (ExcludeDirectories != null) - { - foreach (string exDir in ExcludeDirectories) - { - if (Path.GetFullPath(path).Contains(Path.GetFullPath(exDir))) - { - return true; - } -/* else - { - return false; - }*/ - } - } - return false; - } - } -} diff --git a/src/VSNDK.Tasks/GetAppInfo.cs b/src/VSNDK.Tasks/GetAppInfo.cs deleted file mode 100644 index 353f09de..00000000 --- a/src/VSNDK.Tasks/GetAppInfo.cs +++ /dev/null @@ -1,124 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Xml; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - /// - /// MSBuid Task to retrieve the application info - /// - public class GetAppInfo : Task - { - #region Member Variables and Constants - private string _projectDir; - private string _appName; - private string _barDescriptorPath = ""; - private string _appId; - #endregion - - /// - /// Execute the MSBuild Task - /// - /// - public override bool Execute() - { - string rootedOutDir = (Path.IsPathRooted(_barDescriptorPath)) ? _barDescriptorPath : _projectDir + _barDescriptorPath; - XmlReader reader = XmlReader.Create(rootedOutDir); - reader.ReadToFollowing("id"); - _appId = reader.ReadElementContentAsString(); - - return true; - } - - /// - /// Getter/Setter for the ApplicationDescriptorXml property - /// - public string ApplicationDescriptorXml - { - set - { - _barDescriptorPath = value; - } - get - { - return _barDescriptorPath; - } - } - - /// - /// Getter/Setter for the ProjectDir property - /// - public string ProjectDir - { - set - { - _projectDir = value; - } - get - { - return _projectDir; - } - } - - /// - /// Getter/Setter for the AppName property - /// - public string AppName - { - set - { - _appName = value; - - if (_barDescriptorPath == "") - { - // Default location of bar-descriptor file, if not specified in the Properties Configurations. - _barDescriptorPath = "BlackBerry-" + _appName + "\\bar-descriptor.xml"; - if (!File.Exists(_barDescriptorPath)) - { - // Just to support the default locations of bar-descriptor from previous versions of the plug-in. - _barDescriptorPath = _appName + "_barDescriptor\\bar-descriptor.xml"; - if (!File.Exists(_barDescriptorPath)) - { - _barDescriptorPath = "bar-descriptor.xml"; - } - } - } - } - get - { - return _appName; - } - } - - /// - /// Getter/Setter for the AppId property - /// - [Output] - public string AppId - { - get - { - return _appId; - } - } - } -} diff --git a/src/VSNDK.Tasks/LaunchDebugEngine.cs b/src/VSNDK.Tasks/LaunchDebugEngine.cs deleted file mode 100644 index bd688a79..00000000 --- a/src/VSNDK.Tasks/LaunchDebugEngine.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.Utilities; -using Microsoft.Build.Framework; - -using EnvDTE; -using EnvDTE80; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.OLE.Interop; -using System.Runtime.InteropServices; - -namespace VSNDK.Tasks -{ - /*[ComImport] - [Guid("23EB4AF8-BE9C-4b49-B3A4-24F4FF657B27")] - * */ - - public abstract class LaunchDebugEngine : Microsoft.Build.Utilities.Task - { - /* - [DllImport("ole32.dll")] - static extern int CoInitializeEx(IntPtr pvReserved, uint dwCoInit); - */ - private DTE2 _applicationObject; - private string _filePath; - - public override bool Execute() - { - System.Diagnostics.Debugger.Launch(); - //CoInitializeEx(NULL, COINIT_MULTITHREADED); - //enum comEnum = {COINIT_MULTITHREADED=0}; - //CoInitializeEx((IntPtr)null, (uint)0); - - _applicationObject = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0"); - - Microsoft.VisualStudio.Shell.ServiceProvider sp = - new Microsoft.VisualStudio.Shell.ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)_applicationObject); - - IVsDebugger dbg = (IVsDebugger)sp.GetService(typeof(SVsShellDebugger)); - - VsDebugTargetInfo info = new VsDebugTargetInfo(); - info.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(info); - info.dlo = Microsoft.VisualStudio.Shell.Interop.DEBUG_LAUNCH_OPERATION.DLO_CreateProcess; - - info.bstrExe = _filePath; - info.bstrCurDir = System.IO.Path.GetDirectoryName(info.bstrExe); - info.bstrArg = null; // no command line parameters - info.bstrRemoteMachine = null; // debug locally - info.fSendStdoutToOutputWindow = 0; // Let stdout stay with the application. - info.clsidCustom = new Guid("{D951924A-4999-42a0-9217-1EB5233D1D5A}"); // Set the launching engine the sample engine guid - info.grfLaunch = 0; - - IntPtr pInfo = System.Runtime.InteropServices.Marshal.AllocCoTaskMem((int)info.cbSize); - System.Runtime.InteropServices.Marshal.StructureToPtr(info, pInfo, false); - - try - { - dbg.LaunchDebugTargets(1, pInfo); - } - finally - { - if (pInfo != IntPtr.Zero) - { - System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pInfo); - } - } - - return true; - } - - [Required] - public string FilePath - { - set - { - _filePath = value; - } - } - } -} diff --git a/src/VSNDK.Tasks/MakeAllAndFormatOutputMessages.cs b/src/VSNDK.Tasks/MakeAllAndFormatOutputMessages.cs deleted file mode 100644 index 2dfcefe2..00000000 --- a/src/VSNDK.Tasks/MakeAllAndFormatOutputMessages.cs +++ /dev/null @@ -1,556 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using EnvDTE; -using EnvDTE80; -using System.Runtime.InteropServices; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using System.Runtime.Serialization; -using System.Diagnostics; -using Microsoft.Build.Utilities; -using Microsoft.Build.Framework; -using System.Text.RegularExpressions; - -namespace VSNDK.Tasks -{ - /// - /// Cancelabe MSBuild Task for Running the Make file for the build. - /// - public class MakeAllAndFormatOutputMessages : ICancelableTask - { - #region Member Variables and Constants - - private string _projectDir; - private string _intDir; - private string _outDir; - - private static StringBuilder stdOutput = null; - private static StringBuilder errorOutput = null; - private IBuildEngine buildEngine; - private System.Diagnostics.Process proc = null; - private ITaskHost hostObject; - - private string _numProcessors; - - #endregion - - /// - /// Getter/Setter for the BuildEngine property - /// - public IBuildEngine BuildEngine - { - get { return buildEngine; } - set { buildEngine = value; } - } - - /// - /// Getter/Setter for the HostObject property - /// - public ITaskHost HostObject - { - get { return hostObject; } - set { hostObject = value; } - } - - /// - /// Getter/Setter for CompileItems property - /// - public ITaskItem[] CompileItems - { - set; - get; - } - - /// - /// Getter/Setter for the number of processors property. - /// - public string numProcessors - { - get - { - _numProcessors = Environment.ProcessorCount.ToString(); - return _numProcessors; - } - set { _numProcessors = value; } - } - - /// - /// Perform Task Execution - /// - /// Return true on successful task completion - public bool Execute() - { - string pCommand = ""; - string pArgs = ""; - bool mprocess = false; - - try - { - foreach (ITaskItem compileItem in CompileItems) - { - // Get the metadata we need from this compile item. - mprocess = (compileItem.GetMetadata("MultiProcess") == "true"); - } - - pCommand = "cmd"; - if (mprocess) - pArgs = "/c " + ToolsPath + @"\make -j" + numProcessors + " all"; - else - pArgs = "/c " + ToolsPath + @"\make all"; - - System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(pCommand, pArgs); - - // Set UseShellExecute to false for redirection. - procStartInfo.UseShellExecute = false; - - // The following commands are needed to redirect the standard and error outputs. - // These streams are read asynchronously using an event handler. - procStartInfo.RedirectStandardOutput = true; - stdOutput = new StringBuilder(""); - procStartInfo.RedirectStandardError = true; - errorOutput = new StringBuilder(""); - - // Setting the work directory. - string rootedOutDir = (Path.IsPathRooted(OutDir)) ? OutDir : ProjectDir + OutDir; - procStartInfo.WorkingDirectory = rootedOutDir; - - // Do not create the black window. - procStartInfo.CreateNoWindow = true; - - // Create a process and assign its ProcessStartInfo - proc = new System.Diagnostics.Process(); - proc.StartInfo = procStartInfo; - - // Set ours events handlers to asynchronously read the standard and error outputs. - proc.OutputDataReceived += new DataReceivedEventHandler(StdOutputHandler); - proc.ErrorDataReceived += new DataReceivedEventHandler(ErrorOutputHandler); - - // Start the process - proc.Start(); - - // Start the asynchronous read of the standard and error output stream. - proc.BeginOutputReadLine(); - proc.BeginErrorReadLine(); - - do - { - // Wait until finished - // This code is correct, don't remove it. WaitForExit freezes the IDE while waiting for the end of the build process. - // With this loop and the time out, the IDE won't be frozen enabling the build process to be cancelled. - } - while (!proc.WaitForExit(1000)); - - } - catch (Exception e) - { - Console.WriteLine("Failed to execute make all. Reason: " + e.Message); - return false; - } - - if (errorOutput.ToString().IndexOf(": error:") == -1) - { - int pos = errorOutput.ToString().LastIndexOf("\\make:"); - if (pos == -1) - return true; - else - { - pos = errorOutput.ToString().IndexOf("Error ", pos); - if (pos == -1) - return true; - } - } - - return false; - - } - - /// - /// Standard Output Event Handler - /// - /// Sending Process - /// Output Text - private void StdOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) - { - if (!String.IsNullOrEmpty(outLine.Data)) - { - string outputText = outLine.Data; - - int tilde = outputText.IndexOf("~"); - while (tilde != -1) - { - int end = outputText.IndexOf(':', tilde); - int end1 = outputText.IndexOf(' ', tilde); - int end2 = outputText.IndexOf('\n', tilde); - if ((end == -1) && (end1 == -1) && (end2 == -1)) - break; - if (end == -1) - end = outputText.Length - 1; - if (end1 == -1) - end1 = outputText.Length - 1; - if (end2 == -1) - end2 = outputText.Length - 1; - if (end > end1) - end = end1; - if (end > end2) - end = end2; - int begin = outputText.LastIndexOf('\n', tilde) + 1; - int begin1 = outputText.LastIndexOf(' ', tilde) + 1; - if (begin < begin1) - begin = begin1; - StringBuilder longPathName = new StringBuilder(1024); - string shortPathName = outputText.Substring(begin, end - begin); - GetLongPathName(shortPathName, longPathName, longPathName.Capacity); - if (longPathName.ToString() == "") - { - int sep = shortPathName.LastIndexOf('/'); - int sep2 = shortPathName.LastIndexOf('\\'); - if (sep2 > sep) - sep = sep2; - if (sep != -1) - { - shortPathName = shortPathName.Remove(sep + 1); - GetLongPathName(shortPathName, longPathName, longPathName.Capacity); - } - } - if (longPathName.ToString() != "") - outputText = outputText.Replace(shortPathName, longPathName.ToString()); - - tilde = outputText.IndexOf("~", tilde + 1); - } - - - BuildMessageEventArgs taskEvent = new BuildMessageEventArgs(outputText, "", "", MessageImportance.High); - BuildEngine.LogMessageEvent(taskEvent); - - } - } - - /// - /// Error Output Event Handler - /// - /// Sending process - /// Error Message - private void ErrorOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) - { - if (!String.IsNullOrEmpty(outLine.Data)) - { - string outputText = outLine.Data; - int pos = outputText.IndexOf(": warning:"); - if (pos == -1) - pos = outputText.IndexOf(": note:"); - int diff = 10; - int tilde; - while (pos != -1) - { - if (outputText[pos - 1] != ')') - { - int end = pos; - int begin = outputText.LastIndexOf('\n', end) + 1; - string oldPath = outputText.Substring(begin, end - begin + 1); - string newPath = oldPath; - newPath = newPath.Insert(newPath.Length - 1, ")"); - end = newPath.LastIndexOf(":", newPath.Length - 2); - if (end != -1) - { - newPath = newPath.Remove(end, 1); - newPath = newPath.Insert(end, ","); - end = newPath.LastIndexOf(":", end - 1); - if (end != -1) - { - if (end > 5) - { - newPath = newPath.Remove(end, 1); - newPath = newPath.Insert(end, "("); - } - else - { - end = newPath.IndexOf(",", end); - newPath = newPath.Remove(end, 1); - newPath = newPath.Insert(end, "("); - } - - tilde = newPath.IndexOf("~"); - if (tilde != -1) - { - StringBuilder longPathName = new StringBuilder(1024); - string shortPathName = newPath.Substring(0, end); - GetLongPathName(shortPathName, longPathName, longPathName.Capacity); - newPath = longPathName.ToString() + newPath.Substring(end); - } - - diff += (newPath.Length - oldPath.Length); - outputText = outputText.Replace(oldPath, newPath); - } - } - } - pos = outputText.IndexOf(": warning:", pos + diff); - } - - pos = outputText.IndexOf(": error:"); - diff = 8; - while (pos != -1) - { - if (outputText[pos - 1] != ')') - { - int end = pos; - int begin = outputText.LastIndexOf('\n', end) + 1; - string oldPath = outputText.Substring(begin, end - begin + 1); - string newPath = oldPath; - newPath = newPath.Insert(newPath.Length - 1, ")"); - end = newPath.LastIndexOf(":", newPath.Length - 2); - if (end != -1) - { - newPath = newPath.Remove(end, 1); - newPath = newPath.Insert(end, ","); - end = newPath.LastIndexOf(":", end - 1); - if (end != -1) - { - if (end > 5) - { - newPath = newPath.Remove(end, 1); - newPath = newPath.Insert(end, "("); - } - else - { - end = newPath.IndexOf(",", end); - newPath = newPath.Remove(end, 1); - newPath = newPath.Insert(end, "("); - } - - tilde = newPath.IndexOf("~"); - if (tilde != -1) - { - StringBuilder longPathName = new StringBuilder(1024); - string shortPathName = newPath.Substring(0, end); - GetLongPathName(shortPathName, longPathName, longPathName.Capacity); - newPath = longPathName.ToString() + newPath.Substring(end); - } - - diff += (newPath.Length - oldPath.Length); - outputText = outputText.Replace(oldPath, newPath); - } - } - } - pos = outputText.IndexOf(": error:", pos + diff); - } - - tilde = outputText.IndexOf("~"); - while (tilde != -1) - { - int end = outputText.IndexOf(':', tilde); - int end1 = outputText.IndexOf(' ', tilde); - int end2 = outputText.IndexOf('\n', tilde); - if ((end == -1) && (end1 == -1) && (end2 == -1)) - break; - if (end == -1) - end = outputText.Length - 1; - if (end1 == -1) - end1 = outputText.Length - 1; - if (end2 == -1) - end2 = outputText.Length - 1; - if (end > end1) - end = end1; - if (end > end2) - end = end2; - int begin = outputText.LastIndexOf('\n', tilde) + 1; - int begin1 = outputText.LastIndexOf(' ', tilde) + 1; - if (begin < begin1) - begin = begin1; - StringBuilder longPathName = new StringBuilder(1024); - string shortPathName = outputText.Substring(begin, end - begin); - GetLongPathName(shortPathName, longPathName, longPathName.Capacity); - if (longPathName.ToString() == "") - { - int sep = shortPathName.LastIndexOf('/'); - int sep2 = shortPathName.LastIndexOf('\\'); - if (sep2 > sep) - sep = sep2; - if (sep != -1) - { - shortPathName = shortPathName.Remove(sep + 1); - GetLongPathName(shortPathName, longPathName, longPathName.Capacity); - } - } - if (longPathName.ToString() != "") - outputText = outputText.Replace(shortPathName, longPathName.ToString()); - - tilde = outputText.IndexOf("~", tilde + 1); - } - - /// Send build output to the Output window and to the ErrorList window - if (outputText.IndexOf(": error:") > 0) - { - string fileName = outputText.Substring(0, outputText.IndexOf(": error:")); - int lineNum = 0; - - int ini = fileName.IndexOf('(') + 1; - int end = fileName.IndexOf(')'); - - if (fileName.IndexOf(',', ini) > 0) - { - if (fileName.IndexOf(',', ini) < end) - { - end = fileName.IndexOf(',', ini); - } - } - end = end - fileName.IndexOf('(') - 1; - - try - { - lineNum = Convert.ToInt16(fileName.Substring(ini, end)); - } - catch - { - lineNum = 0; - } - - int colNum = 0; - string messageErr = outputText.Substring(outputText.IndexOf(": error:") + 9); - fileName = fileName.Substring(0, fileName.IndexOf('(')); - BuildErrorEventArgs errorEvent = new BuildErrorEventArgs("", "", fileName, lineNum, colNum, 0, 0, messageErr, "", ""); - BuildEngine.LogErrorEvent(errorEvent); - } - else if (outputText.IndexOf(": warning:") > 0) - { - string fileName = outputText.Substring(0, outputText.IndexOf(": warning:")); - int lineNum = 0; - - int ini = fileName.IndexOf('(') + 1; - int end = fileName.IndexOf(')'); - if (fileName.IndexOf(',', ini) > 0) - { - if (fileName.IndexOf(',', ini) < end) - { - end = fileName.IndexOf(',', ini); - } - } - end = end - fileName.IndexOf('(') - 1; - - try - { - lineNum = Convert.ToInt16(fileName.Substring(ini, end)); - } - catch - { - lineNum = 0; - } - - int colNum = 0; - string messageErr = outputText.Substring(outputText.IndexOf(": warning:") + 11); - fileName = fileName.Substring(0, fileName.IndexOf('(')); - BuildWarningEventArgs warningEvent = new BuildWarningEventArgs("", "", fileName, lineNum, colNum, 0, 0, messageErr, "", ""); - BuildEngine.LogWarningEvent(warningEvent); - } - else if (outputText.Contains("undefined reference")) - { - Regex re = new Regex(@":\d+:"); - Match m = re.Match(outputText); - string fileName = ""; - int lineNum = 0; - string message = ""; - - if (m.Success) - { - fileName = outputText.Substring(0, m.Index); - try - { - lineNum = Convert.ToInt16(m.Value.Trim(':')); - } - catch - { - lineNum = 0; - } - message = outputText.Substring(m.Index + m.Length).Trim(); - } - else - { - lineNum = 0; - fileName = outputText.Substring(0, outputText.IndexOf(':')); - message = outputText.Substring(outputText.LastIndexOf(':') + 1).Trim(); - } - - BuildErrorEventArgs errorEvent = new BuildErrorEventArgs("", "", fileName, lineNum, 1, 0, 0, message, "", ""); - BuildEngine.LogErrorEvent(errorEvent); - } - else - { - BuildMessageEventArgs taskEvent = new BuildMessageEventArgs(outputText, "", "", MessageImportance.High); - BuildEngine.LogMessageEvent(taskEvent); - } - - // Add the text to the collected output. - errorOutput.Append(Environment.NewLine + outputText); - } - } - - - /// GDB works with short path names only, which requires converting the path names to/from long ones. This function - /// returns the long path name for a given short one. - /// Short path name. - /// Returns this long path name. - /// Lenght of this long path name. - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern int GetLongPathName( - [MarshalAs(UnmanagedType.LPTStr)] - string path, - [MarshalAs(UnmanagedType.LPTStr)] - StringBuilder longPath, - int longPathLength - ); - - [Required] - public string ProjectDir - { - set { _projectDir = value.Replace('\\', '/'); } - get { return _projectDir; } - } - - [Required] - public string OutDir - { - set { _outDir = value.Replace('\\', '/'); } - get { return _outDir; } - } - - [Required] - public string ToolsPath - { - get; - set; - } - - /// - /// Perform Cancel Code - /// - public void Cancel() - { - try - { - proc.Kill(); - } - catch (Exception ex) - { - BuildMessageEventArgs taskEvent2 = new BuildMessageEventArgs(ex.Message, "", "", MessageImportance.High); - BuildEngine.LogMessageEvent(taskEvent2); - } - - } - } -} diff --git a/src/VSNDK.Tasks/PackagerCmdBuilder.cs b/src/VSNDK.Tasks/PackagerCmdBuilder.cs deleted file mode 100644 index 37b9b905..00000000 --- a/src/VSNDK.Tasks/PackagerCmdBuilder.cs +++ /dev/null @@ -1,44 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - class PackagerCmdBuilder : CommandLineBuilder - { - - /// - /// Constructor - /// - public PackagerCmdBuilder() - : base(true) - { - } - - /// - /// Override of IsQuotingRequired function. Always return true. - /// - /// - /// - protected override bool IsQuotingRequired(string parameter) - { - return true; - } - } -} diff --git a/src/VSNDK.Tasks/Properties/AssemblyInfo.cs b/src/VSNDK.Tasks/Properties/AssemblyInfo.cs deleted file mode 100644 index ebb81dcb..00000000 --- a/src/VSNDK.Tasks/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,50 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("VSNDK.Tasks")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("BlackBerry")] -[assembly: AssemblyProduct("VSNDK.Tasks")] -[assembly: AssemblyCopyright("Copyright © BlackBerry 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("d4362271-7b17-4734-86bb-39564f3e29fc")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/VSNDK.Tasks/Properties/Resources.Designer.cs b/src/VSNDK.Tasks/Properties/Resources.Designer.cs deleted file mode 100644 index fac27f14..00000000 --- a/src/VSNDK.Tasks/Properties/Resources.Designer.cs +++ /dev/null @@ -1,144 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.18408 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace VSNDK.Tasks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VSNDK.Tasks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to # This file is automatically generated by vs-ndk. - ///# Do not modify this file -- YOUR CHANGES WILL BE ERASED! - ///# - ///# This file must *NOT* be checked in Version Control Systems, - ///# as it contains information specific to your local configuration. - /// - ///# location of the SDK. This is only used by Ant - ///# For customization when using a Version Control System, please read the - ///# header note. - ///sdk.dir={SDKDIR}. - /// - internal static string localproperties_ant_file { - get { - return ResourceManager.GetString("localproperties_ant_file", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tracking command:. - /// - internal static string Native_TrackingCommandMessage { - get { - return ResourceManager.GetString("Native_TrackingCommandMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MSB8016: Can not turn on Unicode output for "{0}". Some Unicode characters will be improperly displayed.. - /// - internal static string TrackedVCToolTask_CreateUnicodeOutputPipeFailed { - get { - return ResourceManager.GetString("TrackedVCToolTask.CreateUnicodeOutputPipeFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Forcing rebuild of all source files due to a change in the command line since the last build.. - /// - internal static string TrackedVCToolTask_RebuildingAllSourcesCommandLineChanged { - get { - return ResourceManager.GetString("TrackedVCToolTask.RebuildingAllSourcesCommandLineChanged", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MSB8014: Forcing a rebuild of all sources due to an error with the tracking logs. {0}. - /// - internal static string TrackedVCToolTask_RebuildingDueToInvalidTLog { - get { - return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLog", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MSB8015: Forcing a rebuild of all source files due to the contents of "{0}" being invalid.. - /// - internal static string TrackedVCToolTask_RebuildingDueToInvalidTLogContents { - get { - return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLogContents", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Forcing rebuild of all source files due to missing command tlog "{0}".. - /// - internal static string TrackedVCToolTask_RebuildingNoCommandTLog { - get { - return ResourceManager.GetString("TrackedVCToolTask.RebuildingNoCommandTLog", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Forcing rebuild of source file "{0}" due to a change in the command line since the last build.. - /// - internal static string TrackedVCToolTask_RebuildingSourceCommandLineChanged { - get { - return ResourceManager.GetString("TrackedVCToolTask.RebuildingSourceCommandLineChanged", resourceCulture); - } - } - } -} diff --git a/src/VSNDK.Tasks/QccCompiler.cs b/src/VSNDK.Tasks/QccCompiler.cs deleted file mode 100644 index 45fc19bd..00000000 --- a/src/VSNDK.Tasks/QccCompiler.cs +++ /dev/null @@ -1,513 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.Utilities; -using Microsoft.Build.CPPTasks; -using System.Resources; -using System.Reflection; -using Microsoft.Build.Framework; -using System.Collections; -using System.IO; - -namespace VSNDK.Tasks -{ - public class QccCompiler : VSNDKTasks - { - #region fields - // Fields - private ITaskItem[] preprocessOutput; - - //constant fields - private const string ADDITIONAL_INCLUDEDIRECTORIES = "AdditionalIncludeDirectories"; - private const string PREPROCESSOR_DEFINITIONS = "PreprocessorDefinitions"; - private const string UNDEFINE_PREPROCESSOR_DEFINITION = "UndefinePreprocessorDefinition"; - private const string PREPROCESS_TO_FILE = "PreprocessToFile"; - private const string PREPROCESS_TO_STDOUT = "PreprocessToStdout"; - private const string PREPROCESS_KEEP_COMMENTS = "PreprocessKeepComments"; - private const string RUNTIME_TYPE_INFO = "RuntimeTypeInfo"; - private const string OBJECT_FILE_NAME = "ObjectFileName"; - private const string ANSI = "Ansi"; - #endregion - - #region ctors - public QccCompiler() - : base(new ResourceManager("VSNDK.Tasks.Properties.Resources", Assembly.GetExecutingAssembly())) - { - this.preprocessOutput = new ITaskItem[0]; - this.switchOrderList.Add(ADDITIONAL_INCLUDEDIRECTORIES); - this.switchOrderList.Add(ANSI); - this.switchOrderList.Add(PREPROCESSOR_DEFINITIONS); - this.switchOrderList.Add(UNDEFINE_PREPROCESSOR_DEFINITION); - this.switchOrderList.Add(PREPROCESS_TO_FILE); - this.switchOrderList.Add(PREPROCESS_TO_STDOUT); - this.switchOrderList.Add(PREPROCESS_KEEP_COMMENTS); - this.switchOrderList.Add(RUNTIME_TYPE_INFO); - this.switchOrderList.Add(OBJECT_FILE_NAME); - this.switchOrderList.Add(SOURCES); - } - #endregion - - #region overrides - /// - /// Getter/Setter for the AlwaysAppend property - /// - protected override string AlwaysAppend - { - get - { - return LinkSharedLibrary ? "-c -shared" : "-c"; - } - } - - /// - /// Getter/Setter for the AttributeFileTracking property - /// - public override bool AttributeFileTracking - { - get - { - return true; - } - } - - /// - /// Getter/Setter for the TrackedInputFiles property - /// - protected override Microsoft.Build.Framework.ITaskItem[] TrackedInputFiles - { - get - { - return Sources; - } - } - - /// - /// Execute the specified tool for building - /// - /// - /// - /// - /// - protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) - { - foreach (ITaskItem item in this.Sources) - { - string source = item.ItemSpec; - base.LogEventsFromTextOutput(source, MessageImportance.High); - } - return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); - } - - /// - /// Getter/Setter for the WriteTLogNames property - /// - protected override string[] WriteTLogNames - { - get - { - return new string[] { "qcc_compiler.write.1.tlog", "qcc_compiler.*.write.1.tlog" }; - } - } - - /// - /// Getter/Setter for the CommandTLogName property - /// - protected override string CommandTLogName - { - get - { - return "qcc_compiler.command.1.tlog"; - } - } - - /// - /// Getter/Setter for the ReadTLogNames property - /// - protected override string[] ReadTLogNames - { - get - { - return new string[] { "qcc_compiler.read.1.tlog", "qcc_compiler.*.read.1.tlog" }; - } - } - #endregion //override - - #region properties - - /// - /// GetterSetter for the AdditionalIncludeDirectories property. - /// - public string[] AdditionalIncludeDirectories - { - get - { - if (base.IsPropertySet(ADDITIONAL_INCLUDEDIRECTORIES)) - { - return base.ActiveToolSwitches[ADDITIONAL_INCLUDEDIRECTORIES].StringList; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(ADDITIONAL_INCLUDEDIRECTORIES); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) - { - DisplayName = "Additional Include Directories", - Description = "Specifies one or more directories to add to the include path; separate with semi-colons if more than one. (-I[path])", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-I", - Name = ADDITIONAL_INCLUDEDIRECTORIES, - StringList = value - }; - base.ActiveToolSwitches.Add(ADDITIONAL_INCLUDEDIRECTORIES, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the Ansi property - /// - public bool Ansi - { - get - { - return (base.IsPropertySet(ANSI) && base.ActiveToolSwitches[ANSI].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(ANSI); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Compile ANSI code", - Description = "Compile ansi code", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-ansi", - Name = ANSI, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(ANSI, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the MinimalRebuild property - /// - public virtual bool MinimalRebuild - { - get - { - return (base.IsPropertySet("MinimalRebuild") && base.ActiveToolSwitches["MinimalRebuild"].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove("MinimalRebuild"); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Enable Minimal Rebuild", - Description = "Enables minimal rebuild, which determines whether C++ source files that include changed C++ class definitions (stored in header (.h) files) need to be recompiled.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "/Gm", - ReverseSwitchValue = "/Gm-", - Name = "MinimalRebuild", - BooleanValue = value - }; - base.ActiveToolSwitches.Add("MinimalRebuild", switch2); - base.AddActiveSwitchToolValue(switch2); - switch2.Overrides.AddLast(new KeyValuePair("Gm", "Gm-")); - switch2.Overrides.AddLast(new KeyValuePair("Gm-", "Gm")); - } - } - - /// - /// Getter/Setter for the ObjectFileName property - /// - public string ObjectFileName - { - get - { - if (base.IsPropertySet(OBJECT_FILE_NAME)) - { - return base.ActiveToolSwitches[OBJECT_FILE_NAME].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(OBJECT_FILE_NAME); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Object File Name", - Description = "Specifies a name to override the default object file name; can be file or directory name. (-o[name])", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-o", - Name = OBJECT_FILE_NAME, - Value = value - }; - base.ActiveToolSwitches.Add(OBJECT_FILE_NAME, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the ExpandAttributedSource property - /// - public bool ExpandAttributedSource - { - get - { - return (base.IsPropertySet("ExpandAttributedSource") && base.ActiveToolSwitches["ExpandAttributedSource"].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove("ExpandAttributedSource"); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Expand Attributed Source", - Description = "Create listing file with expanded attributes injected into source file. (/Fx)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "/Fx", - Name = "ExpandAttributedSource", - BooleanValue = value - }; - base.ActiveToolSwitches.Add("ExpandAttributedSource", switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the FavorSizeOrSpeed property - /// - public string FavorSizeOrSpeed - { - get - { - if (base.IsPropertySet("FavorSizeOrSpeed")) - { - return base.ActiveToolSwitches["FavorSizeOrSpeed"].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove("FavorSizeOrSpeed"); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Favor Size Or Speed", - Description = "Whether to favor code size or code speed; 'Global Optimization' must be turned on. (/Ot, /Os)", - ArgumentRelationList = new ArrayList() - }; - string[][] switchMap = new string[][] { new string[] { "Size", "/Os" }, new string[] { "Speed", "/Ot" }, new string[] { "Neither", "" } }; - switch2.SwitchValue = base.ReadSwitchMap("FavorSizeOrSpeed", switchMap, value); - switch2.Name = "FavorSizeOrSpeed"; - switch2.Value = value; - switch2.MultiValues = true; - base.ActiveToolSwitches.Add("FavorSizeOrSpeed", switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the PreprocessKeepComments property - /// - public bool PreprocessKeepComments - { - get - { - return (base.IsPropertySet(PREPROCESS_KEEP_COMMENTS) && base.ActiveToolSwitches[PREPROCESS_KEEP_COMMENTS].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(PREPROCESS_KEEP_COMMENTS); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Keep Comments", - Description = "Suppresses comment strip from source code; requires that one of the 'Preprocessing' options be set. (-C)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-C", - Name = PREPROCESS_KEEP_COMMENTS, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(PREPROCESS_KEEP_COMMENTS, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for hte PreprocessorDefinitions property - /// - public string[] PreprocessorDefinitions - { - get - { - if (base.IsPropertySet(PREPROCESSOR_DEFINITIONS)) - { - return base.ActiveToolSwitches[PREPROCESSOR_DEFINITIONS].StringList; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PREPROCESSOR_DEFINITIONS); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) - { - DisplayName = "Preprocessor Definitions", - Description = "Defines a preprocessing symbols for your source file.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-D", - Name = PREPROCESSOR_DEFINITIONS, - StringList = value - }; - base.ActiveToolSwitches.Add(PREPROCESSOR_DEFINITIONS, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the PreprocessOutput property - /// - [Output] - public ITaskItem[] PreprocessOutput - { - get - { - return this.preprocessOutput; - } - set - { - this.preprocessOutput = value; - } - } - - /// - /// Getter/Setter for the PreprocessOutputPath - /// - public string PreprocessOutputPath - { - get - { - if (base.IsPropertySet(PREPROCESS_TO_STDOUT)) - { - return base.ActiveToolSwitches[PREPROCESS_TO_STDOUT].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PREPROCESS_TO_STDOUT); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Preprocess Output Path", - Description = "Specify the output path for the preprocesser. The default location is the same as the source file(s).", - ArgumentRelationList = new ArrayList(), - Name = PREPROCESS_TO_STDOUT, - Value = value, - SwitchValue = "E" - }; - base.ActiveToolSwitches.Add(PREPROCESS_TO_STDOUT, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the PreprocessSuppressLineNumbers property - /// - public bool PreprocessSuppressLineNumbers - { - get - { - return (base.IsPropertySet("PreprocessSuppressLineNumbers") && base.ActiveToolSwitches["PreprocessSuppressLineNumbers"].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove("PreprocessSuppressLineNumbers"); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Preprocess Suppress Line Numbers", - Description = "Preprocess without #line directives.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "/EP", - Name = "PreprocessSuppressLineNumbers", - BooleanValue = value - }; - base.ActiveToolSwitches.Add("PreprocessSuppressLineNumbers", switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the PreprocessToFile property - /// - public bool PreprocessToFile - { - get - { - return (base.IsPropertySet(PREPROCESS_TO_FILE) && base.ActiveToolSwitches[PREPROCESS_TO_FILE].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(PREPROCESS_TO_FILE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Preprocess to a File", - Description = "Preprocesses C and C++ source files and writes the preprocessed output to a file. This option suppresses compilation, thus it does not produce an .obj file.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-P", - Name = PREPROCESS_TO_FILE, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(PREPROCESS_TO_FILE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the UndefinePreprocessorDefinition property - /// - public string[] UndefinePreprocessorDefinition - { - get - { - if (base.IsPropertySet(UNDEFINE_PREPROCESSOR_DEFINITION)) - { - return base.ActiveToolSwitches[UNDEFINE_PREPROCESSOR_DEFINITION].StringList; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(UNDEFINE_PREPROCESSOR_DEFINITION); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) - { - DisplayName = "Undefine Preprocessor Definitions", - Description = "Specifies one or more preprocessor undefines. (-U[macro])", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-U", - Name = UNDEFINE_PREPROCESSOR_DEFINITION, - StringList = value - }; - base.ActiveToolSwitches.Add(UNDEFINE_PREPROCESSOR_DEFINITION, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - public bool RuntimeTypeInfo { get; set; } - public bool ShortEnums { get; set; } - #endregion //properties - } -} diff --git a/src/VSNDK.Tasks/QccLib.cs b/src/VSNDK.Tasks/QccLib.cs deleted file mode 100644 index e446e89b..00000000 --- a/src/VSNDK.Tasks/QccLib.cs +++ /dev/null @@ -1,244 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.CPPTasks; -using System.Resources; -using System.Reflection; -using System.Collections; - -namespace VSNDK.Tasks -{ - public class QccLib : VSNDKTasks - { - #region Member Variables and Constants - private const string ADDITIONAL_DEPENDENCIES = "AdditionalDependencies"; - private const string ADDITIONAL_LIB_DIR = "AdditionalLibraryDirectories"; - private const string OUTPUT_FILE = "OutputFile"; - private const string LINK_STATIC = "LinkStatic"; - private const string TREAT_LIB_WARNING_AS_ERROR = "TreatLibWarningAsErrors"; - #endregion - - /// - /// QccLib Constructor - /// - public QccLib() - : base(new ResourceManager("VSNDK.Tasks.Properties.Resources", Assembly.GetExecutingAssembly())) - { - this.switchOrderList.Add(ADDITIONAL_DEPENDENCIES); - this.switchOrderList.Add(ADDITIONAL_LIB_DIR); - this.switchOrderList.Add(TREAT_LIB_WARNING_AS_ERROR); - this.switchOrderList.Add(OUTPUT_FILE); - this.switchOrderList.Add(SOURCES); - } - - #region overrides - - /// - /// Getter/Setter for the AlwaysAppend property - /// - protected override string AlwaysAppend - { - get - { - return string.Empty; - } - } - - /// - /// Getter/Setter for the CommandTLogName property - /// - protected override string CommandTLogName - { - get { return "qcc_lib.command.1.tlog"; } - } - - /// - /// Getter/Setter for the ReadTLogNames property - /// - protected override string[] ReadTLogNames - { - get { return new string[] { "qcc_lib.read.1.tlog", "qcc_lib.*.read.1.tlog" }; } - } - - /// - /// Getter/Setter for the WriteTLogNames - /// - protected override string[] WriteTLogNames - { - get - { - return new string[] { "qcc_lib.write.1.tlog", "qcc_lib.*.write.1.tlog" }; - } - } - - /// - /// Method return the EnhancedSecuritySwitch - /// - /// - protected override string GetEnhancedSecuritySwitchValue() - { - return string.Empty; - } - #endregion overrides - - #region properties - /// - /// Getter/Setter for the LinkStatic property - /// - public bool LinkStatic - { - get - { - return (base.IsPropertySet(LINK_STATIC) && base.ActiveToolSwitches[LINK_STATIC].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(LINK_STATIC); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Link Static", - Description = "Static link Lib", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-static", - Name = LINK_STATIC, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(LINK_STATIC, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the AdditionalDependencies property - /// - public virtual string[] AdditionalDependencies - { - get - { - if (base.IsPropertySet(ADDITIONAL_DEPENDENCIES)) - { - return base.ActiveToolSwitches[ADDITIONAL_DEPENDENCIES].StringList; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(ADDITIONAL_DEPENDENCIES); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) - { - DisplayName = "Additional Dependencies", - Description = "Specifies additional items to add to the link command line [i.e. bps] ", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-l", - Name = ADDITIONAL_DEPENDENCIES, - StringList = value - }; - base.ActiveToolSwitches.Add(ADDITIONAL_DEPENDENCIES, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the AdditionalLibraryDirectories property - /// - public virtual string[] AdditionalLibraryDirectories - { - get - { - if (base.IsPropertySet(ADDITIONAL_LIB_DIR)) - { - return base.ActiveToolSwitches[ADDITIONAL_LIB_DIR].StringList; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(ADDITIONAL_LIB_DIR); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) - { - DisplayName = "Additional Library Directories", - Description = "Allows the user to override the environmental library path (-Lfolder)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-L", - Name = ADDITIONAL_LIB_DIR, - StringList = value - }; - base.ActiveToolSwitches.Add(ADDITIONAL_LIB_DIR, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the TreatLibWarningAsErrors property - /// - public virtual bool TreatLibWarningAsErrors - { - get - { - return (base.IsPropertySet(TREAT_LIB_WARNING_AS_ERROR) && base.ActiveToolSwitches[TREAT_LIB_WARNING_AS_ERROR].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(TREAT_LIB_WARNING_AS_ERROR); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Treat Lib Warning As Errors", - Description = "-Werror causes no output file to be generated if lib generates a warning.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-Werror", - Name = TREAT_LIB_WARNING_AS_ERROR, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(TREAT_LIB_WARNING_AS_ERROR, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// GetterSetter for the OutputFile property - /// - public virtual string OutputFile - { - get - { - if (base.IsPropertySet(OUTPUT_FILE)) - { - return base.ActiveToolSwitches[OUTPUT_FILE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(OUTPUT_FILE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - //Separator = ":", - DisplayName = "Output File", - Description = "The -A option overrides the default name and location of the program that the linker creates.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-A ", - Name = OUTPUT_FILE, - Value = value - }; - base.ActiveToolSwitches.Add(OUTPUT_FILE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - #endregion properties - } -} diff --git a/src/VSNDK.Tasks/QccLink.cs b/src/VSNDK.Tasks/QccLink.cs deleted file mode 100644 index cc8eda2f..00000000 --- a/src/VSNDK.Tasks/QccLink.cs +++ /dev/null @@ -1,401 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.CPPTasks; -using System.Resources; -using System.Reflection; -using Microsoft.Build.Framework; -using System.Collections; -using Microsoft.Build.Utilities; -using System.IO; - -namespace VSNDK.Tasks -{ - public class QccLink : VSNDKTasks - { - #region Member Variables and Constants - private const string ADDITIONAL_DEPENDENCIES = "AdditionalDependencies"; - private const string LINK_ERROR_REPORTING = "LinkErrorReporting"; - private const string ADDITIONAL_LIB_DIR = "AdditionalLibraryDirectories"; - private const string GENERATE_MAP_FILE = "GenerateMapFile"; - private const string IGNORE_ALL_DEFAULT_LIB = "IgnoreAllDefaultLibraries"; - private const string IGNOR_ALL_DEFAULT_CPP_LIB = "IgnoreAllDefaultCppLibraries"; - private const string LINK_INCREMENTAL = "LinkIncremental"; - private const string LINK_STATUS = "LinkStatus"; - private const string LINK_LIB_DEP = "LinkLibraryDependencies"; - private const string OUTPUT_FILE = "OutputFile"; - private const string TREAT_LINK_WARNING_AS_ERR = "TreatLinkerWarningAsErrors"; - #endregion - - /// - /// QccLink Constructor - /// - public QccLink() - : base(new ResourceManager("VSNDK.Tasks.Properties.Resources", Assembly.GetExecutingAssembly())) - { - this.switchOrderList.Add(ADDITIONAL_DEPENDENCIES); - this.switchOrderList.Add(LINK_ERROR_REPORTING); - this.switchOrderList.Add(ADDITIONAL_LIB_DIR); - this.switchOrderList.Add(GENERATE_MAP_FILE); - this.switchOrderList.Add(IGNORE_ALL_DEFAULT_LIB); - this.switchOrderList.Add(IGNOR_ALL_DEFAULT_CPP_LIB); - this.switchOrderList.Add(LINK_INCREMENTAL); - this.switchOrderList.Add(LINK_STATUS); - this.switchOrderList.Add(LINK_LIB_DEP); - this.switchOrderList.Add(OUTPUT_FILE); - this.switchOrderList.Add(TREAT_LINK_WARNING_AS_ERR); - this.switchOrderList.Add(SOURCES); - } - - #region overrides - - /// - /// Getter/Setter for AlwaysAppend property - /// - protected override string AlwaysAppend - { - get - { - return LinkSharedLibrary? "-shared" : string.Empty; - } - } - - /// - /// Getter/Setter for CommandTLogName property - /// - protected override string CommandTLogName - { - get { return "qcc_linker.command.1.tlog"; } - } - - /// - /// Getter/Setter for ReadTLog - /// - protected override string[] ReadTLogNames - { - get { return new string[] { "qcc_linker.read.1.tlog", "qcc_linker.*.read.1.tlog" }; } - } - - /// - /// Getter/Setter WriteTLogNames property - /// - protected override string[] WriteTLogNames - { - get - { - return new string[] { "qcc_linker.write.1.tlog", "qcc_linker.*.write.1.tlog" }; - } - } - - /// - /// Function to return the Enhanced Security value. - /// - /// - protected override string GetEnhancedSecuritySwitchValue() - { - return "-Wl,-z,relro -Wl,-z,now"; - } - #endregion - - #region properties - - /// - /// Getter/Setter for the AdditionalDependencies property - /// - public virtual string[] AdditionalDependencies - { - get - { - if (base.IsPropertySet(ADDITIONAL_DEPENDENCIES)) - { - return base.ActiveToolSwitches[ADDITIONAL_DEPENDENCIES].StringList; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(ADDITIONAL_DEPENDENCIES); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) - { - DisplayName = "Additional Dependencies", - Description = "Specifies additional items to add to the link command line [i.e. bps] ", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-l", - Name = ADDITIONAL_DEPENDENCIES, - StringList = value - }; - base.ActiveToolSwitches.Add(ADDITIONAL_DEPENDENCIES, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the AdditionalLibraryDirectories property - /// - public virtual string[] AdditionalLibraryDirectories - { - get - { - if (base.IsPropertySet(ADDITIONAL_LIB_DIR)) - { - return base.ActiveToolSwitches[ADDITIONAL_LIB_DIR].StringList; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(ADDITIONAL_LIB_DIR); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) - { - DisplayName = "Additional Library Directories", - Description = "Allows the user to override the environmental library path (-Lfolder)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-L", - Name = ADDITIONAL_LIB_DIR, - StringList = value - }; - base.ActiveToolSwitches.Add(ADDITIONAL_LIB_DIR, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the GenerateMapFile property - /// - public virtual bool GenerateMapFile - { - get - { - return (base.IsPropertySet(GENERATE_MAP_FILE) && base.ActiveToolSwitches[GENERATE_MAP_FILE].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(GENERATE_MAP_FILE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Generate Map File", - Description = "The -M option tells the linker to create a mapfile.", - ArgumentRelationList = new ArrayList() - }; - switch2.ArgumentRelationList.Add(new ArgumentRelation("MapFileName", "true", false, "")); - switch2.SwitchValue = "-M"; - switch2.Name = GENERATE_MAP_FILE; - switch2.BooleanValue = value; - base.ActiveToolSwitches.Add(GENERATE_MAP_FILE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the IgnoreAllDefaultLibraries - /// - public virtual bool IgnoreAllDefaultLibraries - { - get - { - return (base.IsPropertySet(IGNORE_ALL_DEFAULT_LIB) && base.ActiveToolSwitches[IGNORE_ALL_DEFAULT_LIB].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(IGNORE_ALL_DEFAULT_LIB); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Ignore All Default Libraries", - Description = "The -nostdlib option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. ", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-nostdlib", - Name = IGNORE_ALL_DEFAULT_LIB, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(IGNORE_ALL_DEFAULT_LIB, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the IgnoreAllDefaultCppLibraries property - /// - public virtual bool IgnoreAllDefaultCppLibraries - { - get - { - return (base.IsPropertySet(IGNOR_ALL_DEFAULT_CPP_LIB) && base.ActiveToolSwitches[IGNOR_ALL_DEFAULT_CPP_LIB].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(IGNOR_ALL_DEFAULT_CPP_LIB); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Ignore All Default C++ Libraries", - Description = "The -nostdlib++ option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. ", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-nostdlib++", - Name = IGNOR_ALL_DEFAULT_CPP_LIB, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(IGNOR_ALL_DEFAULT_CPP_LIB, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the LinkIncremental Property - /// - public virtual bool LinkIncremental - { - get - { - return (base.IsPropertySet(LINK_INCREMENTAL) && base.ActiveToolSwitches[LINK_INCREMENTAL].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(LINK_INCREMENTAL); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Enable Incremental Linking", - Description = "Enables incremental linking. (/INCREMENTAL, /INCREMENTAL:NO)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "/INCREMENTAL", - ReverseSwitchValue = "/INCREMENTAL:NO", - Name = LINK_INCREMENTAL, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(LINK_INCREMENTAL, switch2); - base.AddActiveSwitchToolValue(switch2); - switch2.Overrides.AddLast(new KeyValuePair("INCREMENTAL", "INCREMENTAL:NO")); - switch2.Overrides.AddLast(new KeyValuePair("INCREMENTAL:NO", "INCREMENTAL")); - } - } - - /// - /// Getter/Setter for the LinkStatus property - /// - public virtual bool LinkStatus - { - get - { - return (base.IsPropertySet(LINK_STATUS) && base.ActiveToolSwitches[LINK_STATUS].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(LINK_STATUS); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Link Status", - Description = "Specifies whether the linker should display a progress indicator showing what percentage of the link is complete. The default is to not display this status information. (/LTCG:STATUS|LTCG:NOSTATUS)", - ArgumentRelationList = new ArrayList(), - SwitchValue = "/LTCG:STATUS", - ReverseSwitchValue = "/LTCG:NOSTATUS", - Name = LINK_STATUS, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(LINK_STATUS, switch2); - base.AddActiveSwitchToolValue(switch2); - switch2.Overrides.AddLast(new KeyValuePair("LTCG:STATUS", "LTCG:NOSTATUS")); - switch2.Overrides.AddLast(new KeyValuePair("LTCG:NOSTATUS", "LTCG:STATUS")); - } - } - - /// - /// Getter/Setter for the LinkLibraryDependencies - /// - public virtual bool LinkLibraryDependencies - { - get - { - return (base.IsPropertySet(LINK_LIB_DEP) && base.ActiveToolSwitches[LINK_LIB_DEP].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(LINK_LIB_DEP); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Link Library Dependencies", - Description = "Specifies whether or not library outputs from project dependencies are automatically linked in.", - ArgumentRelationList = new ArrayList(), - Name = LINK_LIB_DEP, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(LINK_LIB_DEP, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the OutputFile property - /// - public virtual string OutputFile - { - get - { - if (base.IsPropertySet(OUTPUT_FILE)) - { - return base.ActiveToolSwitches[OUTPUT_FILE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(OUTPUT_FILE); - - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) - { - DisplayName = "Output File", - Description = "The -o option overrides the default name and location of the program that the linker creates.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-o ", - Name = OUTPUT_FILE, - Value = value - }; - base.ActiveToolSwitches.Add(OUTPUT_FILE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the TreatLinkerWarningAsErrors property. - /// - public virtual bool TreatLinkerWarningAsErrors - { - get - { - return (base.IsPropertySet(TREAT_LINK_WARNING_AS_ERR) && base.ActiveToolSwitches[TREAT_LINK_WARNING_AS_ERR].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(TREAT_LINK_WARNING_AS_ERR); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Treat Linker Warning As Errors", - Description = "/WX causes no output file to be generated if the linker generates a warning.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "/WX", - ReverseSwitchValue = "/WX:NO", - Name = TREAT_LINK_WARNING_AS_ERR, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(TREAT_LINK_WARNING_AS_ERR, switch2); - base.AddActiveSwitchToolValue(switch2); - switch2.Overrides.AddLast(new KeyValuePair("WX", "WX:NO")); - switch2.Overrides.AddLast(new KeyValuePair("WX:NO", "WX")); - } - } - #endregion - - } -} diff --git a/src/VSNDK.Tasks/RemoveFlagFile.cs b/src/VSNDK.Tasks/RemoveFlagFile.cs deleted file mode 100644 index a8034e56..00000000 --- a/src/VSNDK.Tasks/RemoveFlagFile.cs +++ /dev/null @@ -1,69 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Collections; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - - /// - /// MSBuild Task for reading in the flag file from the start debugging button. - /// - public class RemoveFlagFile : Task - { - #region Member Variables and Constants. - private string _flagFile; - #endregion - - /// - /// Execute the MSBuild Task - /// - /// - public override bool Execute() - { - bool removed; - try - { - File.Delete(_flagFile); - removed = true; - } - catch (DirectoryNotFoundException dirNotFound) - { - Console.WriteLine(dirNotFound.Message); - removed = false; - } - - return removed; - } - - /// - /// Setter for FlagFile property - /// - [Required] - public string FlagFile - { - set - { - _flagFile = value; - } - } - } -} diff --git a/src/VSNDK.Tasks/SSHDelete.cs b/src/VSNDK.Tasks/SSHDelete.cs deleted file mode 100644 index 6eeff091..00000000 --- a/src/VSNDK.Tasks/SSHDelete.cs +++ /dev/null @@ -1,325 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.CPPTasks; -using System.Resources; -using System.Reflection; -using System.Collections; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - public class SSHDelete : TrackedVCToolTask - { - #region Member Variables and Constants - protected ArrayList switchOrderList; - - private const string DEVICE = "Device"; - private const string PRIVATE_KEY_PATH = "PrivateKeyPath"; - private const string DELETE_FILES = "DeleteFiles"; - private const string PACKAGE_ID = "PackageId"; - private const string PACKAGE_NAME = "PackageName"; - #endregion - - /// - /// SSHDelete Constructor - /// - public SSHDelete() - : base(new ResourceManager("VSNDK.Tasks.Properties.Resources", Assembly.GetExecutingAssembly())) - { - this.switchOrderList = new ArrayList(); - this.switchOrderList.Add(PRIVATE_KEY_PATH); - } - - /// - /// Return the Response File Switch string - /// - /// - /// - protected override string GetResponseFileSwitch(string responseFilePath) - { - return string.Empty; - } - - /// - /// Return the command line string - /// - /// - protected override string GenerateCommandLineCommands() - { - return GenerateResponseFileCommands(); - } - - /// - /// Getter/Setter for the CommandTLogName property - /// - protected override string CommandTLogName - { - get { return "SSHDelete.command.1.tlog"; } - } - - /// - /// Getter/Setter for the ReadTLogNames string - /// - protected override string[] ReadTLogNames - { - get { return new string[] { "SSHDelete.read.1.tlog", "SSHDelete.*.read.1.tlog" }; } - } - - /// - /// Getter/Setter for the WriteTLogNames string - /// - protected override string[] WriteTLogNames - { - get - { - return new string[] { "SSHDelete.write.1.tlog", "SSHDelete.*.write.1.tlog" }; - } - } - - /// - /// Getter/Setter for the TrackedInputFiles string - /// - protected override Microsoft.Build.Framework.ITaskItem[] TrackedInputFiles - { - get - { - if (base.IsPropertySet(DELETE_FILES)) - { - return base.ActiveToolSwitches[DELETE_FILES].TaskItemArray; - } - return null; - } - } - - /// - /// Getter/Setter for the ToolName property - /// - protected override string ToolName - { - get - { - return ToolExe; - } - } - - /// - /// Getter/Setter for the TrackerIntermediateDirectory property - /// - protected override string TrackerIntermediateDirectory - { - get - { - return string.Empty; - } - } - - /// - /// Function to generate the response file commands string - /// - /// - protected override string GenerateResponseFileCommands() - { - string cmd = base.GenerateResponseFileCommands(); - - cmd += " -o \"StrictHostKeyChecking no\""; - - if (base.IsPropertySet(DEVICE)) - { - cmd += " devuser@" + base.ActiveToolSwitches[DEVICE].Value; - } - - if (base.IsPropertySet(DELETE_FILES)) - { - string path = "../../../../apps/" + PackageName + "." + PackageId + "/"; - cmd += " '"; - foreach (ITaskItem taskItem in base.ActiveToolSwitches[DELETE_FILES].TaskItemArray) - { - cmd += "rm " + path + taskItem.GetMetadata("Identity") + "; "; - } - cmd += "'"; - } - else - { - cmd += "'pwd;'"; - } - - return cmd; - } - - /// - /// Getter/Setter for the SwitchOrderList property. - /// - protected override ArrayList SwitchOrderList - { - get - { - return this.switchOrderList; - } - } - - /// - /// Getter/Setter for the Device property - /// - public virtual string Device - { - get - { - if (base.IsPropertySet(DEVICE)) - { - return base.ActiveToolSwitches[DEVICE].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(DEVICE); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = DEVICE, - DisplayName = "Device IP", - Description = "Specifies the target device's IP address.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "devuser@", - Value = value - }; - base.ActiveToolSwitches.Add(DEVICE, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the PrivateKeyPath property - /// - public virtual string PrivateKeyPath - { - get - { - if (base.IsPropertySet(PRIVATE_KEY_PATH)) - { - return base.ActiveToolSwitches[PRIVATE_KEY_PATH].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PRIVATE_KEY_PATH); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PRIVATE_KEY_PATH, - DisplayName = "Path to public key", - Description = "The -i option specifies the public SSH key to use.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-i ", - Value = value - }; - base.ActiveToolSwitches.Add(PRIVATE_KEY_PATH, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the PackageId property - /// - public virtual string PackageId - { - get - { - if (base.IsPropertySet(PACKAGE_ID)) - { - return base.ActiveToolSwitches[PACKAGE_ID].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PACKAGE_ID); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PACKAGE_ID, - DisplayName = "Package ID", - Description = "The -package-id option specifies the application's package id.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-package-id ", - Value = value - }; - base.ActiveToolSwitches.Add(PACKAGE_ID, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the PackageName property - /// - public virtual string PackageName - { - get - { - if (base.IsPropertySet(PACKAGE_NAME)) - { - return base.ActiveToolSwitches[PACKAGE_NAME].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(PACKAGE_NAME); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) - { - Name = PACKAGE_NAME, - DisplayName = "Package Name", - Description = "The -package-name option specifies the application's package name.", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-package-name ", - Value = value - }; - base.ActiveToolSwitches.Add(PACKAGE_NAME, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - - /// - /// Getter/Setter for the DeleteFiles property - /// - public virtual ITaskItem[] DeleteFiles - { - get - { - if (base.IsPropertySet(DELETE_FILES)) - { - return base.ActiveToolSwitches[DELETE_FILES].TaskItemArray; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(DELETE_FILES); - ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.ITaskItemArray) - { - Name = DELETE_FILES, - DisplayName = "Files to delete", - Description = "Delete all items in the array from the device.", - TaskItemArray = value - }; - base.ActiveToolSwitches.Add(DELETE_FILES, toolSwitch); - base.AddActiveSwitchToolValue(toolSwitch); - } - } - } -} diff --git a/src/VSNDK.Tasks/VSNDK.Tasks.csproj b/src/VSNDK.Tasks/VSNDK.Tasks.csproj deleted file mode 100644 index da22f1de..00000000 --- a/src/VSNDK.Tasks/VSNDK.Tasks.csproj +++ /dev/null @@ -1,274 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C} - Library - Properties - VSNDK.Tasks - VSNDK.Tasks - v4.0 - 512 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - True - - - True - - - - False - ..\..\..\..\..\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.Build.CPPTasks.Common.dll - - - - - - - - - - - - - - - - - bar-descriptor.xsd - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - - - Designer - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Always - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Always - Designer - - - Always - - - - - Designer - - - Always - - - Always - - - Always - Designer - - - Always - Designer - - - Designer - Always - - - Always - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - Always - Designer - - - Always - - - Always - - - Designer - Always - - - Always - - - Always - Designer - - - Designer - Always - - - Designer - Always - - - Designer - Always - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - - - - - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/VSNDK.Tasks.csproj.user b/src/VSNDK.Tasks/VSNDK.Tasks.csproj.user deleted file mode 100644 index e7613c65..00000000 --- a/src/VSNDK.Tasks/VSNDK.Tasks.csproj.user +++ /dev/null @@ -1,13 +0,0 @@ - - - - Program - C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe - /rootsuffix Exp - - - Program - C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe - /rootsuffix Exp - - \ No newline at end of file diff --git a/src/VSNDK.Tasks/VSNDKTasks.cs b/src/VSNDK.Tasks/VSNDKTasks.cs deleted file mode 100644 index 13c4ad04..00000000 --- a/src/VSNDK.Tasks/VSNDKTasks.cs +++ /dev/null @@ -1,680 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.Utilities; -using Microsoft.Build.CPPTasks; -using System.Resources; -using System.Reflection; -using Microsoft.Build.Framework; -using System.Collections; -using System.IO; - -namespace VSNDK.Tasks -{ - public abstract class VSNDKTasks : TrackedVCToolTask - { - #region fields - // Fields - protected ArrayList switchOrderList; - - //constant fields - protected const string GENERATE_DEBUG_INFORMATION = "GenerateDebugInformation"; - protected const string WARING_LEVEL = "WarningLevel"; - protected const string TREAT_WARNING_AS_ERROR = "TreatWarningAsError"; - protected const string TRACKER_LOG_DIRECTORY = "TrackerLogDirectory"; - protected const string OPTIMIZATION = "Optimization"; - protected const string GCC_EXCEPTION_HANDLING = "GccExceptionHandling"; - protected const string SOURCES = "Sources"; - protected const string ADDITIONAL_OPTIONS = "AdditionalOptions"; - protected const string BUILDING_IN_IDE = "BuildingInIDE"; - protected const string ENHANCED_SECURITY = "EnhancedSecurity"; - protected const string POSITION_INDEPENDENT_EXECUTABLE = "PIE"; - protected const string COMPILER_VERSION_TARGET = "CompilerVersionTarget"; - protected const string VERBOSE = "Verbose"; - protected const string COMPILE_AS = "CompileAs"; - - private static string ERROR = " error:"; - private static string WARNING = " warning:"; - #endregion - - #region ctors - - /// - /// VSNDKTasks Constructor - /// - /// - public VSNDKTasks(ResourceManager res) - : base(res) - { - this.switchOrderList = new ArrayList(); - this.switchOrderList.Add(COMPILER_VERSION_TARGET); - this.switchOrderList.Add("AlwaysAppend"); - this.switchOrderList.Add(GENERATE_DEBUG_INFORMATION); - this.switchOrderList.Add(VERBOSE); - this.switchOrderList.Add(WARING_LEVEL); - this.switchOrderList.Add(TREAT_WARNING_AS_ERROR); - this.switchOrderList.Add(TRACKER_LOG_DIRECTORY); - this.switchOrderList.Add(OPTIMIZATION); - this.switchOrderList.Add(GCC_EXCEPTION_HANDLING); - this.switchOrderList.Add(ADDITIONAL_OPTIONS); - this.switchOrderList.Add(BUILDING_IN_IDE); - this.switchOrderList.Add(ENHANCED_SECURITY); - this.switchOrderList.Add(POSITION_INDEPENDENT_EXECUTABLE); - this.switchOrderList.Add(COMPILE_AS); - } - #endregion - - #region overrides - /// - /// don't use response file for msbuild because it is removed before qcc to run GCC compiler - /// - /// - /// - protected override string GetResponseFileSwitch(string responseFilePath) - { - return string.Empty; - } - - /// - /// instead pass the response file to command line commands - /// - /// - protected override string GenerateCommandLineCommands() - { - string cmd = GenerateResponseFileCommands(); - return cmd; - } - - /// - /// Function to assign out of date sources - /// - /// - /// - protected override ITaskItem[] AssignOutOfDateSources(ITaskItem[] sources) - { - base.ActiveToolSwitches[SOURCES].TaskItemArray = sources; - return sources; - } - - /// - /// Getter/Setter for SwitchOrderList property - /// - protected override ArrayList SwitchOrderList - { - get - { - return this.switchOrderList; - } - } - - /// - /// Getter/Setter for TrackedInputFiles property - /// - protected override Microsoft.Build.Framework.ITaskItem[] TrackedInputFiles - { - get - { - return Sources; - } - } - - /// - /// Getter/Setter for TrackerIntermediateDirectory - /// - protected override string TrackerIntermediateDirectory - { - get - { - if (this.TrackerLogDirectory != null) - { - return this.TrackerLogDirectory; - } - return string.Empty; - } - } - - /// - /// Getter/Setter for ToolName property - /// - protected override string ToolName - { - get { return QccExe; } - } - - /// - /// Getter/Setter for LogEventsFromTextOutput - /// - /// - /// - protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) - { - base.LogEventsFromTextOutput(Reformat(singleLine), messageImportance); - } - - - - /// - /// Reformat the qcc compiler error to msbuild known error format - /// singeLine: main.c:53: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int' - /// or main.c:38:19: error: hello.h: No such file or directory - /// output: main.c(53): error QCC001: expected '=', ',', ';', 'asm' or '__attribute__' before 'int' - /// TODO: this method need to be updated in case any more error formats of qcc compiler - /// - /// - /// - private string Reformat(string singleLine) - { - string msbuilError = singleLine; - string[] separators = { ERROR, WARNING }; - string errCode = singleLine.Contains(ERROR) ? "error qcc" : "warning qcc"; - string[] parts = singleLine.Split(separators, StringSplitOptions.None); - if (parts != null && parts.Length > 1) - { - string[] segments = parts[0].Split(new Char[]{':'}, StringSplitOptions.RemoveEmptyEntries); - if (segments.Length == 3) - msbuilError = String.Format("{0}({1}-{2}): {3}: {4}", segments[0], segments[1], segments[2], errCode, parts[1]); - if ( segments.Length == 2 ) - msbuilError = String.Format("{0}({1}): {2}: {3}", segments[0], segments[1], errCode, parts[1]); - } - return msbuilError; - } - - /// - /// getter/setter for UseUnicodeOutput - /// - protected override bool UseUnicodeOutput - { - get - { - return this.BuildingInIDE; - } - } - - #endregion //override - - #region properties - - /// - /// Getter/Setter for GenerateDebugInformation property - /// - public virtual bool GenerateDebugInformation - { - get - { - if (base.IsPropertySet(GENERATE_DEBUG_INFORMATION)) - { - return base.ActiveToolSwitches[GENERATE_DEBUG_INFORMATION].BooleanValue; - } - return false; - } - set - { - base.ActiveToolSwitches.Remove(GENERATE_DEBUG_INFORMATION); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Generate Debug Info", - Description = "Generate Debug Info (-g)", - ArgumentRelationList = new ArrayList() - }; - switch2.SwitchValue = "-g"; - switch2.Name = GENERATE_DEBUG_INFORMATION; - switch2.BooleanValue = value; - base.ActiveToolSwitches.Add(GENERATE_DEBUG_INFORMATION, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for WarningLevel property - /// - public virtual string WarningLevel - { - get - { - if (base.IsPropertySet(WARING_LEVEL)) - { - return base.ActiveToolSwitches[WARING_LEVEL].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(WARING_LEVEL); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Warning Level", - Description = "Select how strict you want the compiler to be about code errors. (-w0 - -w4)", - ArgumentRelationList = new ArrayList() - }; - string[][] switchMap = new string[][] - { new string[] { "TurnOffAllWarnings", "-w0" }, - new string[] { "Level1", "-w1" }, - new string[] { "Level2", "-w2" }, - new string[] { "Level3", "-w3" }, - new string[] { "Level4", "-w4" }, - new string[] { "Level5", "-w5" }, - new string[] { "Level6", "-w6" }, - new string[] { "Level7", "-w7" }, - new string[] { "Level8", "-w8" }, - new string[] { "Level9", "-w9" }, - new string[] { "EnableAllWarnings", "-Wall" } }; - switch2.SwitchValue = base.ReadSwitchMap(WARING_LEVEL, switchMap, value); - switch2.Name = WARING_LEVEL; - switch2.Value = value; - switch2.MultiValues = true; - base.ActiveToolSwitches.Add(WARING_LEVEL, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for TreatWarningAsError property - /// - public virtual bool TreatWarningAsError - { - get - { - if (base.IsPropertySet(TREAT_WARNING_AS_ERROR)) - { - return base.ActiveToolSwitches[TREAT_WARNING_AS_ERROR].BooleanValue; - } - return false; - } - set - { - base.ActiveToolSwitches.Remove(TREAT_WARNING_AS_ERROR); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Treat Warnings as Errors", - Description = "Treat Warnings as Errors", - ArgumentRelationList = new ArrayList() - }; - switch2.ArgumentRelationList.Add(new ArgumentRelation(TREAT_WARNING_AS_ERROR, "true", false, "")); - switch2.SwitchValue = "-Werror"; - switch2.Name = TREAT_WARNING_AS_ERROR; - switch2.BooleanValue = value; - base.ActiveToolSwitches.Add(TREAT_WARNING_AS_ERROR, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for BuildingInIDE property - /// - public virtual bool BuildingInIDE - { - get - { - return (base.IsPropertySet(BUILDING_IN_IDE) && base.ActiveToolSwitches[BUILDING_IN_IDE].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(BUILDING_IN_IDE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - ArgumentRelationList = new ArrayList(), - Name = BUILDING_IN_IDE, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(BUILDING_IN_IDE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for GccExceptHandling property - /// - public virtual string GccExceptionHandling - { - get - { - if (base.IsPropertySet("ExceptionHandling")) - { - return base.ActiveToolSwitches["ExceptionHandling"].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove("ExceptionHandling"); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Enable C++ Exceptions", - Description = "Specifies the model of exception handling to be used by the compiler.", - ArgumentRelationList = new ArrayList() - }; - string[][] switchMap = new string[][] { new string[] { "Async", "/EHa" }, new string[] { "Sync", "/EHsc" }, new string[] { "SyncCThrow", "/EHs" }, new string[] { "false", "" } }; - switch2.SwitchValue = base.ReadSwitchMap("ExceptionHandling", switchMap, value); - switch2.Name = "ExceptionHandling"; - switch2.Value = value; - switch2.MultiValues = true; - base.ActiveToolSwitches.Add("ExceptionHandling", switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for Optimization property - /// - public virtual string Optimization - { - get - { - if (base.IsPropertySet(OPTIMIZATION)) - { - return base.ActiveToolSwitches[OPTIMIZATION].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(OPTIMIZATION); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = OPTIMIZATION, - Description = "Select option for code optimization; choose Custom to use specific optimization options. (-O0, -O1, -O2, -O3)", - ArgumentRelationList = new ArrayList() - }; - string[][] switchMap = new string[][] { new string[] { "Disabled", "-O0" }, new string[] { "MinSpace", "-O1" }, - new string[] { "MaxSpeed", "-O2" }, new string[] { "Full", "-O3" } }; - switch2.SwitchValue = base.ReadSwitchMap(OPTIMIZATION, switchMap, value); - switch2.Name = OPTIMIZATION; - switch2.Value = value; - switch2.MultiValues = true; - base.ActiveToolSwitches.Add(OPTIMIZATION, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for PlatformToolset property - /// - public virtual string PlatformToolset - { - get - { - return "qcc"; - } - } - - /// - /// Getter/Setter for TrackerLogDirectory - /// - public virtual string TrackerLogDirectory - { - get - { - if ( base.IsPropertySet( TRACKER_LOG_DIRECTORY ) ) - { - return base.ActiveToolSwitches[TRACKER_LOG_DIRECTORY].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove( TRACKER_LOG_DIRECTORY ); - ToolSwitch switch2 = new ToolSwitch( ToolSwitchType.Directory ) - { - DisplayName = "Tracker Log Directory", - Description = "Tracker Log Directory.", - ArgumentRelationList = new ArrayList(), - Value = VCToolTask.EnsureTrailingSlash( value ) - }; - base.ActiveToolSwitches.Add( TRACKER_LOG_DIRECTORY, switch2 ); - base.AddActiveSwitchToolValue( switch2 ); - } - } - - /// - /// Getter/Setter for TargetMachine property - /// - public virtual string TargetMachine - { - get - { - if (base.IsPropertySet("TargetMachine")) - { - return base.ActiveToolSwitches["TargetMachine"].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove("TargetMachine"); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Target Machine", - Description = "The /MACHINE option specifies the target platform for the program.", - ArgumentRelationList = new ArrayList() - }; - string[][] switchMap = new string[][] { new string[] { "MachineARM", "/MACHINE:ARM" }, new string[] { "MachineEBC", "/MACHINE:EBC" }, new string[] { "MachineIA64", "/MACHINE:IA64" }, new string[] { "MachineMIPS", "/MACHINE:MIPS" }, new string[] { "MachineMIPS16", "/MACHINE:MIPS16" }, new string[] { "MachineMIPSFPU", "/MACHINE:MIPSFPU" }, new string[] { "MachineMIPSFPU16", "/MACHINE:MIPSFPU16" }, new string[] { "MachineSH4", "/MACHINE:SH4" }, new string[] { "MachineTHUMB", "/MACHINE:THUMB" }, new string[] { "MachineX64", "/MACHINE:X64" }, new string[] { "MachineX86", "/MACHINE:X86" } }; - switch2.SwitchValue = base.ReadSwitchMap("TargetMachine", switchMap, value); - switch2.Name = "TargetMachine"; - switch2.Value = value; - switch2.MultiValues = true; - base.ActiveToolSwitches.Add("TargetMachine", switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for CompileAs property - /// - public virtual string CompileAs - { - get - { - if (base.IsPropertySet(COMPILE_AS)) - { - return base.ActiveToolSwitches[COMPILE_AS].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(COMPILE_AS); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Compile As", - Description = "Select compile language option for .c and .cpp files. (-lang-c, -lang-c++)", - ArgumentRelationList = new ArrayList() - }; - string[][] switchMap = new string[][] { new string[] { "CompileAsC", "-lang-c" }, new string[] { "CompileAsCpp", "-lang-c++" } }; - switch2.SwitchValue = base.ReadSwitchMap(COMPILE_AS, switchMap, value); - switch2.Name = COMPILE_AS; - switch2.Value = value; - switch2.MultiValues = true; - base.ActiveToolSwitches.Add(COMPILE_AS, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for Verbose property - /// - public bool Verbose - { - get - { - return (base.IsPropertySet(VERBOSE) && base.ActiveToolSwitches[VERBOSE].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(VERBOSE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Verbose", - Description = "Verbose", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-v", - Name = VERBOSE, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(VERBOSE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for EnhancedSecutiry property - /// - public virtual bool EnhancedSecurity - { - get - { - return (base.IsPropertySet(ENHANCED_SECURITY) && base.ActiveToolSwitches[ENHANCED_SECURITY].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(ENHANCED_SECURITY); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Enhanced Security(-fstack-protector-all)", - Description = " ", - ArgumentRelationList = new ArrayList(), - SwitchValue = GetEnhancedSecuritySwitchValue(), - Name = ENHANCED_SECURITY, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(ENHANCED_SECURITY, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Return the Get Enhanced Security string. - /// - /// - protected virtual string GetEnhancedSecuritySwitchValue() - { - return "-fstack-protector-all"; - } - - /// - /// Getter/Setter for the PIE property - /// - public bool PIE - { - get - { - return (base.IsPropertySet(POSITION_INDEPENDENT_EXECUTABLE) && base.ActiveToolSwitches[POSITION_INDEPENDENT_EXECUTABLE].BooleanValue); - } - set - { - base.ActiveToolSwitches.Remove(POSITION_INDEPENDENT_EXECUTABLE); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) - { - DisplayName = "Position Independent Executable(fPIE)", - Description = " ", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-fPIE", - Name = POSITION_INDEPENDENT_EXECUTABLE, - BooleanValue = value - }; - base.ActiveToolSwitches.Add(POSITION_INDEPENDENT_EXECUTABLE, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the ProfilingCall property - /// - public bool ProfilingCall { get; set; } - - /// - /// Getter/Setter for the CodeCoverage property - /// - public bool CodeCoverage { get; set; } - - /// - /// Getter/Setter for the Mudflap property - /// - public bool Mudflap { get; set; } - - /// - /// Getter/Setter for the QccExe property - /// - public string QccExe { get; set; } - - /// - /// Getter/Setter for the CompilerVersionTarget property - /// - public string CompilerVersionTarget - { - get - { - if (base.IsPropertySet(COMPILER_VERSION_TARGET)) - { - return base.ActiveToolSwitches[COMPILER_VERSION_TARGET].Value; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(COMPILER_VERSION_TARGET); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) - { - DisplayName = "Compiler version and target", - Description = " ", - ArgumentRelationList = new ArrayList(), - SwitchValue = "-V", - }; - switch2.Name = COMPILER_VERSION_TARGET; - switch2.Value = value; - - base.ActiveToolSwitches.Add(COMPILER_VERSION_TARGET, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - - /// - /// Getter/Setter for the LinkSharedLibrary property - /// - public virtual bool LinkSharedLibrary { get; set; } - - /// - /// Getter/Setter for the Sources property - /// - [Required] - public virtual ITaskItem[] Sources - { - get - { - if (base.IsPropertySet(SOURCES)) - { - return base.ActiveToolSwitches[SOURCES].TaskItemArray; - } - return null; - } - set - { - base.ActiveToolSwitches.Remove(SOURCES); - ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.ITaskItemArray) - { - Separator = " ", - Required = true, - ArgumentRelationList = new ArrayList(), - TaskItemArray = value - }; - base.ActiveToolSwitches.Add(SOURCES, switch2); - base.AddActiveSwitchToolValue(switch2); - } - } - #endregion //properties - } -} diff --git a/src/VSNDK.Tasks/WriteDebuggerArgs.cs b/src/VSNDK.Tasks/WriteDebuggerArgs.cs deleted file mode 100644 index c712be98..00000000 --- a/src/VSNDK.Tasks/WriteDebuggerArgs.cs +++ /dev/null @@ -1,174 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Collections; -using System.Text.RegularExpressions; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace VSNDK.Tasks -{ - public class WriteDebuggerArgs : Task - { - #region Member Variables and Constants - - private string _projectDir; - private string _outDir; - private string _appName; - private string _device; - private bool _isSimulator; - private string _appData; - - #endregion - - #region Public Propeties - - /// - /// Getter/Setter for the ProjectDir property - /// - [Required] - public string ProjectDir - { - set { _projectDir = value.Replace('\\', '/'); } - get { return _projectDir; } - } - - /// - /// Getter/Setter for the _appData property - /// -// [Required] - public string AppData - { - set { _appData = value; } - get { return _appData; } - } - - /// - /// Getter/Setter for the OutDir property - /// - [Required] - public string OutDir - { - set { _outDir = value.Replace('\\', '/'); } - get { return _outDir; } - } - - /// - /// Getter/Setter for the AppName property - /// - [Required] - public string AppName - { - set { _appName = value; } - get { return _appName; } - } - - /// - /// Getter/Setter for the Device property - /// - [Required] - public string Device - { - set - { - _device = value; - } - } - - /// - /// Getter/Setter for the isSimulator property - /// - [Required] - public bool isSimulator - { - set - { - _isSimulator = value; - } - } - - /// - /// Getter/Setter for the ToolsPath property - /// - [Required] - public string ToolsPath - { - get; - set; - } - - /// - /// Getter/Setter for the PublicKeyPath property - /// - [Required] - public string PublicKeyPath - { - get; - set; - } - - /// - /// Getter/Setter for the Password property - /// - public string Password - { - get; - set; - } - - #endregion - - /// - /// Execute MSBuild function - /// - /// - public override bool Execute() - { - /// Initialize Variables - bool result; - - try - { - // Setting the work directory. - string rootedOutDir = (Path.IsPathRooted(OutDir)) ? OutDir + AppName : ProjectDir + OutDir + AppName; - - AppData = Environment.GetEnvironmentVariable("AppData") + @"\BlackBerry\vsndk-args-file.txt"; - - System.IO.StreamWriter file = new System.IO.StreamWriter(AppData); - - file.WriteLine(_device); - file.WriteLine(rootedOutDir.Replace(@"\\", @"\\\\")); - file.WriteLine(_isSimulator); - file.WriteLine(ToolsPath); - file.WriteLine(PublicKeyPath); - file.WriteLine(Password); - file.Close(); - - result = true; - } - catch (Exception ex) - { - result = false; - } - return result; - } - - - } -} diff --git a/src/VSNDK.sln b/src/VSNDK.sln deleted file mode 100644 index e417934d..00000000 --- a/src/VSNDK.sln +++ /dev/null @@ -1,126 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSNDK.Tasks", "VSNDK.Tasks\VSNDK.Tasks.csproj", "{328CAD98-F4E5-444A-B5DF-AD102C67BA3C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSNDK.AddIn", "VSNDK.AddIn\VSNDK.AddIn.csproj", "{D4644752-F6B1-47EE-A0FB-1197355A525E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSNDK.Package", "VSNDK.Package\VSNDK.Package.csproj", "{3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GDBParser", "GDBParser\GDBParser.vcxproj", "{CC7B28E0-CB31-44F7-A380-E7072F670F38}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GDBWrapper", "GDBWrapper\GDBWrapper.vcxproj", "{9A560339-44DB-413F-868C-403962C2CF01}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSNDK.DebugEngine", "VSNDK.DebugEngine\VSNDK.DebugEngine.csproj", "{59A7B188-E307-4495-A3AF-4ED76B086A87}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GDBParser_UnitTests", "GDBParser.UnitTests\GDBParser_UnitTests.csproj", "{6451DFCD-1CCD-4796-A832-A45FB95D994F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSNDK.Tasks.Test", "VSNDK.Tasks.Test\VSNDK.Tasks.Test.csproj", "{BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSNDK.Package.Test", "VSNDK.Package.Test\VSNDK.Package.Test.csproj", "{EA581F35-1EE6-4C7B-89FF-C3C7D886869D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Win32.ActiveCfg = Debug|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Any CPU.Build.0 = Release|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Win32.ActiveCfg = Release|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Debug|Win32.ActiveCfg = Debug|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Release|Any CPU.Build.0 = Release|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {D4644752-F6B1-47EE-A0FB-1197355A525E}.Release|Win32.ActiveCfg = Release|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Win32.ActiveCfg = Debug|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Any CPU.Build.0 = Release|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Win32.ActiveCfg = Release|Any CPU - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Debug|Win32.ActiveCfg = Debug|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Debug|Win32.Build.0 = Debug|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Release|Any CPU.ActiveCfg = Release|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Release|Mixed Platforms.Build.0 = Release|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Release|Win32.ActiveCfg = Release|Win32 - {CC7B28E0-CB31-44F7-A380-E7072F670F38}.Release|Win32.Build.0 = Release|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Win32.ActiveCfg = Debug|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Win32.Build.0 = Debug|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Release|Any CPU.ActiveCfg = Release|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Release|Mixed Platforms.Build.0 = Release|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Release|Win32.ActiveCfg = Release|Win32 - {9A560339-44DB-413F-868C-403962C2CF01}.Release|Win32.Build.0 = Release|Win32 - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Win32.ActiveCfg = Debug|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Any CPU.ActiveCfg = Release|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Any CPU.Build.0 = Release|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Win32.ActiveCfg = Release|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Debug|Win32.ActiveCfg = Debug|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Release|Any CPU.Build.0 = Release|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6451DFCD-1CCD-4796-A832-A45FB95D994F}.Release|Win32.ActiveCfg = Release|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Debug|Win32.ActiveCfg = Debug|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Release|Any CPU.Build.0 = Release|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {BDA81519-4AC1-4B1B-9EA0-18124E3C5E4E}.Release|Win32.ActiveCfg = Release|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Win32.ActiveCfg = Debug|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Any CPU.Build.0 = Release|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Win32.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src_vs2010/BlackBerry.NativePlugin.sln b/src_vs2010/BlackBerry.NativePlugin.sln new file mode 100644 index 00000000..e7f0d8bc --- /dev/null +++ b/src_vs2010/BlackBerry.NativePlugin.sln @@ -0,0 +1,90 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.BuildTasks", "BuildTasks\BlackBerry.BuildTasks.csproj", "{328CAD98-F4E5-444A-B5DF-AD102C67BA3C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.Package", "Package\BlackBerry.Package.csproj", "{3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.DebugEngine", "DebugEngine\BlackBerry.DebugEngine.csproj", "{59A7B188-E307-4495-A3AF-4ED76B086A87}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{EA581F35-1EE6-4C7B-89FF-C3C7D886869D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.NativeCore", "NativeCore\BlackBerry.NativeCore.csproj", "{36D4495B-9A92-478F-BF95-AEA13804A7BA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackBerry.GDBHost", "GDBHost\BlackBerry.GDBHost.vcxproj", "{9A560339-44DB-413F-868C-403962C2CF01}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Win32.ActiveCfg = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Any CPU.Build.0 = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Win32.ActiveCfg = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Any CPU.Build.0 = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Win32.ActiveCfg = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Win32.ActiveCfg = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Any CPU.Build.0 = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Win32.ActiveCfg = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Any CPU.Build.0 = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Win32.ActiveCfg = Release|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Debug|Win32.ActiveCfg = Debug|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Release|Any CPU.Build.0 = Release|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {36D4495B-9A92-478F-BF95-AEA13804A7BA}.Release|Win32.ActiveCfg = Release|Any CPU + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Win32.ActiveCfg = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Win32.Build.0 = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Any CPU.ActiveCfg = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Mixed Platforms.Build.0 = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Win32.ActiveCfg = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src_vs2010/BuildTasks/BlackBerry.BuildTasks.csproj b/src_vs2010/BuildTasks/BlackBerry.BuildTasks.csproj new file mode 100644 index 00000000..69a8cd87 --- /dev/null +++ b/src_vs2010/BuildTasks/BlackBerry.BuildTasks.csproj @@ -0,0 +1,290 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C} + Library + Properties + BlackBerry.BuildTasks + BlackBerry.BuildTasks + v4.0 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2010 + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2010 + prompt + 4 + + + + + False + C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.Build.CPPTasks.Common.dll + + + + + + + + + + + + + AsyncExec.cs + + + BarDescriptor\Parser.cs + + + BBDeploy.cs + + + BBNativePackager.cs + + + BBSigner.cs + + + BBTask.cs + + + CheckIfInstalled.cs + + + DiffManifests.cs + + + GenerateMakefile.cs + + + GetAppInfo.cs + + + Helpers\ProcessSetupHelper.cs + + + Helpers\TemplateHelper.cs + + + MakeAllAndFormatOutputMessages.cs + + + PackagerCmdBuilder.cs + + + Properties\Resources.Designer.cs + True + True + Resources.resx + + + QccCompiler.cs + + + QccExec.cs + + + QccLib.cs + + + QccLink.cs + + + QccTask.cs + + + RemoveFlagFile.cs + + + SSHDelete.cs + + + Templates\ConfigPriTemplate.cs + True + True + ConfigPriTemplate.tt + + + Templates\ConfigPriTemplate.Properties.cs + + + Templates\MakefileTemplate.cs + True + True + MakefileTemplate.tt + + + Templates\MakefileTemplate.Properties.cs + + + ConfigDefaults.cs + + + Helpers\GlobalHelper.cs + + + NativeMethods.cs + + + BarDescriptor\Schema\bar-descriptor.cs + + + BarDescriptor\Schema\bar-descriptor.Extensions.cs + + + + + + Templates\ConfigPriTemplate.tt + TextTemplatingFilePreprocessor + ConfigPriTemplate.cs + + + Templates\MakefileTemplate.tt + TextTemplatingFilePreprocessor + MakefileTemplate.cs + + + Designer + Always + + + Designer + Always + + + Designer + Always + + + Designer + Always + + + Designer + Always + + + Designer + Always + + + Always + + + + + BlackBerry\PlatformToolsets\qcc\1033\cl.xml + Always + + + BlackBerry\PlatformToolsets\qcc\1033\debugger_general.xml + Always + + + BlackBerry\PlatformToolsets\qcc\1033\directories.xml + Always + + + BlackBerry\PlatformToolsets\qcc\1033\general.xml + Always + + + BlackBerry\PlatformToolsets\qcc\1033\lib.xml + Always + + + BlackBerry\PlatformToolsets\qcc\1033\link.xml + Always + + + BlackBerry\PlatformToolsets\qcc\1033\packager.xml + Always + + + BlackBerry\PlatformToolsets\qcc\1033\ProjectItemsSchema.xml + Always + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + Properties\Resources.resx + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets new file mode 100644 index 00000000..bed3b761 --- /dev/null +++ b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + true + + + + true + + + + true + + + + + $(BuildLinkTargets); + + $(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets) + + + + + + + + + + + + + + + + + + $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) + $([System.IO.Path]::GetFileName('$(TargetPath)')) + $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) + $(LibPrefix)$(ProjectName) + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + true + $(IsAppInstalled) + false + + + + + + + + + + + + + + + + + + + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@CSKPass) + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props new file mode 100644 index 00000000..58536401 --- /dev/null +++ b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props @@ -0,0 +1,31 @@ + + + + + BlackBerry + qcc + Regular + all + armle-v7 + Unicode + + + + + $(IntermediateOutputPath) + $(Configuration)\ + $(Configuration)\ + $(IntDir) + + diff --git a/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.props b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.props new file mode 100644 index 00000000..7c96ed94 --- /dev/null +++ b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.props @@ -0,0 +1,179 @@ + + + + + + + $(IntermediateOutputPath) + Device-$(Configuration)\ + Device-$(Configuration)\ + $(IntDir) + + gcc_ntoarmv7le + Device + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@device_IP) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@device_password) + armle-v7 + arm + .le-v7 + + + + $(IntermediateOutputPath) + Simulator-$(Configuration)\ + Simulator-$(Configuration)\ + $(IntDir) + + gcc_ntox86 + Simulator + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@simulator_IP) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@simulator_password) + x86 + x86 + + + + + + + + + QCC;__QCC__;__QNX__;QNX_DEVICE=1;QNX_FAMILY=device + QCC;__QCC__;__QNX__;QNX_DEVICE=2;QNX_TABLET=1;QNX_FAMILY=tablet + false + + + QCC;__QCC__;__QNX__;QNX_SIMULATOR=1;QNX_FAMILY=device-simulator + QCC;__QCC__;__QNX__;QNX_SIMULATOR=2;QNX_TABLET=1;QNX_FAMILY=tablet-simulator + false + + + + + true + false + + + + + true + .a + lib + + + + true + + + + + + true + .so + true + lib + + + + + $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) + $(TargetPath.TrimEnd('\')) + $([System.IO.Path]::GetFileName('$(TargetPath)')) + $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) + $(LibPrefix)$(ProjectName) + + + + + + $(IntDir)%(FileName).o + $(QccDefines) + WIN32;_WINDOWS + NormalWarnings + false + false + + true + + false + false + Default + true + + + + + + + O2 + true + + + + + + + O2 + false + + + + + + + $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) + $(TargetPath) + + + false + false + true + false + true + Default + + + + + + + $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) + false + + + + + + + $(IntDir) + true + $(OutDir)$(TargetName).bar + true + false + false + bar-debug + bar + true + false + None + Install + false + 1 + bar-descriptor.xml + + + + + diff --git a/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets new file mode 100644 index 00000000..0893a7d2 --- /dev/null +++ b/src_vs2010/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + CompileAsC + CompileAsCpp + false + + + + + + + $(DefaultToolArchitecture) + + + + + + + + false + + + + + $(DefaultToolArchitecture) + + + + + + + + + + + false + false + true + $(DefaultToolArchitecture) + true + + + + + + CompileAsC + CompileAsCpp + + + + + + + + + + + + + $(CleanDependsOn); + MakeClean; + + + + + + + + + + + + + + + PlatformPrepareForBuild;$(PrepareForBuildDependsOn) + PlatformPrepareForBuild;$(PrepareForBuildDependsOn) + + + + + + + + + + + + + + diff --git a/src_vs2010/BuildTasks/BlackBerry/Microsoft.CppBuild.BlackBerry.targets b/src_vs2010/BuildTasks/BlackBerry/Microsoft.CppBuild.BlackBerry.targets new file mode 100644 index 00000000..5e412b2c --- /dev/null +++ b/src_vs2010/BuildTasks/BlackBerry/Microsoft.CppBuild.BlackBerry.targets @@ -0,0 +1,94 @@ + + + + + + + false + false + false + + + + + + + + + + + + + + + + + + PropertySheet + + + + + + + + + + + + + + + + Project + + + PropertySheet + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2010/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props b/src_vs2010/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props new file mode 100644 index 00000000..15c665e8 --- /dev/null +++ b/src_vs2010/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props @@ -0,0 +1,95 @@ + + + + + + + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@NDKTargetPath) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@NDKHostPath) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@NDKFamilyType) + $([System.IO.File]::ReadAllText("$(QNX_HOST)\etc\qcc\gcc\default").Substring(4,5)) + $(QNX_HOST)\etc\qcc\gcc + $(from_file) + gcc_ntoarmv7le + armle-v7 + Regular + Unicode + $(QNX_TARGET)\$(CPUVARDIR)\lib + $(LocalAppData) + + + $(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion@CurrentVersion) + $(HomeDrive)$(HomePath)\Local Settings\Application Data + + $(AppDataPath)\Research In Motion + $(SSHKeyDir)\bbt_id_rsa.pub + $(SSHKeyDir)\bbt_id_rsa + + + + BlackBerryDebugEngine + + + + qcc2.0 + $(QNX_HOST)\usr\bin + qcc.exe + qcc.exe + qcc.exe + $(registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@QNXToolsPath) + $(QNX_HOST)\usr\bin + $(MSBuildProgramFiles32)\MSBuild\BlackBerry\QnxTools\bin + $(QnxToolsPath)\blackberry-signer.bat + $(QnxToolsPath) + $(QnxToolsPath)\blackberry-nativepackager.bat + $(QnxToolsPath) + $(QnxToolsPath)\blackberry-deploy.bat + $(QnxToolsPath)\blackberry-connect.bat + ssh.exe + $(QccToolsPath) + $(QccToolsPath)\ssh-keygen.exe + + + + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC@ProductDir) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VC@ProductDir) + + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VS@ProductDir) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VCExpress\10.0\Setup\VS@ProductDir) + + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) + + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework@InstallRoot) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework@InstallRoot) + + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder) + + + + $(QNX_HOST)\usr\bin;$(PATH); + $(QNX_TARGET)\usr\include;$(QNX_TARGET)\usr\include\freetype2;$(QNX_TARGET)\usr\include\qt4\QtCore;$(QNX_TARGET)\usr\include\qt4\QtDeclarative;$(QNX_TARGET)\usr\include\qt4;$(QNX_TARGET)\..\target-override\usr\include;$(QNX_TARGET)\usr\include\cpp;$(QNX_TARGET)\usr\include\cpp\c;$(ProjectDir)\arm\o.le-v7-g\.moc;$(ProjectDir)\arm\o.le-v7\.moc;$(ProjectDir)\x86\o-g\.moc + $(QccLibPath);$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\lib;$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\usr\lib; + + $(ExecutablePath) + + + + diff --git a/src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.targets b/src_vs2010/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.targets similarity index 100% rename from src/VSNDK.Tasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.targets rename to src_vs2010/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.targets diff --git a/src_vs2010/BuildTasks/Properties/AssemblyInfo.cs b/src_vs2010/BuildTasks/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..5c553b9e --- /dev/null +++ b/src_vs2010/BuildTasks/Properties/AssemblyInfo.cs @@ -0,0 +1,51 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +using BlackBerry.NativeCore; + +[assembly: AssemblyTitle("BlackBerry Native SDK Build Tasks")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("BlackBerry")] +[assembly: AssemblyProduct("BlackBerry.BuildTasks")] +[assembly: AssemblyCopyright("Copyright © BlackBerry 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d4362271-7b17-4734-86bb-39564f3e29fc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion(ConfigDefaults.VersionString)] +[assembly: AssemblyFileVersion(ConfigDefaults.VersionString)] diff --git a/src_vs2010/DebugEngine/AD7.Definitions/AD7Enums.cs b/src_vs2010/DebugEngine/AD7.Definitions/AD7Enums.cs new file mode 100644 index 00000000..f6cf0c11 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Definitions/AD7Enums.cs @@ -0,0 +1,100 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + + +namespace BlackBerry.DebugEngine +{ + /// + /// Flags passed by the debugger to the engine to describe the desired format and execution options for properties + /// (locals, arguments, etc...) + /// + public enum DEBUGPROP_INFO_FLAGS + { + DEBUGPROP_INFO_FULLNAME = 0x00000001, + DEBUGPROP_INFO_NAME = 0x00000002, + DEBUGPROP_INFO_TYPE = 0x00000004, + DEBUGPROP_INFO_VALUE = 0x00000008, + DEBUGPROP_INFO_ATTRIB = 0x00000010, + DEBUGPROP_INFO_PROP = 0x00000020, + + DEBUGPROP_INFO_VALUE_AUTOEXPAND = 0x00010000, + DEBUGPROP_INFO_NOFUNCEVAL = 0x00020000, // Tell EE not to perform ANY type of func-eval. + DEBUGPROP_INFO_VALUE_RAW = 0x00040000, // Tell EE not to return any beautified values or members. + DEBUGPROP_INFO_VALUE_NO_TOSTRING = 0x00080000, // Tell EE not to return any special synthesized values (ToString() for instance). + DEBUGPROP_INFO_NO_NONPUBLIC_MEMBERS = 0x00100000, // Tell EE to return non-public members for non-user objects. + + DEBUGPROP_INFO_NONE = 0x00000000, + DEBUGPROP_INFO_STANDARD = DEBUGPROP_INFO_ATTRIB | DEBUGPROP_INFO_NAME | DEBUGPROP_INFO_TYPE | DEBUGPROP_INFO_VALUE, + } + + public static class DBG_ATTRIB_FLAGS + { + public static readonly ulong DBG_ATTRIB_NONE = 0x0000000000000000; + public static readonly ulong DBG_ATTRIB_ALL = 0x00000000ffffffff; + + // Attributes about the object itself + public static readonly ulong DBG_ATTRIB_OBJ_IS_EXPANDABLE = 0x0000000000000001; + public static readonly ulong DBG_ATTRIB_OBJ_HAS_ID = 0x0000000000000002; + public static readonly ulong DBG_ATTRIB_OBJ_CAN_HAVE_ID = 0x0000000000000004; + + // Attributes about the value of the object + public static readonly ulong DBG_ATTRIB_VALUE_READONLY = 0x0000000000000010; + public static readonly ulong DBG_ATTRIB_VALUE_ERROR = 0x0000000000000020; + public static readonly ulong DBG_ATTRIB_VALUE_SIDE_EFFECT= 0x0000000000000040; + public static readonly ulong DBG_ATTRIB_OVERLOADED_CONTAINER = 0x0000000000000080; + public static readonly ulong DBG_ATTRIB_VALUE_BOOLEAN = 0x0000000000000100; + public static readonly ulong DBG_ATTRIB_VALUE_BOOLEAN_TRUE = 0x0000000000000200; + public static readonly ulong DBG_ATTRIB_VALUE_INVALID = 0x0000000000000400; + public static readonly ulong DBG_ATTRIB_VALUE_NAT = 0x0000000000000800; + public static readonly ulong DBG_ATTRIB_VALUE_AUTOEXPANDED = 0x0000000000001000; + public static readonly ulong DBG_ATTRIB_VALUE_TIMEOUT = 0x0000000000002000; + public static readonly ulong DBG_ATTRIB_VALUE_RAW_STRING = 0x0000000000004000; + public static readonly ulong DBG_ATTRIB_VALUE_CUSTOM_VIEWER = 0x0000000000008000; + + // Attributes about field access types for the object + public static readonly ulong DBG_ATTRIB_ACCESS_NONE = 0x0000000000010000; + public static readonly ulong DBG_ATTRIB_ACCESS_PUBLIC = 0x0000000000020000; + public static readonly ulong DBG_ATTRIB_ACCESS_PRIVATE = 0x0000000000040000; + public static readonly ulong DBG_ATTRIB_ACCESS_PROTECTED = 0x0000000000080000; + public static readonly ulong DBG_ATTRIB_ACCESS_FINAL = 0x0000000000100000; + public static readonly ulong DBG_ATTRIB_ACCESS_ALL = 0x00000000001f0000; + + // Attributes for the storage types of the object + public static readonly ulong DBG_ATTRIB_STORAGE_NONE = 0x0000000001000000; + public static readonly ulong DBG_ATTRIB_STORAGE_GLOBAL = 0x0000000002000000; + public static readonly ulong DBG_ATTRIB_STORAGE_STATIC = 0x0000000004000000; + public static readonly ulong DBG_ATTRIB_STORAGE_REGISTER = 0x0000000008000000; + public static readonly ulong DBG_ATTRIB_STORAGE_ALL= 0x000000000f000000; + + // Attributes for the type modifiers on the object + public static readonly ulong DBG_ATTRIB_TYPE_NONE = 0x0000000100000000; + public static readonly ulong DBG_ATTRIB_TYPE_VIRTUAL = 0x0000000200000000; + public static readonly ulong DBG_ATTRIB_TYPE_CONSTANT = 0x0000000400000000; + public static readonly ulong DBG_ATTRIB_TYPE_SYNCHRONIZED = 0x0000000800000000; + public static readonly ulong DBG_ATTRIB_TYPE_VOLATILE = 0x0000001000000000; + public static readonly ulong DBG_ATTRIB_TYPE_ALL = 0x0000001f00000000; + + // Attributes that describe the type of object + public static readonly ulong DBG_ATTRIB_DATA = 0x0000010000000000; + public static readonly ulong DBG_ATTRIB_METHOD = 0x0000020000000000; + public static readonly ulong DBG_ATTRIB_PROPERTY = 0x0000040000000000; + public static readonly ulong DBG_ATTRIB_CLASS = 0x0000080000000000; + public static readonly ulong DBG_ATTRIB_BASECLASS = 0x0000100000000000; + public static readonly ulong DBG_ATTRIB_INTERFACE = 0x0000200000000000; + public static readonly ulong DBG_ATTRIB_INNERCLASS = 0x0000400000000000; + public static readonly ulong DBG_ATTRIB_MOSTDERIVED = 0x0000800000000000; + public static readonly ulong DBG_ATTRIB_CHILD_ALL = 0x0000ff0000000000; + + } +} diff --git a/src_vs2010/DebugEngine/AD7.Definitions/AD7Guids.cs b/src_vs2010/DebugEngine/AD7.Definitions/AD7Guids.cs new file mode 100644 index 00000000..5574dd38 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Definitions/AD7Guids.cs @@ -0,0 +1,68 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; + +namespace BlackBerry.DebugEngine +{ + /// + /// These are well-known guids in AD7. Most of these are used to specify filters in what the debugger UI is requesting. + /// For instance, guidFilterLocals can be passed to IDebugStackFrame2::EnumProperties to specify only locals are requested. + /// + static class AD7Guids + { + static private Guid _guidFilterRegisters = new Guid("223ae797-bd09-4f28-8241-2763bdc5f713"); + static public Guid guidFilterRegisters + { + get { return _guidFilterRegisters; } + } + + static private Guid _guidFilterLocals = new Guid("b200f725-e725-4c53-b36a-1ec27aef12ef"); + static public Guid guidFilterLocals + { + get { return _guidFilterLocals; } + } + + static private Guid _guidFilterAllLocals = new Guid("196db21f-5f22-45a9-b5a3-32cddb30db06"); + static public Guid guidFilterAllLocals + { + get { return _guidFilterAllLocals; } + } + + static private Guid _guidFilterArgs = new Guid("804bccea-0475-4ae7-8a46-1862688ab863"); + static public Guid guidFilterArgs + { + get { return _guidFilterArgs; } + } + + static private Guid _guidFilterLocalsPlusArgs = new Guid("e74721bb-10c0-40f5-807f-920d37f95419"); + static public Guid guidFilterLocalsPlusArgs + { + get { return _guidFilterLocalsPlusArgs; } + } + + static private Guid _guidFilterAllLocalsPlusArgs = new Guid("939729a8-4cb0-4647-9831-7ff465240d5f"); + static public Guid guidFilterAllLocalsPlusArgs + { + get { return _guidFilterAllLocalsPlusArgs; } + } + + // Language guid for C++. Used when the language for a document context or a stack frame is requested. + static private Guid _guidLanguageCpp = new Guid("3a12d0b7-c26c-11d0-b442-00a0244a1dd2"); + static public Guid guidLanguageCpp + { + get { return _guidLanguageCpp; } + } + } +} diff --git a/src_vs2010/DebugEngine/AD7.Definitions/AD7Hresult.cs b/src_vs2010/DebugEngine/AD7.Definitions/AD7Hresult.cs new file mode 100644 index 00000000..1efbb9ad --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Definitions/AD7Hresult.cs @@ -0,0 +1,254 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +namespace BlackBerry.DebugEngine +{ + /// + /// These are managed definitions of the well-known AD7 HRESULTS. Defined in msdbg.idl. + /// + static public class AD7_HRESULT + { + public const int S_ATTACH_DEFERRED=unchecked((int)0x40004); + public const int S_ATTACH_IGNORED=unchecked((int)0x40005); + public const int S_JIT_USERCANCELLED=unchecked((int)0x400B0); + public const int S_JIT_NOT_REG_FOR_ENGINE=unchecked((int)0x400B5); + public const int S_TERMINATE_PROCESSES_STILL_DETACHING=unchecked((int)0x400C0); + public const int S_TERMINATE_PROCESSES_STILL_TERMINATING=unchecked((int)0x400C1); + public const int S_ENC_SETIP_REQUIRES_CONTINUE=unchecked((int)0x40106); + public const int S_WEBDBG_UNABLE_TO_DIAGNOSE=unchecked((int)0x40120); + public const int S_WEBDBG_DEBUG_VERB_BLOCKED=unchecked((int)0x40121); + public const int S_ASP_USER_ACCESS_DENIED=unchecked((int)0x40125); + public const int S_JMC_LIMITED_SUPPORT=unchecked((int)0x40146); + public const int S_CANNOT_REMAP_IN_EXCEPTION=unchecked((int)0x40150); + public const int S_CANNOT_REMAP_NOT_AT_SEQUENCE_POINT=unchecked((int)0x40151); + public const int S_GETPARENT_NO_PARENT=unchecked((int)0x40531); + public const int S_GETDERIVEDMOST_NO_DERIVED_MOST=unchecked((int)0x40541); + public const int S_GETMEMORYBYTES_NO_MEMORY_BYTES=unchecked((int)0x40551); + public const int S_GETMEMORYCONTEXT_NO_MEMORY_CONTEXT=unchecked((int)0x40561); + public const int S_GETSIZE_NO_SIZE=unchecked((int)0x40571); + public const int S_GETEXTENDEDINFO_NO_EXTENDEDINFO=unchecked((int)0x40591); + public const int S_ASYNC_STOP=unchecked((int)0x40B02); + public const int E_ATTACH_DEBUGGER_ALREADY_ATTACHED=unchecked((int)0x80040001); + public const int E_ATTACH_DEBUGGEE_PROCESS_SECURITY_VIOLATION=unchecked((int)0x80040002); + public const int E_ATTACH_CANNOT_ATTACH_TO_DESKTOP=unchecked((int)0x80040003); + public const int E_LAUNCH_NO_INTEROP=unchecked((int)0x80040005); + public const int E_LAUNCH_DEBUGGING_NOT_POSSIBLE=unchecked((int)0x80040006); + public const int E_LAUNCH_KERNEL_DEBUGGER_ENABLED=unchecked((int)0x80040007); + public const int E_LAUNCH_KERNEL_DEBUGGER_PRESENT=unchecked((int)0x80040008); + public const int E_INTEROP_NOT_SUPPORTED=unchecked((int)0x80040009); + public const int E_TOO_MANY_PROCESSES=unchecked((int)0x8004000A); + public const int E_MSHTML_SCRIPT_DEBUGGING_DISABLED=unchecked((int)0x8004000B); + public const int E_SCRIPT_PDM_NOT_REGISTERED=unchecked((int)0x8004000C); + public const int E_DE_CLR_DBG_SERVICES_NOT_INSTALLED=unchecked((int)0x8004000D); + public const int E_ATTACH_NO_CLR_PROGRAMS=unchecked((int)0x8004000E); + public const int E_REMOTE_SERVER_CLOSED=unchecked((int)0x80040010); + public const int E_CLR_NOT_SUPPORTED=unchecked((int)0x80040016); + public const int E_64BIT_CLR_NOT_SUPPORTED=unchecked((int)0x80040017); + public const int E_CANNOT_MIX_MINDUMP_DEBUGGING=unchecked((int)0x80040018); + public const int E_DEBUG_ENGINE_NOT_REGISTERED=unchecked((int)0x80040019); + public const int E_LAUNCH_SXS_ERROR=unchecked((int)0x8004001A); + public const int E_REMOTE_SERVER_DOES_NOT_EXIST=unchecked((int)0x80040020); + public const int E_REMOTE_SERVER_ACCESS_DENIED=unchecked((int)0x80040021); + public const int E_REMOTE_SERVER_MACHINE_DOES_NOT_EXIST=unchecked((int)0x80040022); + public const int E_DEBUGGER_NOT_REGISTERED_PROPERLY=unchecked((int)0x80040023); + public const int E_FORCE_GUEST_MODE_ENABLED=unchecked((int)0x80040024); + public const int E_GET_IWAM_USER_FAILURE=unchecked((int)0x80040025); + public const int E_REMOTE_SERVER_INVALID_NAME=unchecked((int)0x80040026); + public const int E_REMOTE_SERVER_MACHINE_NO_DEFAULT=unchecked((int)0x80040027); + public const int E_AUTO_LAUNCH_EXEC_FAILURE=unchecked((int)0x80040028); + public const int E_SERVICE_ACCESS_DENIED=unchecked((int)0x80040029); + public const int E_SERVICE_ACCESS_DENIED_ON_CALLBACK=unchecked((int)0x8004002A); + public const int E_REMOTE_COMPONENTS_NOT_REGISTERED=unchecked((int)0x8004002B); + public const int E_DCOM_ACCESS_DENIED=unchecked((int)0x8004002C); + public const int E_SHARE_LEVEL_ACCESS_CONTROL_ENABLED=unchecked((int)0x8004002D); + public const int E_WORKGROUP_REMOTE_LOGON_FAILURE=unchecked((int)0x8004002E); + public const int E_WINAUTH_CONNECT_NOT_SUPPORTED=unchecked((int)0x8004002F); + public const int E_EVALUATE_BUSY_WITH_EVALUATION=unchecked((int)0x80040030); + public const int E_EVALUATE_TIMEOUT=unchecked((int)0x80040031); + public const int E_INTEROP_NOT_SUPPORTED_FOR_THIS_CLR=unchecked((int)0x80040032); + public const int E_CLR_INCOMPATIBLE_PROTOCOL=unchecked((int)0x80040033); + public const int E_CLR_CANNOT_DEBUG_FIBER_PROCESS=unchecked((int)0x80040034); + public const int E_PROCESS_OBJECT_ACCESS_DENIED=unchecked((int)0x80040035); + public const int E_PROCESS_TOKEN_ACCESS_DENIED=unchecked((int)0x80040036); + public const int E_PROCESS_TOKEN_ACCESS_DENIED_NO_TS=unchecked((int)0x80040037); + public const int E_OPERATION_REQUIRES_ELEVATION=unchecked((int)0x80040038); + public const int E_ATTACH_REQUIRES_ELEVATION=unchecked((int)0x80040039); + public const int E_MEMORY_NOTSUPPORTED=unchecked((int)0x80040040); + public const int E_DISASM_NOTSUPPORTED=unchecked((int)0x80040041); + public const int E_DISASM_BADADDRESS=unchecked((int)0x80040042); + public const int E_DISASM_NOTAVAILABLE=unchecked((int)0x80040043); + public const int E_BP_DELETED=unchecked((int)0x80040060); + public const int E_PROCESS_DESTROYED=unchecked((int)0x80040070); + public const int E_PROCESS_DEBUGGER_IS_DEBUGGEE=unchecked((int)0x80040071); + public const int E_TERMINATE_FORBIDDEN=unchecked((int)0x80040072); + public const int E_THREAD_DESTROYED=unchecked((int)0x80040075); + public const int E_PORTSUPPLIER_NO_PORT=unchecked((int)0x80040080); + public const int E_PORT_NO_REQUEST=unchecked((int)0x80040090); + public const int E_COMPARE_CANNOT_COMPARE=unchecked((int)0x800400A0); + public const int E_JIT_INVALID_PID=unchecked((int)0x800400B1); + public const int E_JIT_VSJITDEBUGGER_NOT_REGISTERED=unchecked((int)0x800400B3); + public const int E_JIT_APPID_NOT_REGISTERED=unchecked((int)0x800400B4); + public const int E_SESSION_TERMINATE_DETACH_FAILED=unchecked((int)0x800400C2); + public const int E_SESSION_TERMINATE_FAILED=unchecked((int)0x800400C3); + public const int E_DETACH_NO_PROXY=unchecked((int)0x800400D0); + public const int E_DETACH_TS_UNSUPPORTED=unchecked((int)0x800400E0); + public const int E_DETACH_IMPERSONATE_FAILURE=unchecked((int)0x800400F0); + public const int E_CANNOT_SET_NEXT_STATEMENT_ON_NONLEAF_FRAME=unchecked((int)0x80040100); + public const int E_TARGET_FILE_MISMATCH=unchecked((int)0x80040101); + public const int E_IMAGE_NOT_LOADED=unchecked((int)0x80040102); + public const int E_FIBER_NOT_SUPPORTED=unchecked((int)0x80040103); + public const int E_CANNOT_SETIP_TO_DIFFERENT_FUNCTION=unchecked((int)0x80040104); + public const int E_CANNOT_SET_NEXT_STATEMENT_ON_EXCEPTION=unchecked((int)0x80040105); + public const int E_ENC_SETIP_REQUIRES_CONTINUE=unchecked((int)0x80040107); + public const int E_CANNOT_SET_NEXT_STATEMENT_INTO_FINALLY=unchecked((int)0x80040108); + public const int E_CANNOT_SET_NEXT_STATEMENT_OUT_OF_FINALLY=unchecked((int)0x80040109); + public const int E_CANNOT_SET_NEXT_STATEMENT_INTO_CATCH=unchecked((int)0x8004010A); + public const int E_CANNOT_SET_NEXT_STATEMENT_GENERAL=unchecked((int)0x8004010B); + public const int E_CANNOT_SET_NEXT_STATEMENT_INTO_OR_OUT_OF_FILTER=unchecked((int)0x8004010C); + public const int E_ASYNCBREAK_NO_PROGRAMS=unchecked((int)0x80040110); + public const int E_ASYNCBREAK_DEBUGGEE_NOT_INITIALIZED=unchecked((int)0x80040111); + public const int E_WEBDBG_DEBUG_VERB_BLOCKED=unchecked((int)0x80040121); + public const int E_ASP_USER_ACCESS_DENIED=unchecked((int)0x80040125); + public const int E_AUTO_ATTACH_NOT_REGISTERED=unchecked((int)0x80040126); + public const int E_AUTO_ATTACH_DCOM_ERROR=unchecked((int)0x80040127); + public const int E_AUTO_ATTACH_NOT_SUPPORTED=unchecked((int)0x80040128); + public const int E_AUTO_ATTACH_CLASSNOTREG=unchecked((int)0x80040129); + public const int E_CANNOT_CONTINUE_DURING_PENDING_EXPR_EVAL=unchecked((int)0x80040130); + public const int E_REMOTE_REDIRECTION_UNSUPPORTED=unchecked((int)0x80040135); + public const int E_INVALID_WORKING_DIRECTORY=unchecked((int)0x80040136); + public const int E_LAUNCH_FAILED_WITH_ELEVATION=unchecked((int)0x80040137); + public const int E_LAUNCH_ELEVATION_REQUIRED=unchecked((int)0x80040138); + public const int E_CANNOT_FIND_INTERNET_EXPLORER=unchecked((int)0x80040139); + public const int E_EXCEPTION_CANNOT_BE_INTERCEPTED=unchecked((int)0x80040140); + public const int E_EXCEPTION_CANNOT_UNWIND_ABOVE_CALLBACK=unchecked((int)0x80040141); + public const int E_INTERCEPT_CURRENT_EXCEPTION_NOT_SUPPORTED=unchecked((int)0x80040142); + public const int E_INTERCEPT_CANNOT_UNWIND_LASTCHANCE_INTEROP=unchecked((int)0x80040143); + public const int E_JMC_CANNOT_SET_STATUS=unchecked((int)0x80040145); + public const int E_DESTROYED=unchecked((int)0x80040201); + public const int E_REMOTE_NOMSVCMON=unchecked((int)0x80040202); + public const int E_REMOTE_BADIPADDRESS=unchecked((int)0x80040203); + public const int E_REMOTE_MACHINEDOWN=unchecked((int)0x80040204); + public const int E_REMOTE_MACHINEUNSPECIFIED=unchecked((int)0x80040205); + public const int E_CRASHDUMP_ACTIVE=unchecked((int)0x80040206); + public const int E_ALL_THREADS_SUSPENDED=unchecked((int)0x80040207); + public const int E_LOAD_DLL_TL=unchecked((int)0x80040208); + public const int E_LOAD_DLL_SH=unchecked((int)0x80040209); + public const int E_LOAD_DLL_EM=unchecked((int)0x8004020A); + public const int E_LOAD_DLL_EE=unchecked((int)0x8004020B); + public const int E_LOAD_DLL_DM=unchecked((int)0x8004020C); + public const int E_LOAD_DLL_MD=unchecked((int)0x8004020D); + public const int E_IOREDIR_BADFILE=unchecked((int)0x8004020E); + public const int E_IOREDIR_BADSYNTAX=unchecked((int)0x8004020F); + public const int E_REMOTE_BADVERSION=unchecked((int)0x80040210); + public const int E_CRASHDUMP_UNSUPPORTED=unchecked((int)0x80040211); + public const int E_REMOTE_BAD_CLR_VERSION=unchecked((int)0x80040212); + public const int E_UNSUPPORTED_BINARY=unchecked((int)0x80040215); + public const int E_DEBUGGEE_BLOCKED=unchecked((int)0x80040216); + public const int E_REMOTE_NOUSERMSVCMON=unchecked((int)0x80040217); + public const int E_STEP_WIN9xSYSCODE=unchecked((int)0x80040218); + public const int E_INTEROP_ORPC_INIT=unchecked((int)0x80040219); + public const int E_CANNOT_DEBUG_WIN32=unchecked((int)0x8004021B); + public const int E_CANNOT_DEBUG_WIN64=unchecked((int)0x8004021C); + public const int E_MINIDUMP_READ_WIN9X=unchecked((int)0x8004021D); + public const int E_CROSS_TSSESSION_ATTACH=unchecked((int)0x8004021E); + public const int E_STEP_BP_SET_FAILED=unchecked((int)0x8004021F); + public const int E_LOAD_DLL_TL_INCORRECT_VERSION=unchecked((int)0x80040220); + public const int E_LOAD_DLL_DM_INCORRECT_VERSION=unchecked((int)0x80040221); + public const int E_REMOTE_NOMSVCMON_PIPE=unchecked((int)0x80040222); + public const int E_LOAD_DLL_DIA=unchecked((int)0x80040223); + public const int E_DUMP_CORRUPTED=unchecked((int)0x80040224); + public const int E_INTEROP_WIN64=unchecked((int)0x80040225); + public const int E_CRASHDUMP_DEPRECATED=unchecked((int)0x80040227); + public const int E_DEVICEBITS_NOT_SIGNED=unchecked((int)0x80040401); + public const int E_ATTACH_NOT_ENABLED=unchecked((int)0x80040402); + public const int E_REMOTE_DISCONNECT=unchecked((int)0x80040403); + public const int E_BREAK_ALL_FAILED=unchecked((int)0x80040404); + public const int E_DEVICE_ACCESS_DENIED_SELECT_YES=unchecked((int)0x80040405); + public const int E_DEVICE_ACCESS_DENIED=unchecked((int)0x80040406); + public const int E_DEVICE_CONNRESET=unchecked((int)0x80040407); + public const int E_BAD_NETCF_VERSION=unchecked((int)0x80040408); + public const int E_REFERENCE_NOT_VALID=unchecked((int)0x80040501); + public const int E_PROPERTY_NOT_VALID=unchecked((int)0x80040511); + public const int E_SETVALUE_VALUE_CANNOT_BE_SET=unchecked((int)0x80040521); + public const int E_SETVALUE_VALUE_IS_READONLY=unchecked((int)0x80040522); + public const int E_SETVALUEASREFERENCE_NOTSUPPORTED=unchecked((int)0x80040523); + public const int E_CANNOT_GET_UNMANAGED_MEMORY_CONTEXT=unchecked((int)0x80040561); + public const int E_GETREFERENCE_NO_REFERENCE=unchecked((int)0x80040581); + public const int E_CODE_CONTEXT_OUT_OF_SCOPE=unchecked((int)0x800405A1); + public const int E_INVALID_SESSIONID=unchecked((int)0x800405A2); + public const int E_SERVER_UNAVAILABLE_ON_CALLBACK=unchecked((int)0x800405A3); + public const int E_ACCESS_DENIED_ON_CALLBACK=unchecked((int)0x800405A4); + public const int E_UNKNOWN_AUTHN_SERVICE_ON_CALLBACK=unchecked((int)0x800405A5); + public const int E_NO_SESSION_AVAILABLE=unchecked((int)0x800405A6); + public const int E_CLIENT_NOT_LOGGED_ON=unchecked((int)0x800405A7); + public const int E_OTHER_USERS_SESSION=unchecked((int)0x800405A8); + public const int E_USER_LEVEL_ACCESS_CONTROL_REQUIRED=unchecked((int)0x800405A9); + public const int E_SCRIPT_CLR_EE_DISABLED=unchecked((int)0x800405B0); + public const int E_HTTP_SERVERERROR=unchecked((int)0x80040700); + public const int E_HTTP_UNAUTHORIZED=unchecked((int)0x80040701); + public const int E_HTTP_SENDREQUEST_FAILED=unchecked((int)0x80040702); + public const int E_HTTP_FORBIDDEN=unchecked((int)0x80040703); + public const int E_HTTP_NOT_SUPPORTED=unchecked((int)0x80040704); + public const int E_HTTP_NO_CONTENT=unchecked((int)0x80040705); + public const int E_HTTP_NOT_FOUND=unchecked((int)0x80040706); + public const int E_HTTP_BAD_REQUEST=unchecked((int)0x80040707); + public const int E_HTTP_ACCESS_DENIED=unchecked((int)0x80040708); + public const int E_HTTP_CONNECT_FAILED=unchecked((int)0x80040709); + public const int E_HTTP_EXCEPTION=unchecked((int)0x8004070A); + public const int E_HTTP_TIMEOUT=unchecked((int)0x8004070B); + public const int E_64BIT_COMPONENTS_NOT_INSTALLED=unchecked((int)0x80040750); + public const int E_UNMARSHAL_SERVER_FAILED=unchecked((int)0x80040751); + public const int E_UNMARSHAL_CALLBACK_FAILED=unchecked((int)0x80040752); + public const int E_RPC_REQUIRES_AUTHENTICATION=unchecked((int)0x80040755); + public const int E_LOGON_FAILURE_ON_CALLBACK=unchecked((int)0x80040756); + public const int E_REMOTE_SERVER_UNAVAILABLE=unchecked((int)0x80040757); + public const int E_FIREWALL_USER_CANCELED=unchecked((int)0x80040758); + public const int E_REMOTE_CREDENTIALS_PROHIBITED=unchecked((int)0x80040759); + public const int E_FIREWALL_NO_EXCEPTIONS=unchecked((int)0x8004075A); + public const int E_FIREWALL_CANNOT_OPEN_APPLICATION=unchecked((int)0x8004075B); + public const int E_FIREWALL_CANNOT_OPEN_PORT=unchecked((int)0x8004075C); + public const int E_FIREWALL_CANNOT_OPEN_FILE_SHARING=unchecked((int)0x8004075D); + public const int E_REMOTE_DEBUGGING_UNSUPPORTED=unchecked((int)0x8004075E); + public const int E_REMOTE_BAD_MSDBG2=unchecked((int)0x8004075F); + public const int E_ATTACH_USER_CANCELED=unchecked((int)0x80040760); + public const int E_FUNCTION_NOT_JITTED=unchecked((int)0x80040800); + public const int E_NO_CODE_CONTEXT=unchecked((int)0x80040801); + public const int E_BAD_CLR_DIASYMREADER=unchecked((int)0x80040802); + public const int E_CLR_SHIM_ERROR=unchecked((int)0x80040803); + public const int E_AUTOATTACH_ACCESS_DENIED=unchecked((int)0x80040900); + public const int E_AUTOATTACH_WEBSERVER_NOT_FOUND=unchecked((int)0x80040901); + public const int E_DBGEXTENSION_NOT_FOUND=unchecked((int)0x80040910); + public const int E_DBGEXTENSION_FUNCTION_NOT_FOUND=unchecked((int)0x80040911); + public const int E_DBGEXTENSION_FAULTED=unchecked((int)0x80040912); + public const int E_DBGEXTENSION_RESULT_INVALID=unchecked((int)0x80040913); + public const int E_PROGRAM_IN_RUNMODE=unchecked((int)0x80040914); + public const int E_CAUSALITY_NO_SERVER_RESPONSE=unchecked((int)0x80040920); + public const int E_CAUSALITY_REMOTE_NOT_REGISTERED=unchecked((int)0x80040921); + public const int E_CAUSALITY_BREAKPOINT_NOT_HIT=unchecked((int)0x80040922); + public const int E_CAUSALITY_BREAKPOINT_BIND_ERROR=unchecked((int)0x80040923); + public const int E_CAUSALITY_PROJECT_DISABLED=unchecked((int)0x80040924); + public const int E_NO_ATTACH_WHILE_DDD=unchecked((int)0x80040A00); + public const int E_SQLLE_ACCESSDENIED=unchecked((int)0x80040A01); + public const int E_SQL_SP_ENABLE_PERMISSION_DENIED=unchecked((int)0x80040A02); + public const int E_SQL_DEBUGGING_NOT_ENABLED_ON_SERVER=unchecked((int)0x80040A03); + public const int E_SQL_CANT_FIND_SSDEBUGPS_ON_CLIENT=unchecked((int)0x80040A04); + public const int E_SQL_EXECUTED_BUT_NOT_DEBUGGED=unchecked((int)0x80040A05); + public const int E_SQL_VDT_INIT_RETURNED_SQL_ERROR=unchecked((int)0x80040A06); + public const int E_ATTACH_FAILED_ABORT_SILENTLY=unchecked((int)0x80040A07); + public const int E_SQL_REGISTER_FAILED=unchecked((int)0x80040A08); + public const int E_DE_NOT_SUPPORTED_PRE_8_0=unchecked((int)0x80040B00); + public const int E_PROGRAM_DESTROY_PENDING=unchecked((int)0x80040B01); + public const int E_MANAGED_FEATURE_NOTSUPPORTED=unchecked((int)0x80040BAD); + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7BoundBreakpoint.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7BoundBreakpoint.cs new file mode 100644 index 00000000..9353f373 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7BoundBreakpoint.cs @@ -0,0 +1,500 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.NativeCore.Debugger.Model; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System.Runtime.InteropServices; +using System.Threading; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents a breakpoint that has been bound to a location in the debuggee. It is a child of the pending + /// breakpoint that creates it. Unless the pending breakpoint only has one bound breakpoint, each bound breakpoint is displayed as + /// a child of the pending breakpoint in the breakpoints window. Otherwise, only one is displayed. + /// (http://msdn.microsoft.com/en-us/library/bb161979.aspx) + /// + public sealed class AD7BoundBreakpoint : IDebugBoundBreakpoint2 + { + private readonly AD7PendingBreakpoint _pendingBreakpoint; + private readonly AD7BreakpointResolution _breakpointResolution; + private readonly AD7Engine _engine; + + private bool _enabled; + private bool _deleted; + public uint _hitCount; + + public uint m_bpLocationType; + public string m_filename = ""; + public uint m_line; + public string m_func = ""; + + public BP_PASSCOUNT m_bpPassCount; + public BP_CONDITION m_bpCondition; + + /// + /// TRUE if the program has to stop when the hit count is equal to a given value. + /// + public bool _isHitCountEqual; + + /// + /// Different than 0 if the program has to stop whenever the hit count is multiple of a given value + /// + public uint _hitCountMultiple; + public bool _breakWhenCondChanged; + public string _previousCondEvaluation = ""; + + /// + /// Indicates if a given breakpoint is being manipulated in one of these 2 methods: SetPassCount and BreakpointHit. + /// + public bool _blockedPassCount; + + /// + /// Indicates if a given breakpoint is being manipulated in one of these 2 methods: SetCondition and BreakpointHit. + /// + public bool _blockedConditional; + + /// + /// GDB member variables. + /// + private BreakpointInfo _gdbInfo; + + public BreakpointInfo GdbInfo + { + get { return _gdbInfo; } + set { _gdbInfo = value; } + } + + /// + /// AD7BoundBreakpoint constructor for file/line breaks. + /// + /// AD7 Engine. + /// Contains the information required to implement a breakpoint. + /// Associated pending breakpoint. + public AD7BoundBreakpoint(AD7Engine engine, BP_REQUEST_INFO requestInfo, AD7PendingBreakpoint pendingBreakpoint) + { + if (engine == null) + throw new ArgumentNullException("engine"); + + if (requestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) + { + string documentName; + + // Get Document Position and File Name + IDebugDocumentPosition2 docPosition = (IDebugDocumentPosition2)(Marshal.GetObjectForIUnknown(requestInfo.bpLocation.unionmember2)); + docPosition.GetFileName(out documentName); + + // Get the location in the document that the breakpoint is in. + TEXT_POSITION[] startPosition = new TEXT_POSITION[1]; + TEXT_POSITION[] endPosition = new TEXT_POSITION[1]; + docPosition.GetRange(startPosition, endPosition); + + _engine = engine; + m_bpLocationType = (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE; + m_filename = documentName.Replace('\\', '/'); + m_line = startPosition[0].dwLine + 1; + + _pendingBreakpoint = pendingBreakpoint; + _enabled = true; + _deleted = false; + _hitCount = 0; + _engine.BreakpointManager.RemoteAdd(this, out _gdbInfo); + } + else if (requestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) + { + string func; + + IDebugFunctionPosition2 funcPosition = (IDebugFunctionPosition2)(Marshal.GetObjectForIUnknown(requestInfo.bpLocation.unionmember2)); + funcPosition.GetFunctionName(out func); + + _engine = engine; + m_func = func; + _enabled = true; + _deleted = false; + _hitCount = 0; + m_bpLocationType = (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET; + _pendingBreakpoint = pendingBreakpoint; + _engine.BreakpointManager.RemoteAdd(this, out _gdbInfo); + } + + if (_gdbInfo != null) + { + if (!string.IsNullOrEmpty(_gdbInfo.FileName) && _gdbInfo.Address != 0) + { + // Set the hit count and condition + if (requestInfo.bpPassCount.stylePassCount != enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_NONE) + SetPassCount(requestInfo.bpPassCount); + if (requestInfo.bpCondition.styleCondition != enum_BP_COND_STYLE.BP_COND_NONE) + SetCondition(requestInfo.bpCondition); + + // Get the Line Position sent back from GDB + AD7MemoryAddress codeContext = new AD7MemoryAddress(_engine, _gdbInfo.Address); + AD7DocumentContext documentContext = new AD7DocumentContext(_gdbInfo.FileName, _gdbInfo.Line > 0 ? _gdbInfo.Line - 1 : 0, codeContext); + + _breakpointResolution = new AD7BreakpointResolution(_engine, _gdbInfo.Address, documentContext); + _engine.Callback.OnBreakpointBound(this, 0); + } + } + else + { + _gdbInfo = new BreakpointInfo(0, null, 0, 0); + } + } + + /// + /// Sets the count and conditions upon which a breakpoint is fired. + /// (http://msdn.microsoft.com/en-us/library/bb161364.aspx) + /// + /// Describes the count and conditions upon which a conditional breakpoint is fired. + /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. + public int SetPassCount(BP_PASSCOUNT bpPassCount) + { + bool isRunning = false; + int result = VSConstants.S_FALSE; + while (!_engine.EventDispatcher.LockedBreakpoint(this, true, false)) + { + Thread.Sleep(0); + } + while (!_engine.EventDispatcher.EnterCriticalRegion()) + { + Thread.Sleep(0); + } + if ((_engine.State == AD7Engine.DebugEngineState.Run) && (EventDispatcher._GDBRunMode == true)) + { + isRunning = true; + _engine.EventDispatcher.PrepareToModifyBreakpoint(); + } + m_bpPassCount = bpPassCount; + if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL_OR_GREATER) + { + _isHitCountEqual = false; + _hitCountMultiple = 0; + if (!_breakWhenCondChanged) + { + if ((int)((bpPassCount.dwPassCount - _hitCount)) >= 0) + { + if (_engine.EventDispatcher.IgnoreHitCount(_gdbInfo.ID, (int)(bpPassCount.dwPassCount - _hitCount))) + result = VSConstants.S_OK; + } + else + { + if (_engine.EventDispatcher.IgnoreHitCount(_gdbInfo.ID, 1)) + result = VSConstants.S_OK; + } + + } + else + result = VSConstants.S_OK; + } + else if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL) + { + _hitCountMultiple = 0; + _isHitCountEqual = true; + if (!_breakWhenCondChanged) + { + if (_engine.EventDispatcher.IgnoreHitCount(_gdbInfo.ID, (int)(bpPassCount.dwPassCount - _hitCount))) + result = VSConstants.S_OK; + } + else + result = VSConstants.S_OK; + } + else if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_MOD) + { + _isHitCountEqual = false; + _hitCountMultiple = bpPassCount.dwPassCount; + if (!_breakWhenCondChanged) + { + if (_engine.EventDispatcher.IgnoreHitCount(_gdbInfo.ID, (int)(_hitCountMultiple - (_hitCount % _hitCountMultiple)))) + result = VSConstants.S_OK; + } + else + result = VSConstants.S_OK; + } + else if (bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_NONE) + { + _isHitCountEqual = false; + _hitCountMultiple = 0; + if (!_breakWhenCondChanged) + { + if (_engine.EventDispatcher.IgnoreHitCount(_gdbInfo.ID, 1)) // ignoreHitCount decrement by 1 automatically, so sending 1 means to stop ignoring (or ignore 0) + result = VSConstants.S_OK; + } + else + result = VSConstants.S_OK; + } + + if (isRunning) + { + isRunning = false; + _engine.EventDispatcher.ResumeFromInterrupt(); + } + + _engine.EventDispatcher.LeaveCriticalRegion(); + _engine.EventDispatcher.UnlockBreakpoint(this, true, false); + return result; + } + + /// + /// Sets the conditions under which a conditional breakpoint fires. (http://msdn.microsoft.com/en-us/library/bb146215.aspx) + /// + /// Describes the conditions under which a breakpoint fires. + /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. + public int SetCondition(BP_CONDITION bpCondition) + { + bool updatingCondBreak = _engine._updatingConditionalBreakpoint.WaitOne(0); + bool isRunning = false; + bool verifyCondition = false; + int result = VSConstants.S_FALSE; + while (!_engine.EventDispatcher.LockedBreakpoint(this, false, true)) + { + Thread.Sleep(0); + } + + if (_hitCount != 0) + { + _engine.EventDispatcher.ResetHitCount(this, false); + } + + while (!_engine.EventDispatcher.EnterCriticalRegion()) + { + Thread.Sleep(0); + } + + if ((_engine.State == AD7Engine.DebugEngineState.Run) && (EventDispatcher._GDBRunMode == true)) + { + isRunning = true; + _engine.EventDispatcher.PrepareToModifyBreakpoint(); + _engine.State = AD7Engine.DebugEngineState.Break; + } + + m_bpCondition = bpCondition; + + if (bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE) + { + if (_breakWhenCondChanged) + { + _breakWhenCondChanged = false; + verifyCondition = true; + } + else + _breakWhenCondChanged = false; + + _previousCondEvaluation = ""; + if (_engine.EventDispatcher.SetBreakpointCondition(_gdbInfo.ID, bpCondition.bstrCondition)) + result = VSConstants.S_OK; + } + else if (bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_CHANGED) + { + _breakWhenCondChanged = true; + _previousCondEvaluation = bpCondition.bstrCondition; // just to initialize this variable + _engine.EventDispatcher.IgnoreHitCount(_gdbInfo.ID, 1); // have to break always to evaluate this option because GDB doesn't support it. + _engine.EventDispatcher.SetBreakpointCondition(_gdbInfo.ID, ""); + + result = VSConstants.S_OK; + } + else if (bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_NONE) + { + if (_breakWhenCondChanged) + { + _breakWhenCondChanged = false; + verifyCondition = true; + } + else + _breakWhenCondChanged = false; + + _previousCondEvaluation = ""; + if (_engine.EventDispatcher.SetBreakpointCondition(_gdbInfo.ID, "")) + result = VSConstants.S_OK; + } + + _engine.EventDispatcher.LeaveCriticalRegion(); + _engine.EventDispatcher.UnlockBreakpoint(this, false, true); + + if (verifyCondition) + { + SetPassCount(m_bpPassCount); + verifyCondition = false; + } + + if (isRunning) + { + isRunning = false; + _engine.State = AD7Engine.DebugEngineState.Run; + _engine.EventDispatcher.ResumeFromInterrupt(); + } + + _engine._updatingConditionalBreakpoint.Set(); + + return result; + } + + #region IDebugBoundBreakpoint2 Members + + /// + /// Called when the breakpoint is being deleted by the user. (http://msdn.microsoft.com/en-us/library/bb146595.aspx) + /// + /// VSConstants.S_OK + int IDebugBoundBreakpoint2.Delete() + { + if (!_deleted) + { + _enabled = false; + _deleted = true; + _pendingBreakpoint.OnBoundBreakpointDeleted(this); + _engine.BreakpointManager.RemoteDelete(this); + _gdbInfo = null; + } + return VSConstants.S_OK; + } + + /// + /// Called by the debugger UI when the user is enabling or disabling a breakpoint. + /// (http://msdn.microsoft.com/en-us/library/bb145150.aspx) + /// + /// Equal to 0 if disabling; different than 0 if enabling. + /// VSConstants.S_OK + int IDebugBoundBreakpoint2.Enable(int fEnable) + { + bool xEnabled = fEnable != 0; + if (_enabled != xEnabled) + { + if (xEnabled) + { + _engine.BreakpointManager.RemoteEnable(this); + } + else + { + _engine.BreakpointManager.RemoteDisable(this); + } + _enabled = xEnabled; + } + return VSConstants.S_OK; + } + + /// + /// Return the breakpoint resolution which describes how the breakpoint bound in the debuggee. + /// (http://msdn.microsoft.com/en-us/library/bb145891.aspx) + /// + /// Contains the information that describes a bound breakpoint. + /// VSConstants.S_OK + int IDebugBoundBreakpoint2.GetBreakpointResolution(out IDebugBreakpointResolution2 ppBPResolution) + { + ppBPResolution = _breakpointResolution; + return VSConstants.S_OK; + } + + /// + /// Return the pending breakpoint for this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb145337.aspx) + /// + /// Contains a breakpoint that is ready to bind to a code location. + /// VSConstants.S_OK + int IDebugBoundBreakpoint2.GetPendingBreakpoint(out IDebugPendingBreakpoint2 ppPendingBreakpoint) + { + ppPendingBreakpoint = _pendingBreakpoint; + return VSConstants.S_OK; + } + + /// + /// Gets the state of this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb161276.aspx) + /// + /// Describes the state of the breakpoint. + /// VSConstants.S_OK + int IDebugBoundBreakpoint2.GetState(enum_BP_STATE[] pState) + { + pState[0] = 0; + + if (_deleted) + { + pState[0] = enum_BP_STATE.BPS_DELETED; + } + else if (_enabled) + { + pState[0] = enum_BP_STATE.BPS_ENABLED; + } + else if (!_enabled) + { + pState[0] = enum_BP_STATE.BPS_DISABLED; + } + + return VSConstants.S_OK; + } + + /// + /// Gets the current hit count for this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb145340.aspx) + /// + /// Returns the hit count. + /// AD7_HRESULT.E_BP_DELETED if the breakpoint was deleted; or VSConstants.S_OK if not. + int IDebugBoundBreakpoint2.GetHitCount(out uint pdwHitCount) + { + if (_deleted) + { + pdwHitCount = 0; + return AD7_HRESULT.E_BP_DELETED; + } + else + { + pdwHitCount = _hitCount; + return VSConstants.S_OK; + } + } + + /// + /// Sets or changes the condition associated with this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb146215.aspx) + /// + /// Describes the condition. + /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. + int IDebugBoundBreakpoint2.SetCondition(BP_CONDITION bpCondition) + { + return SetCondition(bpCondition); + } + + /// + /// Sets the hit count for the bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb146736.aspx) + /// + /// The hit count to set. + /// AD7_HRESULT.E_BP_DELETED if the breakpoint was deleted; or VSConstants.S_OK if not. + int IDebugBoundBreakpoint2.SetHitCount(uint dwHitCount) + { + if (_deleted) + { + return AD7_HRESULT.E_BP_DELETED; + } + else + { + if ((dwHitCount == 0) && (_hitCount != 0)) + { + _hitCount = dwHitCount; + _engine.EventDispatcher.ResetHitCount(this, true); + } + else + _hitCount = dwHitCount; + return VSConstants.S_OK; + } + } + + /// + /// Sets or changes the pass count associated with this bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb161364.aspx) + /// + /// Specifies the pass count. + /// VSConstants.S_OK if successful, VSConstants.S_FALSE if not. + int IDebugBoundBreakpoint2.SetPassCount(BP_PASSCOUNT bpPassCount) + { + return SetPassCount(bpPassCount); + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7BreakpointResolution.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7BreakpointResolution.cs new file mode 100644 index 00000000..1c17e776 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7BreakpointResolution.cs @@ -0,0 +1,111 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System.Runtime.InteropServices; + +// TODO: Change to take filename and line number instead of an address? + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents the information that describes a bound breakpoint. (http://msdn.microsoft.com/en-us/library/bb145894.aspx) + /// + public class AD7BreakpointResolution : IDebugBreakpointResolution2 + { + /// + /// AD7 Engine. + /// + private readonly AD7Engine _engine; + + /// + /// GDB Address + /// + private readonly uint _address; + + /// + /// The document context to the debugger. A document context represents a location within a source file. + /// + private readonly AD7DocumentContext _documentContext; + + /// + /// Constructor. + /// + /// AD7 Engine. + /// GDB Address. + /// The document context to the debugger. A document context represents a location within a + /// source file. + public AD7BreakpointResolution(AD7Engine engine, uint address, AD7DocumentContext documentContext) + { + if (engine == null) + throw new ArgumentNullException("engine"); + + _engine = engine; + _address = address; + _documentContext = documentContext; + } + + #region IDebugBreakpointResolution2 Members + + /// + /// Gets the type of the breakpoint represented by this resolution. (http://msdn.microsoft.com/en-us/library/bb145576.aspx) + /// + /// The type of this breakpoint. + /// VSConstants.S_OK. + int IDebugBreakpointResolution2.GetBreakpointType(enum_BP_TYPE[] pBPType) + { + // The VSNDK debug engine only supports code breakpoints. + pBPType[0] = enum_BP_TYPE.BPT_CODE; + return VSConstants.S_OK; + } + + /// + /// Gets the breakpoint resolution information that describes this breakpoint. + /// (http://msdn.microsoft.com/en-us/library/bb146743.aspx) + /// + /// A combination of flags that determine which fields of the pBPResolutionInfo parameter are to be filled out. + /// The BP_RESOLUTION_INFO structure to be filled in with information about this breakpoint. + /// VSConstants.S_OK. + int IDebugBreakpointResolution2.GetResolutionInfo(enum_BPRESI_FIELDS dwFields, BP_RESOLUTION_INFO[] pBPResolutionInfo) + { + if ((dwFields & enum_BPRESI_FIELDS.BPRESI_BPRESLOCATION) != 0) + { + // The sample engine only supports code breakpoints. + BP_RESOLUTION_LOCATION location = new BP_RESOLUTION_LOCATION(); + location.bpType = (uint)enum_BP_TYPE.BPT_CODE; + + // The debugger will not QI the IDebugCodeContex2 interface returned here. We must pass the pointer + // to IDebugCodeContex2 and not IUnknown. + AD7MemoryAddress codeContext = new AD7MemoryAddress(_engine, _address); + codeContext.SetDocumentContext(_documentContext); + location.unionmember1 = Marshal.GetComInterfaceForObject(codeContext, typeof(IDebugCodeContext2)); + pBPResolutionInfo[0].bpResLocation = location; + pBPResolutionInfo[0].dwFields |= enum_BPRESI_FIELDS.BPRESI_BPRESLOCATION; + + } + + if ((dwFields & enum_BPRESI_FIELDS.BPRESI_PROGRAM) != 0) + { + pBPResolutionInfo[0].pProgram = _engine; + pBPResolutionInfo[0].dwFields |= enum_BPRESI_FIELDS.BPRESI_PROGRAM; + } + + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7DocumentContext.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7DocumentContext.cs new file mode 100644 index 00000000..4a24e3cf --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7DocumentContext.cs @@ -0,0 +1,202 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.NativeCore; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents a document context to the debugger. A document context represents a location within a source file. + /// (http://msdn.microsoft.com/en-us/library/bb145572.aspx) + /// + public sealed class AD7DocumentContext : IDebugDocumentContext2 + { + /// + /// Long path file name + /// + private readonly string _fileName; + + /// + /// Start position. In VSNDK debug engine, both begPos and endPos have the same value. + /// + private TEXT_POSITION _beginPosition; + + /// + /// End position. In VSNDK debug engine, both begPos and endPos have the same value. + /// + private TEXT_POSITION _endPosition; + + /// + /// An address in a program's execution stream. + /// + private readonly AD7MemoryAddress _codeContext; + + /// + /// Constructor. + /// + /// Short path file name. + /// Start position. + /// An address in a program's execution stream. + public AD7DocumentContext(string fileName, uint line, AD7MemoryAddress codeContext) + { + // Need to lengthen the path to be used by Visual Studio. + _fileName = NativeMethods.GetLongPathName(fileName.Replace(@"\\\\", @"\\").Replace(@"\\", @"\")).Replace('\\', '/'); + + // Assume source code matching breakpoint begins and ends at the beginning of the line: + _beginPosition = new TEXT_POSITION(); + _beginPosition.dwLine = line; + _beginPosition.dwColumn = 0; + _endPosition = new TEXT_POSITION(); + _endPosition.dwLine = line; + _endPosition.dwColumn = 0; + _codeContext = codeContext; + } + + #region IDebugDocumentContext2 Members + + /// + /// Compares this document context to a given array of document contexts. (http://msdn.microsoft.com/en-us/library/bb145338.aspx) + /// + /// A value from the DOCCONTEXT_COMPARE enumeration that specifies the type of comparison. + /// An array of IDebugDocumentContext2 objects that represent the document contexts being compared to. + /// The length of the array of document contexts to compare. + /// Returns the index into the rgpDocContextSet array of the first document context that satisfies the comparison. + /// VSConstants.E_NOTIMPL. + int IDebugDocumentContext2.Compare(enum_DOCCONTEXT_COMPARE compare, IDebugDocumentContext2[] rgpDocContextSet, uint dwDocContextSetLen, out uint pdwDocContext) + { + pdwDocContext = 0; + return EngineUtils.NotImplemented(); + } + + /// + /// Retrieves a list of all code contexts associated with this document context. The VSNDK Debug Engine only supports one code context per document + /// context and the code contexts are always memory addresses. (http://msdn.microsoft.com/en-us/library/bb146273.aspx) + /// + /// Returns an IEnumDebugCodeContexts2 object that contains a list of code contexts. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugDocumentContext2.EnumCodeContexts(out IEnumDebugCodeContexts2 ppEnumCodeCxts) + { + ppEnumCodeCxts = null; + try + { + IDebugCodeContext2[] codeContexts = new IDebugCodeContext2[1]; + codeContexts[0] = _codeContext; + ppEnumCodeCxts = new AD7CodeContextEnum(codeContexts); + return VSConstants.S_OK; + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + } + + /// + /// Gets the document that contains this document context. This method is for those debug engines that supply documents directly + /// to the IDE. Since the VSNDK Debug Engine does not do this, this method returns E_FAIL. + /// (http://msdn.microsoft.com/en-us/library/bb161759.aspx) + /// + /// Returns an IDebugDocument2 object that represents the document that contains this document context. + /// E_FAIL. + int IDebugDocumentContext2.GetDocument(out IDebugDocument2 ppDocument) + { + ppDocument = null; + return VSConstants.E_FAIL; + } + + /// + /// Gets the language associated with this document context. The language for this sample is always C++. + /// (http://msdn.microsoft.com/en-us/library/bb146340.aspx) + /// + /// Returns the name of the language that implements the code at this document context. + /// Returns the GUID of the language that implements the code at this document context. + /// VSConstants.S_OK. + int IDebugDocumentContext2.GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) + { + pbstrLanguage = "C++"; + pguidLanguage = AD7Guids.guidLanguageCpp; + return VSConstants.S_OK; + } + + /// + /// Gets the displayable name of the document that contains this document context. + /// (http://msdn.microsoft.com/en-us/library/bb146162.aspx) + /// + /// A value from the GETNAME_TYPE enumeration that specifies the type of name to return. + /// Returns the name of the file. + /// VSConstants.S_OK. + int IDebugDocumentContext2.GetName(enum_GETNAME_TYPE gnType, out string pbstrFileName) + { + pbstrFileName = _fileName; + return VSConstants.S_OK; + } + + /// + /// Gets the source code range of this document context. A source range is the entire range of source code, from the current + /// statement back to just after the previous statement that contributed code. The source range is typically used for mixing + /// source statements, including comments, with code in the disassembly window. Since this engine does not support the + /// disassembly window, this is not implemented. (http://msdn.microsoft.com/en-us/library/bb146190.aspx) + /// + /// A TEXT_POSITION structure that is filled in with the starting position. Set to a null value if it is not needed. + /// A TEXT_POSITION structure that is filled in with the ending position. Set to a null value if it is not needed. + /// Not implemented. + int IDebugDocumentContext2.GetSourceRange(TEXT_POSITION[] pBegPosition, TEXT_POSITION[] pEndPosition) + { + return EngineUtils.NotImplemented(); + } + + /// + /// Gets the file statement range of the document context. A statement range is the range of the lines that contributed the code + /// to which this document context refers. (http://msdn.microsoft.com/en-us/library/bb161669.aspx) + /// + /// A TEXT_POSITION structure that is filled in with the starting position. Set to a null value if it is not needed. + /// A TEXT_POSITION structure that is filled in with the ending position. Set to a null value if it is not needed. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugDocumentContext2.GetStatementRange(TEXT_POSITION[] pBegPosition, TEXT_POSITION[] pEndPosition) + { + try + { + pBegPosition[0].dwColumn = _beginPosition.dwColumn; + pBegPosition[0].dwLine = _beginPosition.dwLine; + + pEndPosition[0].dwColumn = _endPosition.dwColumn; + pEndPosition[0].dwLine = _endPosition.dwLine; + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + + return VSConstants.S_OK; + } + + /// + /// Moves the document context by a given number of statements or lines. This is used primarily to support the Autos window in + /// discovering the proximity statements around this document context. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb146603.aspx) + /// + /// The number of statements or lines to move ahead, depending on the document context. + /// Returns a new IDebugDocumentContext2 object with the new position. + /// Not implemented. + int IDebugDocumentContext2.Seek(int nCount, out IDebugDocumentContext2 ppDocContext) + { + ppDocContext = null; + return EngineUtils.NotImplemented(); + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Engine.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Engine.cs new file mode 100644 index 00000000..6fd25cb4 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Engine.cs @@ -0,0 +1,1392 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Runtime.InteropServices; +using BlackBerry.NativeCore.Debugger; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Services; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System.Diagnostics; +using System.Threading; +using System.Windows.Forms; + +namespace BlackBerry.DebugEngine +{ + /// + /// AD7Engine is the primary entrypoint object for the sample engine. + /// + /// It implements: + /// + /// IDebugEngine2: This interface represents a debug engine (DE). It is used to manage various aspects of a debugging session, + /// from creating breakpoints to setting and clearing exceptions. (http://msdn.microsoft.com/en-us/library/bb145310.aspx). + /// + /// IDebugEngineLaunch2: Used by a debug engine (DE) to launch and terminate programs. + /// (http://msdn.microsoft.com/en-us/library/bb146230.aspx). + /// + /// IDebugProgram3: This interface represents a program that is running in a process. Since this engine only debugs one process at a time and each + /// process only contains one program, it is implemented on the engine. (http://msdn.microsoft.com/en-us/library/bb145884.aspx). + /// + /// IDebugEngineProgram2: This interface provides simultanious debugging of multiple threads in a debuggee. + /// (http://msdn.microsoft.com/en-us/library/bb145128.aspx). + /// + /// IDebugSymbolSettings100: (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugsymbolsettings100.aspx). + /// + /// Comments: + /// Process "Is a container for a set of programs". + /// "A debug engine (DE) attaches to a program, and not to a process or a thread". + /// Program "Is a container for both a set of threads and a set of modules.". + /// + [ComVisible(true)] + [Guid(ClassGuid)] + public sealed class AD7Engine : IDebugEngine2, IDebugEngineLaunch2, IDebugProgram3, IDebugEngineProgram2, IDebugSymbolSettings100 + { + public const string ClassGuid = "904AA6E0-942C-4D11-9094-7BAAEB3EE4B9"; + public const string ClassName = "BlackBerry.DebugEngine.AD7Engine"; + + /// + /// This is the engine GUID of the VSNDK debug engine. It needs to be changed here and in the registration when creating a new engine. + /// + public const string DebugEngineGuid = "{E5A37609-2F43-4830-AA85-D94CFA035DD2}"; + + /// + /// Used to send events to the debugger. Some examples of these events are thread create, exception thrown, module load. + /// + public EngineCallback Callback + { + get; + private set; + } + + /// + /// This object manages breakpoints in the sample engine. + /// + public BreakpointManager BreakpointManager + { + get; + private set; + } + + /// + /// This object manages debug events in the engine. + /// + public EventDispatcher EventDispatcher + { + get; + private set; + } + + /// + /// A unique identifier for the program being debugged. + /// + private Guid _programGuid; + + /// + /// A module loaded in the debuggee process to the debugger. It is always null because the AD7Module class is + /// not implemented yet. + /// + private AD7Module _module; + + /// + /// A process running on a port. A process "Is a container for a set of programs". + /// + private AD7Process _process; + + /// + /// A program that can be debugged. + /// + private AD7ProgramNode _progNode; + + /// + /// A program that is running in a process. + /// + private IDebugProgram2 _program; + + /// + /// TRUE whenever a thread is created/ended, so the debug engine can update the m_threads data structure. + /// + public bool _updateThreads; + + /// + /// Array of threads of the program that is being debugged. + /// + public AD7Thread[] Threads + { + get; + private set; + } + + /// + /// The position in the m_threads array that corresponds to the current thread. + /// + public int _currentThreadIndex = -1; + + /// + /// Used to avoid race condition when there are conditional breakpoints and the user hit break all. Both events will pause + /// the Debug Engine, but the one related to conditional breakpoint can resume execution. If both events happens at the same + /// time, the Debug Engine could resume the execution instead of pausing it. + /// + public ManualResetEvent _running = new ManualResetEvent(true); + + /// + /// Used to avoid race condition when there are conditional breakpoints and a breakpoint is hit. This situation is similar to the above one. + /// + public ManualResetEvent _updatingConditionalBreakpoint = new ManualResetEvent(true); + + /// + /// Keeps track of debug engine states + /// + public enum DebugEngineState + { + Design = 0, + Run, + Break, + Step, + Done + } + + public DebugEngineState State + { + get; + set; + } + + public AD7Module Module + { + get { return _module; } + } + + public IDebugProgram2 Program + { + get { return _program; } + } + + /// + /// Constructor. + /// + public AD7Engine() + { + BreakpointManager = new BreakpointManager(this); + State = DebugEngineState.Design; + } + + /// + /// Destructor. + /// + ~AD7Engine() + { + // Transition DE state + State = DebugEngineState.Done; + } + + #region Properties + + public bool HasProcess + { + get { return _process != null; } + } + + #endregion + + #region IDebugEngine2 Members + + /// + /// Attach the debug engine to a program. (http://msdn.microsoft.com/en-us/library/bb145136.aspx) + /// + /// Represent programs to be attached to. These are port programs. + /// Represent program nodes, one for each program. The program nodes in this array represent + /// the same programs as in pProgram. The program nodes are given so that the DE can identify the programs to attach to. + /// Number of programs and/or program nodes in the pProgram and rgpProgramNodes arrays. + /// The IDebugEventCallback2 object to be used to send debug events to the SDM. + /// A value from the ATTACH_REASON enumeration that specifies the reason for attaching these programs. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint aCeltPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason) + { + if (aCeltPrograms != 1) + { + Debug.Fail("VSNDK Debugger only supports one debug target at a time."); + throw new ArgumentException(); + } + + try + { + EngineUtils.RequireOK(rgpPrograms[0].GetProgramId(out _programGuid)); + + _program = rgpPrograms[0]; + + // It is NULL when the user attached the debugger to a running process (by using Attach to Process UI). When that + // happens, some objects must be instantiated, as well as GDB must be launched. Those ones are instantiated/launched + // by LaunchSuspended and ResumeProcess methods when debugging an open project. + if (Callback == null) + { + DebugEngineStatus.IsRunning = true; + Callback = new EngineCallback(this, ad7Callback); + + var programNode = (AD7ProgramNodeAttach)_program; + _process = programNode.Process; + var port = (AD7Port)programNode.Process.Port; + + var attachDiscoveryService = (IAttachDiscoveryService) Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IAttachDiscoveryService)); + Debug.Assert(attachDiscoveryService != null, "Invalid project references (make sure VisualStudio.Shell.dll is not references, as it duplicates the Package definition from VisualStudio.Shell..dll)"); + + // ask the package about opened BlackBerry projects and find matching one: + var exePath = attachDiscoveryService.FindExecutable(_process.Details); + + // load from registry + var runtime = RuntimeDefinition.Load(); + + uint aux; + if (GdbWrapper.AttachToProcess(programNode.Process.ID.ToString(), exePath, _process.Details, port.NDK, port.Device, runtime, out aux)) + { + if (exePath == "CannotAttachToRunningProcess") + { + MessageBoxHelper.Show(_process.Details.Name + " is attached to the debugger. However, to be able to debug your application, you must build and deploy it from this computer first.", "No executable file with symbols found.", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + EventDispatcher = new EventDispatcher(this); + _module = new AD7Module(); + _progNode = new AD7ProgramNode(_process); + AddThreadsToProgram(); + } + else + { + DebugEngineStatus.IsRunning = false; + return VSConstants.E_FAIL; + } + } + AD7EngineCreateEvent.Send(this); + AD7ProgramCreateEvent.Send(this); + AD7ModuleLoadEvent.Send(this, _module, true); + AD7LoadCompleteEvent.Send(this, CurrentThread()); + + // If the reason for attaching is ATTACH_REASON_LAUNCH, the DE needs to send the IDebugEntryPointEvent2 event. + // See http://msdn.microsoft.com/en-us/library/bb145136%28v=vs.100%29.aspx + if (dwReason == enum_ATTACH_REASON.ATTACH_REASON_LAUNCH) + { + AD7EntryPointEvent ad7Event = new AD7EntryPointEvent(); + Guid riidEvent = new Guid(AD7EntryPointEvent.IID); + uint attributes = (uint)enum_EVENTATTRIBUTES.EVENT_STOPPING | (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; + int rc = ad7Callback.Event(this, null, _program, CurrentThread(), ad7Event, ref riidEvent, attributes); + Debug.Assert(rc == VSConstants.S_OK); + } + } + catch (Exception e) + { + return EngineUtils.UnexpectedException(e); + } + return VSConstants.S_OK; + } + + /// + /// Requests that all programs being debugged by this DE stop execution the next time one of their threads attempts to run. + /// This is normally called in response to the user clicking on the pause button in the debugger. When the break is complete, + /// an AsyncBreakComplete event will be sent back to the debugger. (http://msdn.microsoft.com/en-us/library/bb145141.aspx) + /// + /// VSConstants.S_OK. + int IDebugEngine2.CauseBreak() + { + // If not already broken, send the interrupt + if (State != DebugEngineState.Design && State != DebugEngineState.Break && State != DebugEngineState.Step) + { + if (EventDispatcher._GDBRunMode) + { + HandleProcessExecution.m_mre.Reset(); + _running.WaitOne(); + + // Sends the GDB command that interrupts the background execution of the target. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand(@"-exec-interrupt"); + + // Ensure the process is interrupted before returning + HandleProcessExecution.m_mre.WaitOne(1000); + + _running.Set(); + + if (DebugEngineStatus.IsRunning) + HandleProcessExecution.m_mre.Reset(); + } + } + + return VSConstants.S_OK; + } + + /// + /// Called by the SDM to indicate that a synchronous debug event, previously sent by the DE to the SDM, + /// was received and processed. The only event the VSNDK Debug Engine sends in this fashion is Program Destroy. + /// It responds to that event by shutting down the engine. (http://msdn.microsoft.com/en-us/library/bb160915.aspx) + /// + /// Represents the previously sent synchronous event from which the debugger should now continue. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugEngine2.ContinueFromSynchronousEvent(IDebugEvent2 eventObject) + { + try + { + if (eventObject is AD7ProgramDestroyEvent) + { + ResetStackFrames(); + _process.Detach(); + _process = null; + + _program.Detach(); + _program = null; + + Callback = null; + BreakpointManager = null; + EventDispatcher.Dispose(); + EventDispatcher = null; + _module = null; + _progNode = null; + _programGuid = Guid.Empty; + + Threads = null; + } + else + { + Debug.Fail("Unknown synchronous event"); + } + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + + if (EventDispatcher != null) + EventDispatcher.ContinueExecution(); + + return VSConstants.S_OK; + } + + /// + /// Creates a pending breakpoint in the Debug Engine. A pending breakpoint is essentially a collection of all the information + /// needed to bind a breakpoint to code. (http://msdn.microsoft.com/en-us/library/bb147033.aspx) + /// + /// An IDebugBreakpointRequest2 object that describes the pending breakpoint to create. + /// Returns an IDebugPendingBreakpoint2 object that represents the pending breakpoint. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugEngine2.CreatePendingBreakpoint(IDebugBreakpointRequest2 pBPRequest, out IDebugPendingBreakpoint2 ppPendingBP) + { + Debug.Assert(BreakpointManager != null); + ppPendingBP = null; + + try + { + BreakpointManager.CreatePendingBreakpoint(pBPRequest, out ppPendingBP); + } + catch (Exception e) + { + return EngineUtils.UnexpectedException(e); + } + + return VSConstants.S_OK; + } + + /// + /// Informs a DE that the program specified has been atypically terminated and that the DE should clean up all references + /// to the program and send a program destroy event. (http://msdn.microsoft.com/en-us/library/bb145073.aspx) + /// + /// An IDebugProgram2 object that represents the program that has been atypically terminated. + /// AD7_HRESULT.E_PROGRAM_DESTROY_PENDING. + int IDebugEngine2.DestroyProgram(IDebugProgram2 pProgram) + { + // Tell the SDM that the engine knows that the program is exiting, and that the + // engine will send a program destroy. We do this because the Win32 debug api will always + // tell us that the process exited, and otherwise we have a race condition. + + return (AD7_HRESULT.E_PROGRAM_DESTROY_PENDING); + } + + /// + /// Gets the GUID of the DE. (http://msdn.microsoft.com/en-us/library/bb145079.aspx) + /// + /// Returns the GUID of the DE. + /// VSConstants.S_OK. + int IDebugEngine2.GetEngineId(out Guid guidEngine) + { + guidEngine = new Guid(DebugEngineGuid); + return VSConstants.S_OK; + } + + /// + /// Removes the list of exceptions the IDE has set for a particular run-time architecture or language. The VSNDK debug engine + /// does not support exceptions in the debuggee so this method is not actually implemented. + /// (http://msdn.microsoft.com/en-us/library/bb145134.aspx) + /// + /// Either the GUID for the language or the GUID for the debug engine that is specific to a run-time + /// architecture. + /// VSConstants.S_OK. + int IDebugEngine2.RemoveAllSetExceptions(ref Guid guidType) + { + return VSConstants.S_OK; + } + + /// + /// Removes the specified exception so it is no longer handled by the debug engine. The VSNDK debug engine does not support + /// exceptions in the debuggee so this method is not actually implemented. (http://msdn.microsoft.com/en-us/library/bb161697.aspx) + /// + /// An EXCEPTION_INFO structure that describes the exception to be removed. + /// VSConstants.S_OK. + int IDebugEngine2.RemoveSetException(EXCEPTION_INFO[] pException) + { + // The VSNDK debug engine will always stop on all exceptions. + + return VSConstants.S_OK; + } + + /// + /// Specifies how the DE should handle a given exception. The VSNDK debug engine does not support exceptions in the debuggee + /// so this method is not actually implemented. (http://msdn.microsoft.com/en-us/library/bb162170.aspx) + /// + /// An EXCEPTION_INFO structure that describes the exception and how to debug it. + /// VSConstants.S_OK. + int IDebugEngine2.SetException(EXCEPTION_INFO[] pException) + { + return VSConstants.S_OK; + } + + /// + /// Sets the locale of the DE. This method is called by the session debug manager (SDM) to propagate the locale settings + /// of the IDE so that strings returned by the DE are properly localized. The sample engine is not localized so this is + /// not implemented. (http://msdn.microsoft.com/en-us/library/bb161784.aspx) + /// + /// Specifies the language locale. + /// VSConstants.S_OK. + int IDebugEngine2.SetLocale(ushort wLangID) + { + return VSConstants.S_OK; + } + + /// + /// A metric is a registry value used to change a debug engine's behavior or to advertise supported functionality. + /// This method can forward the call to the appropriate form of the Debugging SDK Helpers function, SetMetric. + /// (http://msdn.microsoft.com/en-us/library/bb161968.aspx) + /// + /// The metric name. + /// Specifies the metric value. + /// VSConstants.S_OK. + int IDebugEngine2.SetMetric(string pszMetric, object varValue) + { + // The VSNDK debug engine does not need to understand any metric settings. + return VSConstants.S_OK; + } + + /// + /// Sets the registry root currently in use by the DE. Different installations of Visual Studio can change where their + /// registry information is stored. This allows the debugger to tell the engine where that location is. + /// (http://msdn.microsoft.com/en-us/library/bb161800.aspx) + /// + /// The registry root to use. + /// VSConstants.S_OK. + int IDebugEngine2.SetRegistryRoot(string pszRegistryRoot) + { + // The VSNDK debug engine does not read settings from the registry. + return VSConstants.S_OK; + } + + #endregion + + #region IDebugEngineLaunch2 Members + + /// + /// Determines if a process can be terminated. (http://msdn.microsoft.com/en-us/library/bb146673.aspx) + /// + /// An IDebugProcess2 object that represents the process to be terminated. + /// VSConstants.S_OK. + int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 process) + { + return VSConstants.S_OK; + } + + /// + /// Launches a process by means of the debug engine. (http://msdn.microsoft.com/en-us/library/bb146223.aspx) + /// + /// The name of the machine in which to launch the process. Use a null value to specify the local + /// machine. Or it should be the name of the server? + /// The IDebugPort2 interface representing the port that the program will run in. + /// The name of the executable to be launched. + /// The arguments to pass to the executable. May be a null value if there are no arguments. + /// The name of the working directory used by the executable. May be a null value if no working directory is + /// required. + /// Environment block of NULL-terminated strings, followed by an additional NULL terminator. + /// The options for the executable. + /// Specifies the LAUNCH_FLAGS for a session. + /// Handle to an alternate input stream. May be 0 if redirection is not required. + /// Handle to an alternate output stream. May be 0 if redirection is not required. + /// Handle to an alternate error output stream. May be 0 if redirection is not required. + /// The IDebugEventCallback2 object that receives debugger events. + /// Returns the resulting IDebugProcess2 object that represents the launched process. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) + { + Debug.Assert(_programGuid == Guid.Empty); + + process = null; + + try + { + DebugEngineStatus.IsRunning = true; + Callback = new EngineCallback(this, ad7Callback); + + // Read arguments back from the args string + var nvc = CollectionHelper.Deserialize(args); + + uint pidNumber; + string pidOrName = nvc["pidOrName"]; + + var target = CollectionHelper.GetDevice(nvc); + var ndk = CollectionHelper.GetNDK(nvc); + var runtime = CollectionHelper.GetRuntime(nvc); + if (target == null) + { + TraceLog.WriteLine("LaunchSuspended: Missing info about target device"); + return VSConstants.E_FAIL; + } + if (ndk == null) + { + TraceLog.WriteLine("LaunchSuspended: Missing info about NDK"); + return VSConstants.E_FAIL; + } + + var result = GdbWrapper.AttachToProcess(pidOrName, exe, null, ndk, target, runtime, out pidNumber); + if (result) + { + process = _process = new AD7Process(port, new ProcessInfo(pidNumber, exe), target); + EventDispatcher = new EventDispatcher(this); + _programGuid = _process.UID; + _module = new AD7Module(); + _progNode = new AD7ProgramNode(_process); + AddThreadsToProgram(); + + AD7EngineCreateEvent.Send(this); + + return VSConstants.S_OK; + } + + DebugEngineStatus.IsRunning = false; + return VSConstants.E_FAIL; + } + catch (Exception e) + { + EngineUtils.UnexpectedException(e); + return VSConstants.E_FAIL; + } + } + + /// + /// Resume a process launched by IDebugEngineLaunch2.LaunchSuspended. (http://msdn.microsoft.com/en-us/library/bb146261.aspx) + /// + /// An IDebugProcess2 object that represents the process to be resumed. + /// An IDebugProcess2 object that represents the process to be resumed. + int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process) + { + Debug.Assert(Callback != null); + + try + { + var xProcess = process as AD7Process; + if (xProcess == null) + { + return VSConstants.E_INVALIDARG; + } + + // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach + // which will complete the hookup with AD7 + IDebugPort2 port; + EngineUtils.RequireOK(process.GetPort(out port)); + + IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port; + + IDebugPortNotify2 portNotify; + EngineUtils.RequireOK(defaultPort.GetPortNotify(out portNotify)); + + EngineUtils.RequireOK(portNotify.AddProgramNode(_progNode)); + + Callback.OnModuleLoad(_module); + + Callback.OnThreadStart(CurrentThread()); + } + catch (Exception e) + { + return EngineUtils.UnexpectedException(e); + } + return VSConstants.S_OK; + } + + + /// + /// This function is used to terminate a process. (http://msdn.microsoft.com/en-us/library/bb162314.aspx) + /// The debugger will call IDebugEngineLaunch2::CanTerminateProcess before calling this method. + /// + /// An IDebugProcess2 object that represents the process to be terminated. + /// VSConstants.S_OK. + int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 process) + { + CauseBreak(); + if (EventDispatcher != null) + { + EventDispatcher.KillProcess(); + EventDispatcher.EndDebugSession(0); + } + + return VSConstants.S_OK; + } + + #endregion + + #region IDebugProgram2 Members + + /// + /// Determines if a debug engine (DE) can detach from the program. (http://msdn.microsoft.com/en-us/library/bb161967.aspx) + /// + /// VSConstants.S_OK. + public int CanDetach() + { + // The VSNDK debug engine always supports detach + return VSConstants.S_OK; + } + + /// + /// Requests that the program stop execution the next time one of its threads attempts to run. The debugger calls CauseBreak + /// when the user clicks on the pause button in VS. The debugger should respond by entering breakmode. + /// (http://msdn.microsoft.com/en-us/library/bb145018.aspx) + /// + /// VSConstants.S_OK. + public int CauseBreak() + { + return ((IDebugEngine2)this).CauseBreak(); + } + + /// + /// Continues running this program from a stopped state. Any previous execution state (such as a step) is preserved, and + /// the program starts executing again. (http://msdn.microsoft.com/en-us/library/bb162148.aspx) + /// + /// An IDebugThread2 object that represents the thread. + /// VSConstants.S_OK. + public int Continue(IDebugThread2 pThread) + { + EventDispatcher.ContinueExecution(); + + return VSConstants.S_OK; + } + + /// + /// Detaches a debug engine from the program. (http://msdn.microsoft.com/en-us/library/bb146228.aspx) + /// + /// VSConstants.S_OK. + public int Detach() + { + CauseBreak(); + if (BreakpointManager != null) + BreakpointManager.ClearBoundBreakpoints(); // TODO: Check if active bound BP list needs to be updated too? + + if (EventDispatcher != null) + EventDispatcher.EndDebugSession(0); + + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of the code contexts for a given position in a source file. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb145902.aspx) + /// + /// An object representing an abstract position in a source file known to the IDE. + /// Returns an IEnumDebugCodeContexts2 object that contains a list of the code contexts. + /// Not implemented. + public int EnumCodeContexts(IDebugDocumentPosition2 pDocPos, out IEnumDebugCodeContexts2 ppEnum) + { + ppEnum = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Retrieves a list of the code paths for a given position in a source file. EnumCodePaths is used for the step-into specific + /// feature -- right click on the current statement and decide which function to step into. This is not something that the + /// VSNDK debug engine supports. (http://msdn.microsoft.com/en-us/library/bb162326.aspx) + /// + /// The word under the cursor in the Source or Disassembly view in the IDE. + /// An IDebugCodeContext2 object representing the current code context. + /// An IDebugStackFrame2 object representing the stack frame associated with the current breakpoint. + /// Nonzero (TRUE) if in the Source view, or zero (FALSE) if in the Disassembly view. + /// Returns an IEnumCodePaths2 object containing a list of the code paths. + /// Returns an IDebugCodeContext2 object representing an additional code context to be set as a + /// breakpoint in case the chosen code path is skipped. This can happen in the case of a short-circuited Boolean expression, + /// for example. + /// VSConstants.E_NOTIMPL. + public int EnumCodePaths(string hint, IDebugCodeContext2 start, IDebugStackFrame2 frame, int fSource, out IEnumCodePaths2 pathEnum, out IDebugCodeContext2 safetyContext) + { + pathEnum = null; + safetyContext = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Retrieves a list of the modules that this program has loaded and is executing. + /// (http://msdn.microsoft.com/en-us/library/bb146980.aspx) + /// + /// Returns an IEnumDebugModules2 object that contains a list of the modules. + /// VSConstants.S_OK. + public int EnumModules(out IEnumDebugModules2 ppEnum) + { + ppEnum = new AD7ModuleEnum(new[] { _module }); + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of the threads that are running in the program. (http://msdn.microsoft.com/en-us/library/bb145110.aspx) + /// + /// Returns an IEnumDebugThreads2 object that contains a list of the threads. + /// If successful, returns S_OK; otherwise, returns an error code. + public int EnumThreads(out IEnumDebugThreads2 ppEnum) + { + AD7Thread[] listThreads = null; + int currentThread = 0; + + if (State != DebugEngineState.Run) + currentThread = GetListOfThreads(out listThreads); + + // the following code seems to be weird but I had to update each field of this.m_process._threads because, when using + // "this.m_process._threads = listThreads;" without having a new thread, VS starts to duplicate the existing threads + // and, as a consequence, the call stack entries too. + + if ((currentThread == -1) || (listThreads == null)) + { + ppEnum = null; + return currentThread == 0 ? VSConstants.S_OK : VSConstants.S_FALSE; + } + + if (listThreads.Length != Threads.Length) + { + foreach (AD7Thread t in Threads) + { + AD7ThreadDestroyEvent.Send(this, 0, t); + } + Threads = null; + Threads = listThreads; + _currentThreadIndex = currentThread; + foreach (AD7Thread t in Threads) + { + Callback.OnThreadStart(t); + } + ppEnum = new AD7ThreadEnum(Threads); + } + else + { + if (_currentThreadIndex != currentThread) + { + _currentThreadIndex = currentThread; + } + + for (int i = 0; i < listThreads.Length; i++) + { + if (Threads[i]._engine != listThreads[i]._engine) + { + Threads[i]._engine = listThreads[i]._engine; + } + if (Threads[i]._threadDisplayName != listThreads[i]._threadDisplayName) + { + Threads[i]._threadDisplayName = listThreads[i]._threadDisplayName; + } + if (Threads[i]._id != listThreads[i]._id) + { + Threads[i]._id = listThreads[i]._id; + } + if (Threads[i]._state != listThreads[i]._state) + { + Threads[i]._state = listThreads[i]._state; + } + if (Threads[i]._targetID != listThreads[i]._targetID) + { + Threads[i]._targetID = listThreads[i]._targetID; + } + if (Threads[i]._priority != listThreads[i]._priority) + { + Threads[i]._priority = listThreads[i]._priority; + } + if (Threads[i]._line != listThreads[i]._line) + { + Threads[i]._line = listThreads[i]._line; + } + if (Threads[i]._filename != listThreads[i]._filename) + { + if (listThreads[i]._filename == "") + Threads[i]._filename = ""; + else + Threads[i]._filename = listThreads[i]._filename; + } + Threads[i]._suspendCount = listThreads[i]._suspendCount; + } + + ppEnum = new AD7ThreadEnum(Threads); + } + return VSConstants.S_OK; + } + + /// + /// Gets the program's properties. The VSNDK debug engine does not support this. + /// (http://msdn.microsoft.com/en-us/library/bb161801.aspx) + /// + /// Returns an IDebugProperty2 object that represents the program's properties. + /// Not implemented. + public int GetDebugProperty(out IDebugProperty2 ppProperty) + { + throw new Exception("The method or operation is not implemented."); + } + + /// + /// Gets the disassembly stream for this program or a part of this program. + /// The sample engine does not support dissassembly so it returns E_NOTIMPL + /// + /// Specifies a value from the DISASSEMBLY_STREAM_SCOPE enumeration that defines the scope of the + /// disassembly stream. + /// An object that represents the position of where to start the disassembly stream. + /// Returns an IDebugDisassemblyStream2 object that represents the disassembly stream. + /// VSConstants.E_NOTIMPL. + public int GetDisassemblyStream(enum_DISASSEMBLY_STREAM_SCOPE dwScope, IDebugCodeContext2 codeContext, out IDebugDisassemblyStream2 disassemblyStream) + { + disassemblyStream = null; + return EngineUtils.NotImplemented(); + } + + /// + /// This method gets the Edit and Continue (ENC) update for this program. A custom debug engine always returns E_NOTIMPL + /// + /// Returns an internal interface that can be used to update this program. + /// VSConstants.S_OK. + public int GetENCUpdate(out object update) + { + // The VSNDK debug engine does not participate in managed edit & continue. + update = null; + return VSConstants.S_OK; + } + + /// + /// Gets the name and GUID of the debug engine running this program. (http://msdn.microsoft.com/en-us/library/bb145854.aspx) + /// + /// Returns the name of the DE running this program. + /// Returns the GUID of the DE running this program. + /// VSConstants.S_OK. + public int GetEngineInfo(out string engineName, out Guid engineGuid) + { + engineName = AD7PortSupplier.PublicName; + engineGuid = new Guid(DebugEngineGuid); + + return VSConstants.S_OK; + } + + /// + /// Retrieves the memory bytes occupied by the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145291.aspx) + /// + /// Returns an IDebugMemoryBytes2 object that represents the memory bytes of the program. + /// Not implemented. + public int GetMemoryBytes(out IDebugMemoryBytes2 ppMemoryBytes) + { + throw new Exception("The method or operation is not implemented."); + } + + /// + /// Gets the name of the program. The name returned by this method is always a friendly, user-displayable name that describes + /// the program. (http://msdn.microsoft.com/en-us/library/bb161279.aspx) + /// + /// Returns the name of the program. + /// VSConstants.S_OK. + public int GetName(out string programName) + { + if (_progNode != null) + programName = _progNode.Name; + else + programName = null; + return VSConstants.S_OK; + } + + /// + /// Gets a GUID for this program. A debug engine (DE) must return the program identifier originally passed to the + /// IDebugProgramNodeAttach2::OnAttach or IDebugEngine2::Attach methods. This allows identification of the program + /// across debugger components. (http://msdn.microsoft.com/en-us/library/bb145581.aspx) + /// + /// Returns the GUID for this program. + /// VSConstants.S_OK. + public int GetProgramId(out Guid guidProgramId) + { + guidProgramId = _programGuid; + return VSConstants.S_OK; + } + + /// + /// Performs a step. This method is deprecated. Use the IDebugProcess3::Step method instead. + /// (http://msdn.microsoft.com/en-us/library/bb162134.aspx) + /// + /// An IDebugThread2 object that represents the thread being stepped. + /// A value from the STEPKIND enumeration that specifies the kind of step. + /// A value from the STEPUNIT enumeration that specifies the unit of step. + /// If successful, returns S_OK; otherwise, returns an error code. + public int Step(IDebugThread2 thread, enum_STEPKIND kind, enum_STEPUNIT step) + { + // Don't allow stepping through unknown code because it can lead to future problems with stepping and break-all. + if (EventDispatcher._unknownCode) + { + State = AD7Engine.DebugEngineState.Step; + EventDispatcher.ContinueExecution(); + + return VSConstants.S_OK; + } + + if (kind == enum_STEPKIND.STEP_INTO) + { + // Equivalent to F11 hotkey. + // Sends the GDB command that resumes the execution of the inferior program, stopping at the next instruction, diving + // into function if it is a function call. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand("-exec-step --thread " + Threads[_currentThreadIndex]._id); + } + else if (kind == enum_STEPKIND.STEP_OVER) + { + // Equivalent to F10 hotkey. + // Sends the GDB command that resumes the execution of the inferior program, stopping at the next instruction, but + // without diving into functions. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand("-exec-next --thread " + Threads[_currentThreadIndex]._id); + } + else if (kind == enum_STEPKIND.STEP_OUT) + { + // Equivalent to Shift-F11 hotkey. + if (EventDispatcher.GetStackDepth(Threads[_currentThreadIndex]._id) > 1) + { + // Sends the GDB command that resumes the execution of the inferior program until the current function is exited. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand("-exec-finish --thread " + Threads[_currentThreadIndex]._id + " --frame 0"); + } + else + { + // If this the only frame left, do a step-over. + // Sends the GDB command that resumes the execution of the inferior program, stopping at the next instruction, but + // without diving into functions. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand("-exec-next --thread " + Threads[_currentThreadIndex]._id); + } + } + else if (kind == enum_STEPKIND.STEP_BACKWARDS) + { + return EngineUtils.NotImplemented(); + } + else + { + Callback.OnStepComplete(); // Have to call this otherwise VS gets "stuck" + } + + // Transition DE state + State = DebugEngineState.Step; + + return VSConstants.S_OK; + } + + /// + /// Terminates the program. (http://msdn.microsoft.com/en-us/library/bb145919.aspx) + /// + /// VSConstants.S_OK. + public int Terminate() + { + return VSConstants.S_OK; + } + + /// + /// Writes a dump to a file. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145827.aspx) + /// + /// A value from the DUMPTYPE enumeration that specifies the type of dump, for example, short or + /// long. + /// The URL to write the dump to. Typically, this is in the form of file://c:\path\filename.ext, + /// but may be any valid URL. + /// VSConstants.E_NOTIMPL. + public int WriteDump(enum_DUMPTYPE type, string dumpUrl) + { + // The VSNDK debugger does not support creating or reading mini-dumps. + return EngineUtils.NotImplemented(); + } + + #endregion + + #region IDebugProgram3 Members + + /// + /// Executes the debugger program. The thread is returned to give the debugger information on which thread the user is + /// viewing when executing the program. ExecuteOnThread is called when the SDM wants execution to continue and have + /// stepping state cleared. (http://msdn.microsoft.com/en-us/library/bb145596.aspx) + /// + /// An IDebugThread2 object. + /// VSConstants.S_OK. + public int ExecuteOnThread(IDebugThread2 thread) + { + EventDispatcher.ContinueExecution(); + + return VSConstants.S_OK; + } + + #endregion + + #region IDebugEngineProgram2 Members + + /// + /// Stops all threads running in this program. This method is called when this program is being debugged in a multi-program + /// environment. When a stopping event from some other program is received, this method is called on this program. The + /// implementation of this method should be asynchronous; that is, not all threads should be required to be stopped before + /// this method returns. The implementation of this method may be as simple as calling the IDebugProgram2::CauseBreak method + /// on this program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb146567.aspx) + /// + /// The VSNDK debug engine only supports debugging native applications and therefore only has one program per-process + /// + /// VSConstants.E_NOTIMPL. + public int Stop() + { + return EngineUtils.NotImplemented(); + } + + /// + /// Allows (or disallows) expression evaluation to occur on the given thread, even if the program has stopped. + /// WatchForExpressionEvaluationOnThread is used to cooperate between two different engines debugging the same process. + /// The VSNDK debug engine doesn't cooperate with other engines, so it has nothing to do here. + /// (http://msdn.microsoft.com/en-us/library/bb144913.aspx) + /// + /// An IDebugProgram2 object representing the program that is evaluating an expression. + /// Specifies the identifier of the thread. + /// A combination of flags from the EVALFLAGS enumeration that specify how the evaluation is to be performed. + /// An IDebugEventCallback2 object to be used to send debug events that occur during expression evaluation. + /// If non-zero (TRUE), allows expression evaluation on the thread identified by dwTid; otherwise, zero + /// (FALSE) disallows expression evaluation on that thread. + /// VSConstants.S_OK. + public int WatchForExpressionEvaluationOnThread(IDebugProgram2 program, uint threadID, uint flags, IDebugEventCallback2 callback, int canWatch) + { + return VSConstants.S_OK; + } + + /// + /// Watches for execution (or stops watching for execution) to occur on the given thread. WatchForThreadStep is used to + /// cooperate between two different engines debugging the same process. The VSNDK debug engine doesn't cooperate with other + /// engines, so it has nothing to do here. (http://msdn.microsoft.com/en-us/library/bb161406.aspx) + /// + /// An IDebugProgram2 object representing the program being stepped. + /// Specifies the identifier of the thread to watch. + /// Non-zero (TRUE) means start watching for execution on the thread identified by dwTid; otherwise, + /// zero (FALSE) means stop watching for execution on dwTid. + /// Specifies a frame index that controls the step type. + /// VSConstants.S_OK. + public int WatchForThreadStep(IDebugProgram2 program, uint dwTid, int canWatch, uint frame) + { + return VSConstants.S_OK; + } + + #endregion + + #region IDebugSymbolSettings100 members + + /// + /// The SDM will call this method on the debug engine when it is created, to notify it of the user's + /// symbol settings in Tools->Options->Debugging->Symbols. (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugsymbolsettings100.setsymbolloadstate.aspx) + /// + /// true if 'Automatically load symbols: Only for specified modules' is checked. + /// true if 'Specify modules'->'Always load symbols next to the modules' is checked. + /// semicolon-delimited list of modules when automatically loading 'Only specified modules' + /// semicolon-delimited list of modules when automatically loading 'All modules, unless excluded' + /// VSConstants.S_OK. + int IDebugSymbolSettings100.SetSymbolLoadState(int isManual, int loadAdjacent, string includeList, string excludeList) + { + return VSConstants.S_OK; + } + + #endregion + + #region Thread methods + + /// + /// Verify if the stack frame information specified by "flags" were already evaluated. + /// + /// Thread ID. + /// Specifies the information to verify about a stack frame object. + /// If successful, returns TRUE; otherwise, returns FALSE. + public bool EvaluatedTheseFlags(string threadId, enum_FRAMEINFO_FLAGS flags) + { + if (Threads != null) + { + int currentFlags = Convert.ToInt32(flags); + int i = 0; + // looking for the "threadId" thread. + for (; i < Threads.Length; i++) + { + if (Threads[i]._id == threadId) + break; + } + if (i < Threads.Length) + { + if (Threads[i]._alreadyEvaluated == currentFlags) + { + // This stack frame information were already evaluated. + return true; + } + else + { + // This stack frame information were not evaluated before. Modifying the _alreadyEvaluated flag. + Threads[i]._alreadyEvaluated = currentFlags; + } + } + } + return false; + } + + /// + /// Clean the "flags" data (_alreadyEvaluated) that are stored in each thread without resetting the stack frames. This operation + /// must be done whenever the stack frames for a given thread have to be evaluated, like when the user changes the current frame + /// or when he wants to investigate different threads in break mode, for example. + /// + public void CleanEvaluatedThreads() + { + if (Threads != null) + { + for (int i = 0; i < Threads.Length; i++) + { + Threads[i]._alreadyEvaluated = 0; + } + } + } + + /// + /// Reset stack frames for each thread. This operation must be performed before changing the state to break mode, like when a + /// breakpoint is hit, for example. + /// + public void ResetStackFrames() + { + if (Threads != null) + { + foreach (AD7Thread t in Threads) + { + if (t.__stackFrames != null) + { + t.__stackFrames.Clear(); + t.__stackFrames = null; + } + } + } + } + + /// + /// Update the list of threads. This operation must be performed whenever the list of threads changes (a thread exits or is + /// created) and before entering in break mode. + /// + public void UpdateListOfThreads() + { + if (Threads != null) + { + foreach (AD7Thread t in Threads) + { + // Send events to VS to destroy its current debugged threads. + AD7ThreadDestroyEvent.Send(this, 0, t); + } + + Threads = null; + } + + // Get the current list of threads and store them into a temporary variable listThreads. + AD7Thread[] threads; + _currentThreadIndex = GetListOfThreads(out threads); + Threads = threads; + + if (_currentThreadIndex == -1 || Threads == null) + return; + + // Send events to VS to add this list of debugged threads. + foreach (AD7Thread t in Threads) + { + Callback.OnThreadStart(t); + } + + _updateThreads = false; + } + + /// + /// Get the list of threads being debugged, also returning the index of the current thread (or -1 in case of error) + /// + /// Returns the current list of threads that are being debugged. + /// Returns the index of the current thread in the list of threads (or -1 in case of error) + private int GetListOfThreads(out AD7Thread[] threadObjects) + { + // Gets the parsed response for the GDB/MI command that ask for information about all threads. + // (http://www.sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html) + string threadResponse = GdbWrapper.SendCommand(@"-thread-info", 22); + string[] threadStrings = threadResponse.Split('#'); + CleanEvaluatedThreads(); + + // Query the threads depth without inquiring GDB. + int numThreads = threadStrings.Length - 1; // the last item in threadStrings is not a thread but the current thread ID. + string currentThread = threadStrings[threadStrings.Length - 1]; + if (numThreads < 1) + { + threadObjects = null; + return -1; + } + + try + { + threadObjects = new AD7Thread[numThreads]; + int currentThreadIndex = -1; + + for (int i = 0; i < numThreads; i++) + { + string[] threadInfo = threadStrings[i].Split(';'); + + // Setting the current thread index. + if (currentThread == threadInfo[0]) + { + currentThreadIndex = i; + } + + // Each threadInfo has one of these two formats: + // with 5 elements: ID; State; targetID; details (not used); name -> this format is normally used for external code. + // with 7 elements: ID; State; targetID; details (not used); full short-path filename; line; name + if (threadInfo.Length > 5) + threadObjects[i] = new AD7Thread(this, threadInfo[0], threadInfo[2], threadInfo[1], "Normal", threadInfo[6], threadInfo[4], threadInfo[5]); + else + threadObjects[i] = new AD7Thread(this, threadInfo[0], threadInfo[2], threadInfo[1], "Normal", threadInfo[4], "", ""); + } + return currentThreadIndex; + } + catch (Exception) + { + threadObjects = null; + return -1; + } + } + + /// + /// Returns the current thread. + /// + /// If successful, returns the current thread; otherwise, returns NULL. + public AD7Thread CurrentThread() + { + if (_currentThreadIndex != -1) + return Threads[_currentThreadIndex]; + return null; + } + + /// + /// Returns the thread data structure with a given ID. + /// + /// The ID of the thread to search for. + /// If successful, returns the selected thread; otherwise, returns NULL. + public AD7Thread SelectThread(string id) + { + if (Threads == null) + return null; + + for (int i = 0; i < Threads.Length; i++) + { + if (Threads[i]._id == id) + return Threads[i]; + } + return null; + } + + /// + /// Set a given thread as the current one. + /// + /// The ID of the thread. + public void SetAsCurrentThread(string id) + { + if (Threads != null) + { + for (int i = 0; i < Threads.Length; i++) + { + if (Threads[i]._id == id) + { + _currentThreadIndex = i; + break; + } + } + } + } + + /// + /// Add threads for a program when launching it and the debugger (IDebugEngineLaunch2.LaunchSuspended). + /// + /// VSConstants.S_OK. + public int AddThreadsToProgram() + { + AD7Thread[] threads; + Threads = null; + + _currentThreadIndex = GetListOfThreads(out threads); + Threads = threads; + + if (_currentThreadIndex != -1) + { + foreach (AD7Thread t in threads) + { + Callback.OnThreadStart(t); + } + } + else + { + Callback.OnThreadStart(null); + } + return VSConstants.S_OK; + } + + #endregion + + #region Deprecated interface methods + // These methods are not called by the Visual Studio debugger, so they don't need to be implemented + + /// + /// Retrieves a list of all programs being debugged by a debug engine (DE). Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb146175.aspx) + /// + /// Returns an object that contains a list of all programs being debugged by a DE. + /// VSConstants.E_NOTIMPL. + int IDebugEngine2.EnumPrograms(out IEnumDebugPrograms2 pPrograms) + { + pPrograms = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Attaches to the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb161973.aspx) + /// + /// An IDebugEventCallback2 object to be used for debug event notification. + /// VSConstants.E_NOTIMPL. + public int Attach(IDebugEventCallback2 callback) + { + return EngineUtils.NotImplemented(); + } + + /// + /// Get the process that this program is running in. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145293.aspx) + /// + /// Returns the IDebugProcess2 interface that represents the process. + /// VSConstants.E_NOTIMPL. + public int GetProcess(out IDebugProcess2 pProcess) + { + pProcess = null; + return EngineUtils.NotImplemented(); + } + + /// TODO: Verify if this method is called or not by VS. + /// Continues running this program from a stopped state. Any previous execution state (such as a step) is cleared, and the + /// program starts executing again. (http://msdn.microsoft.com/en-us/library/bb162315.aspx) + /// + /// VSConstants.S_OK. + public int Execute() + { + EventDispatcher.ContinueExecution(); + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Enums.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Enums.cs new file mode 100644 index 00000000..ad7efb0e --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Enums.cs @@ -0,0 +1,396 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + #region Base Class + + /// + /// These classes use a generic enumerator implementation to create the various enumerators required by the engine. + /// They allow the enumeration of everything from programs to breakpoints. + /// + /// Array of T elements. + /// Enumerator interface. + class AD7Enum where I: class + { + private readonly T[] _data; + private uint _position; + + /// + /// Constructor. + /// + /// Array of T elements. + public AD7Enum(T[] data) + { +#if DEBUG + if (data == null) + throw new ArgumentNullException("data"); +#endif + + _data = data; + _position = 0; + } + + /// + /// Returns a copy of the current enumeration as a separate object. Not implemented. + /// + /// Returns a copy of this enumeration as a separate object. + /// Not implemented. + public int Clone(out I ppEnum) + { + ppEnum = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Returns the number of elements in the enumeration. + /// + /// Returns the number of elements in the enumeration. + /// VSConstants.S_OK. + public int GetCount(out uint pcelt) + { + pcelt = (uint)_data.Length; + return VSConstants.S_OK; + } + + /// + /// Returns the next set of elements from the enumeration. + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of T elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, T[] rgelt, out uint celtFetched) + { + return Move(celt, rgelt, out celtFetched); + } + + /// + /// Resets the enumeration to the first element. + /// + /// VSConstants.S_OK. + public int Reset() + { + lock (this) + { + _position = 0; + + return VSConstants.S_OK; + } + } + + /// + /// Skips over the specified number of elements. + /// + /// Number of elements to skip. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Skip(uint celt) + { + uint celtFetched; + + return Move(celt, null, out celtFetched); + } + + /// + /// Returns/Skips over the specified number of elements. + /// + /// Number of elements to retrieve/skip. + /// Array of T elements to be filled in. + /// Returns the number of elements actually returned/skipped in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + private int Move(uint celt, T[] rgelt, out uint celtFetched) + { + lock (this) + { + int hr = VSConstants.S_OK; + celtFetched = (uint)_data.Length - _position; + + if (celt > celtFetched) + { + hr = VSConstants.S_FALSE; + } + else if (celt < celtFetched) + { + celtFetched = celt; + } + + if (rgelt != null) + { + for (int c = 0; c < celtFetched; c++) + { + rgelt[c] = _data[_position + c]; + } + } + + _position += celtFetched; + + return hr; + } + } + } + + #endregion + + /// + /// This class enumerates the processes running on a debug port. (http://msdn.microsoft.com/en-ca/library/bb145005.aspx) + /// + sealed class AD7ProcessEnum : AD7Enum, IEnumDebugProcesses2 + { + /// + /// Constructor. + /// + /// Array of IDebugProcess2 elements. + public AD7ProcessEnum(IDebugProcess2[] data) + : base(data) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb147027.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of IDebugProcess2 elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, IDebugProcess2[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } + + /// + /// This class enumerates the ports of a machine or port supplier. (http://msdn.microsoft.com/en-ca/library/bb145137.aspx) + /// + sealed class AD7PortEnum : AD7Enum, IEnumDebugPorts2 + { + /// + /// Constructor. + /// + /// Array of IDebugPort2 elements. + public AD7PortEnum(IDebugPort2[] data) + : base(data) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb147027.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of IDebugPort2 elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, IDebugPort2[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } + + /// + /// This class enumerates the programs running in the current debug session. (http://msdn.microsoft.com/en-ca/library/bb146727.aspx) + /// + sealed class AD7ProgramEnum : AD7Enum, IEnumDebugPrograms2 + { + /// + /// Constructor. + /// + /// Array of IDebugProgram2 elements. + public AD7ProgramEnum(IDebugProgram2[] data) + : base(data) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb147027.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of IDebugProgram2 elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, IDebugProgram2[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } + + /// + /// This class enumerates FRAMEINFO structures. (http://msdn.microsoft.com/en-us/library/bb147119.aspx) + /// + sealed class AD7FrameInfoEnum : AD7Enum, IEnumDebugFrameInfo2 + { + /// + /// Constructor. + /// + /// Array of FRAMEINFO elements. + public AD7FrameInfoEnum(FRAMEINFO[] data) + : base(data) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-us/library/bb146293.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of FRAMEINFO elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, FRAMEINFO[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } + + /// + /// This class enumerates DEBUG_PROPERTY_INFO structures. (http://msdn.microsoft.com/en-ca/library/bb162336.aspx) + /// + sealed class AD7PropertyInfoEnum : AD7Enum, IEnumDebugPropertyInfo2 + { + /// + /// Constructor. + /// + /// Array of DEBUG_PROPERTY_INFO elements. + public AD7PropertyInfoEnum(DEBUG_PROPERTY_INFO[] data) + : base(data) + { + } + } + + /// + /// This class enumerates the threads running in the current debug session. (http://msdn.microsoft.com/en-ca/library/bb145142.aspx) + /// + sealed class AD7ThreadEnum : AD7Enum, IEnumDebugThreads2 + { + /// + /// Constructor. + /// + /// Array of IDebugThread2 elements. + public AD7ThreadEnum(IDebugThread2[] threads) + : base(threads) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb161679.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of IDebugThread2 elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, IDebugThread2[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } + + /// + /// This class enumerates a list of modules. (http://msdn.microsoft.com/en-ca/library/bb145925.aspx) + /// + sealed class AD7ModuleEnum : AD7Enum, IEnumDebugModules2 + { + /// + /// Constructor. + /// + /// Array of IDebugModule2 elements. + public AD7ModuleEnum(IDebugModule2[] modules) + : base(modules) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb145898.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of IDebugModule2 elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, IDebugModule2[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } + + /// + /// This class enumerates DEBUG_PROPERTY_INFO structures. (http://msdn.microsoft.com/en-ca/library/bb162336.aspx) + /// + sealed class AD7PropertyEnum : AD7Enum, IEnumDebugPropertyInfo2 + { + /// + /// Constructor. + /// + /// Array of DEBUG_PROPERTY_INFO elements. + public AD7PropertyEnum(DEBUG_PROPERTY_INFO[] properties) + : base(properties) + { + } + } + + /// + /// This class enumerates the code contexts associated with the debug session, or with a particular program or document. + /// (http://msdn.microsoft.com/en-us/library/bb146612.aspx) + /// + sealed class AD7CodeContextEnum : AD7Enum, IEnumDebugCodeContexts2 + { + /// + /// Constructor. + /// + /// Array of IDebugCodeContext2 elements. + public AD7CodeContextEnum(IDebugCodeContext2[] codeContexts) + : base(codeContexts) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-us/library/bb145085.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of IDebugCodeContext2 elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, IDebugCodeContext2[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } + + /// + /// This class enumerates the bound breakpoints associated with a pending breakpoint or breakpoint bound event. + /// (http://msdn.microsoft.com/en-ca/library/bb162182.aspx) + /// + sealed class AD7BoundBreakpointsEnum : AD7Enum, IEnumDebugBoundBreakpoints2 + { + /// + /// Constructor. + /// + /// Array of IDebugBoundBreakpoint2 elements. + public AD7BoundBreakpointsEnum(IDebugBoundBreakpoint2[] breakpoints) + : base(breakpoints) + { + } + + /// + /// Returns the next set of elements from the enumeration. (http://msdn.microsoft.com/en-ca/library/bb161772.aspx) + /// + /// The number of elements to retrieve. Also specifies the maximum size of the rgelt array. + /// Array of IDebugBoundBreakpoint2 elements to be filled in. + /// Returns the number of elements actually returned in rgelt. + /// If successful, returns S_OK. If not, returns S_FALSE. + public int Next(uint celt, IDebugBoundBreakpoint2[] rgelt, ref uint celtFetched) + { + return Next(celt, rgelt, out celtFetched); + } + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7ErrorBreakpointResolution.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7ErrorBreakpointResolution.cs new file mode 100644 index 00000000..12249acd --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7ErrorBreakpointResolution.cs @@ -0,0 +1,42 @@ +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// Represents the resolution of a breakpoint error. (http://msdn.microsoft.com/en-us/library/bb161341.aspx) + /// + class AD7ErrorBreakpointResolution : IDebugErrorBreakpointResolution2 + { + #region IDebugErrorBreakpointResolution2 Members + + /// + /// Gets the breakpoint type. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145065.aspx) + /// + /// The type of this breakpoint. + /// Not implemented. + int IDebugErrorBreakpointResolution2.GetBreakpointType(enum_BP_TYPE[] pBPType) + { + return EngineUtils.NotImplemented(); + } + + /// + /// Gets the breakpoint error resolution information. Not implemented. (http://msdn.microsoft.com/en-us/library/bb161960.aspx) + /// + /// A combination of flags that determine which fields of pErrorResolutionInfo are to be filled out. + /// The BP_ERROR_RESOLUTION_INFO structure that is filled in with the description of the + /// breakpoint resolution. + /// Not implemented. + int IDebugErrorBreakpointResolution2.GetResolutionInfo(enum_BPERESI_FIELDS dwFields, BP_ERROR_RESOLUTION_INFO[] pErrorResolutionInfo) + { + if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_BPRESLOCATION) != 0) { } + if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_PROGRAM) != 0) { } + if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_THREAD) != 0) { } + if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_MESSAGE) != 0) { } + if (((uint)dwFields & (uint)enum_BPERESI_FIELDS.BPERESI_TYPE) != 0) { } + + return EngineUtils.NotImplemented(); + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Events.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Events.cs new file mode 100644 index 00000000..b91313b7 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Events.cs @@ -0,0 +1,685 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +// This file contains the various event objects that are sent to the debugger from the VSNDK debug engine via IDebugEventCallback2::Event. +// These are used in EngineCallback.cs. +// The events are how the engine tells the debugger about what is happening in the debuggee process. +// There are four base classes the other events derive from: AD7AsynchronousEvent, AD7StoppingEvent, AD7SynchronousEvent and +// AD7SynchronousStoppingEvent. Each of them implements the IDebugEvent2.GetAttributes method for the type of event they represent. +// Most events sent by the debugger are asynchronous ones. + +namespace BlackBerry.DebugEngine +{ + #region Event Base Classes + + /// + /// Used to communicate both critical debug information and non-critical information. + /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) + /// + class AD7AsynchronousEvent : IDebugEvent2 + { + private const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS; + + /// + /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) + /// + /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. + /// VSConstants.S_OK. + int IDebugEvent2.GetAttributes(out uint eventAttributes) + { + eventAttributes = Attributes; + return VSConstants.S_OK; + } + } + + /// + /// Used to communicate both critical debug information and non-critical information. + /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) + /// + class AD7StoppingEvent : IDebugEvent2 + { + public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_ASYNC_STOP; + + /// + /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) + /// + /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. + /// VSConstants.S_OK. + int IDebugEvent2.GetAttributes(out uint eventAttributes) + { + eventAttributes = Attributes; + return VSConstants.S_OK; + } + } + + /// + /// Used to communicate both critical debug information and non-critical information. + /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) + /// + class AD7SynchronousEvent : IDebugEvent2 + { + public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; + + /// + /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) + /// + /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. + /// VSConstants.S_OK. + int IDebugEvent2.GetAttributes(out uint eventAttributes) + { + eventAttributes = Attributes; + return VSConstants.S_OK; + } + } + + /// + /// Used to communicate both critical debug information and non-critical information. + /// (http://msdn.microsoft.com/en-us/library/bb161977.aspx) + /// + class AD7SynchronousStoppingEvent : IDebugEvent2 + { + public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_STOPPING | (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; + + /// + /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) + /// + /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. + /// VSConstants.S_OK. + int IDebugEvent2.GetAttributes(out uint eventAttributes) + { + eventAttributes = Attributes; + return VSConstants.S_OK; + } + } + + #endregion + + /// + /// The debug engine (DE) sends this interface to the session debug manager (SDM) when an instance of the DE is created. + /// (http://msdn.microsoft.com/en-us/library/bb145830.aspx) + /// + sealed class AD7EngineCreateEvent : AD7AsynchronousEvent, IDebugEngineCreateEvent2 + { + public const string IID = "FE5B734C-759D-4E59-AB04-F103343BDD06"; + + private readonly IDebugEngine2 _engine; + + /// + /// Constructor. + /// + /// The AD7Engine object that represents the DE. + AD7EngineCreateEvent(AD7Engine engine) + { + _engine = engine; + } + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + public static void Send(AD7Engine engine) + { + AD7EngineCreateEvent eventObject = new AD7EngineCreateEvent(engine); + engine.Callback.Send(eventObject, IID, null, null); + } + + /// + /// Retrieves the object that represents the newly created debug engine (DE). + /// (http://msdn.microsoft.com/en-us/library/bb145143.aspx) + /// + /// Returns an AD7Engine object that represents the newly created DE. + /// VSConstants.S_OK. + int IDebugEngineCreateEvent2.GetEngine(out IDebugEngine2 engine) + { + engine = _engine; + return VSConstants.S_OK; + } + } + + /// + /// This interface is sent when a process is launched. (http://msdn.microsoft.com/en-ca/library/bb161755.aspx) + /// + sealed class AD7ProcessCreateEvent : IDebugEvent2, IDebugProcessCreateEvent2 + { + public const string IID = "9020DEE3-362D-4FF2-8CA9-8F6791F0EC85"; + public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_IMMEDIATE; + + /// + /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) + /// + /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. + /// VSConstants.S_OK. + int IDebugEvent2.GetAttributes(out uint eventAttributes) + { + eventAttributes = Attributes; + return VSConstants.S_OK; + } + } + + /// + /// This interface is sent when a process is terminated, exits atypically, or is detached from. + /// (http://msdn.microsoft.com/en-us/library/bb145152.aspx) + /// + sealed class AD7ProcessDestroyEvent : IDebugEvent2, IDebugProcessDestroyEvent2 + { + public const string IID = "29DAA0AC-C718-4F93-A11E-6D15681476C7"; + public const uint Attributes = (uint)enum_EVENTATTRIBUTES.EVENT_IMMEDIATE; + + /// + /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) + /// + /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. + /// VSConstants.S_OK. + int IDebugEvent2.GetAttributes(out uint eventAttributes) + { + eventAttributes = Attributes; + return VSConstants.S_OK; + } + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program is attached to. + /// (http://msdn.microsoft.com/en-ca/library/bb161345.aspx) + /// + sealed class AD7ProgramCreateEvent : AD7AsynchronousEvent, IDebugProgramCreateEvent2 + { + public const string IID = "96CD11EE-ECD4-4E89-957E-B5D496FC4139"; + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + internal static void Send(AD7Engine engine) + { + AD7ProgramCreateEvent eventObject = new AD7ProgramCreateEvent(); + engine.Callback.Send(eventObject, IID, null); + } + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when asynchronous expression evaluation + /// is complete. (http://msdn.microsoft.com/en-ca/library/bb161810.aspx) + /// + sealed class AD7ExpressionEvaluationCompleteEvent : AD7AsynchronousEvent, IDebugExpressionEvaluationCompleteEvent2 + { + public const string IID = "C0E13A85-238A-4800-8315-D947C960A843"; + + private readonly IDebugExpression2 _expression; + private readonly IDebugProperty2 _property; + + /// + /// Constructor. + /// + /// The IDebugExpression2 object that represents the expression. + /// The IDebugProperty2 object that represents the result of the expression evaluation. + public AD7ExpressionEvaluationCompleteEvent(IDebugExpression2 expression, IDebugProperty2 property) + { + _expression = expression; + _property = property; + } + + /// + /// Gets the original expression. (http://msdn.microsoft.com/en-ca/library/bb162323.aspx) + /// + /// Returns an IDebugExpression2 object that represents the expression that was parsed. + /// VSConstants.S_OK. + public int GetExpression(out IDebugExpression2 ppExpr) + { + ppExpr = _expression; + return VSConstants.S_OK; + } + + /// + /// Gets the result of expression evaluation. (http://msdn.microsoft.com/en-ca/library/bb161962.aspx) + /// + /// Returns an IDebugProperty2 object that represents the result of the expression evaluation. + /// VSConstants.S_OK. + public int GetResult(out IDebugProperty2 ppResult) + { + ppResult = _property; + return _property != null ? VSConstants.S_OK : VSConstants.E_FAIL; + } + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a module is loaded or unloaded. + /// (http://msdn.microsoft.com/en-ca/library/bb146706.aspx) + /// + sealed class AD7ModuleLoadEvent : AD7AsynchronousEvent, IDebugModuleLoadEvent2 + { + public const string IID = "989DB083-0D7C-40D1-A9D9-921BF611A4B2"; + + private readonly AD7Module _module; + private readonly bool _isLoad; + + /// + /// Constructor. + /// + /// The IDebugModule2 object that represents the module which is loading or unloading. + /// onzero (TRUE) if the module is loading and zero (FALSE) if the module is unloading. + public AD7ModuleLoadEvent(AD7Module module, bool isLoad) + { + _module = module; + _isLoad = isLoad; + } + + /// + /// Gets the module that is being loaded or unloaded. (http://msdn.microsoft.com/en-ca/library/bb161763.aspx) + /// + /// Returns an IDebugModule2 object that represents the module which is loading or unloading. + /// Returns an optional message describing this event. If this parameter is a null value, no message + /// is requested. + /// Nonzero (TRUE) if the module is loading and zero (FALSE) if the module is unloading. If this + /// parameter is a null value, no status is requested. + /// VSConstants.S_OK. + int IDebugModuleLoadEvent2.GetModule(out IDebugModule2 module, ref string debugMessage, ref int isLoad) + { + module = _module; + isLoad = _isLoad ? 1 : 0; + return VSConstants.S_OK; + } + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + /// The IDebugModule2 object that represents the module which is loading or unloading. + /// onzero (TRUE) if the module is loading and zero (FALSE) if the module is unloading. + internal static void Send(AD7Engine engine, AD7Module module, bool isLoad) + { + var eventObject = new AD7ModuleLoadEvent(module, isLoad); + engine.Callback.Send(eventObject, IID, null); + } + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program has run to completion + /// or is otherwise destroyed. (http://msdn.microsoft.com/en-ca/library/bb161972.aspx) + /// + sealed class AD7ProgramDestroyEvent : AD7SynchronousEvent, IDebugProgramDestroyEvent2 + { + public const string IID = "E147E9E3-6440-4073-A7B7-A65592C714B5"; + + private readonly uint _exitCode; + + /// + /// Constructor. + /// + /// The program's exit code. + public AD7ProgramDestroyEvent(uint exitCode) + { + _exitCode = exitCode; + } + + #region IDebugProgramDestroyEvent2 Members + + /// + /// Gets the program's exit code. (http://msdn.microsoft.com/en-ca/library/bb146724.aspx) + /// + /// Returns the program's exit code. + /// VSConstants.S_OK. + int IDebugProgramDestroyEvent2.GetExitCode(out uint exitCode) + { + exitCode = _exitCode; + return VSConstants.S_OK; + } + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + /// The program's exit code. + internal static void Send(AD7Engine engine, uint exitCode) + { + var eventObject = new AD7ProgramDestroyEvent(exitCode); + engine.Callback.Send(eventObject, IID, null); + } + + #endregion + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a thread is created in a program + /// being debugged. (http://msdn.microsoft.com/en-ca/library/bb161327.aspx) + /// + sealed class AD7ThreadCreateEvent : AD7AsynchronousEvent, IDebugThreadCreateEvent2 + { + public const string IID = "2090CCFC-70C5-491D-A5E8-BAD2DD9EE3EA"; + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a thread has run to completion. + /// (http://msdn.microsoft.com/en-ca/library/bb162330.aspx) + /// + sealed class AD7ThreadDestroyEvent : AD7AsynchronousEvent, IDebugThreadDestroyEvent2 + { + public const string IID = "2C3B7532-A36F-4A6E-9072-49BE649B8541"; + + private readonly uint _exitCode; + + /// + /// Constructor. + /// + /// The thread's exit code. + public AD7ThreadDestroyEvent(uint exitCode) + { + _exitCode = exitCode; + } + + #region IDebugThreadDestroyEvent2 Members + + /// + /// Gets the exit code for a thread. (http://msdn.microsoft.com/en-ca/library/bb146996.aspx) + /// + /// Returns the thread's exit code. + /// VSConstants.S_OK. + int IDebugThreadDestroyEvent2.GetExitCode(out uint exitCode) + { + exitCode = _exitCode; + return VSConstants.S_OK; + } + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + /// The thread's exit code. + /// The AD7Thread object that represents the thread. + internal static void Send(AD7Engine engine, uint exitCode, AD7Thread thread) + { + var eventObject = new AD7ThreadDestroyEvent(exitCode); + if (thread == null) + { + foreach (AD7Thread t in engine.Threads) + { + engine.Callback.Send(eventObject, IID, t); + } + engine._currentThreadIndex = -1; + } + else + { + engine.Callback.Send(eventObject, IID, thread); + } + } + + #endregion + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program is loaded, but before + /// any code is executed. (http://msdn.microsoft.com/en-ca/library/bb145834.aspx) + /// + sealed class AD7LoadCompleteEvent : AD7StoppingEvent, IDebugLoadCompleteEvent2 + { + public const string IID = "B1844850-1349-45D4-9F12-495212F5EB0B"; + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + /// The AD7Thread object that represents the thread. + internal static void Send(AD7Engine engine, AD7Thread thread) + { + if (thread == null) + throw new ArgumentNullException("thread"); + + var message = new AD7LoadCompleteEvent(); + engine.Callback.Send(message, IID, thread); + } + } + + /// + /// This interface tells the session debug manager (SDM) that an asynchronous break has been successfully completed. + /// (http://msdn.microsoft.com/en-ca/library/bb146180.aspx) + /// + sealed class AD7AsyncBreakCompleteEvent : AD7StoppingEvent, IDebugBreakEvent2 + { + public const string IID = "c7405d1d-e24b-44e0-b707-d8a5a4e1641b"; + } + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) to output a string. + /// (http://msdn.microsoft.com/en-ca/library/bb146756.aspx) + /// + sealed class AD7OutputDebugStringEvent : AD7AsynchronousEvent, IDebugOutputStringEvent2 + { + public const string IID = "569c4bb1-7b82-46fc-ae28-4536ddad753e"; + + private readonly string _message; + + /// + /// Constructor. + /// + /// The displayable message. + public AD7OutputDebugStringEvent(string message) + { + _message = message; + } + + #region IDebugOutputStringEvent2 Members + + /// + /// Gets the displayable message. (http://msdn.microsoft.com/en-ca/library/bb162293.aspx) + /// + /// Returns the displayable message. + /// VSConstants.S_OK. + int IDebugOutputStringEvent2.GetString(out string pbstrString) + { + pbstrString = _message; + return VSConstants.S_OK; + } + + #endregion + } + + /// + /// This interface is sent by the debug engine (DE) to indicate that the debugging symbols for a module being debugged have + /// been loaded. (http://msdn.microsoft.com/en-ca/library/bb160924.aspx) + /// + sealed class AD7SymbolSearchEvent : AD7AsynchronousEvent, IDebugSymbolSearchEvent2 + { + public const string IID = "638F7C54-C160-4c7b-B2D0-E0337BC61F8C"; + + private readonly AD7Module _module; + private readonly string _searchInfo; + private readonly uint _symbolFlags; + + /// + /// Constructor. + /// + /// The AD7Module object representing the module for which the symbols were loaded. + /// The string containing any error messages from the module. + /// A combination of flags from the MODULE_INFO_FLAGS enumeration indicating whether any + /// symbols were loaded. + public AD7SymbolSearchEvent(AD7Module module, string searchInfo, uint symbolFlags) + { + _module = module; + _searchInfo = searchInfo; + _symbolFlags = symbolFlags; + } + + #region IDebugSymbolSearchEvent2 Members + + /// + /// Called by an event handler to retrieve results about a symbol load process. + /// (http://msdn.microsoft.com/en-ca/library/bb161324.aspx) + /// + /// An IDebugModule3 object representing the module for which the symbols were loaded. + /// Returns a string containing any error messages from the module. If there is no error, + /// then this string will just contain the module's name but it is never empty. + /// A combination of flags from the MODULE_INFO_FLAGS enumeration indicating whether any + /// symbols were loaded. + /// VSConstants.S_OK. + int IDebugSymbolSearchEvent2.GetSymbolSearchInfo(out IDebugModule3 pModule, ref string pbstrDebugMessage, enum_MODULE_INFO_FLAGS[] pdwModuleInfoFlags) + { + pModule = _module; + pbstrDebugMessage = _searchInfo; + pdwModuleInfoFlags[0] = (enum_MODULE_INFO_FLAGS)_symbolFlags; + + return VSConstants.S_OK; + } + + #endregion + } + + /// + /// This interface tells the session debug manager (SDM) that a pending breakpoint has been successfully bound to a loaded program. + /// (http://msdn.microsoft.com/en-us/library/bb145356.aspx) + /// + sealed class AD7BreakpointBoundEvent : AD7AsynchronousEvent, IDebugBreakpointBoundEvent2 + { + public const string IID = "1dddb704-cf99-4b8a-b746-dabb01dd13a0"; + + private readonly AD7PendingBreakpoint _pendingBreakpoint; + private readonly AD7BoundBreakpoint _boundBreakpoint; + + /// + /// Constructor. + /// + /// The AD7PendingBreakpoint object that represents the pending breakpoint being bound. + /// The AD7BoundBreakpoint object that represents the breakpoint being bound. + public AD7BreakpointBoundEvent(AD7PendingBreakpoint pendingBreakpoint, AD7BoundBreakpoint boundBreakpoint) + { + _pendingBreakpoint = pendingBreakpoint; + _boundBreakpoint = boundBreakpoint; + } + + #region IDebugBreakpointBoundEvent2 Members + + /// + /// Creates an enumerator of breakpoints that were bound on this event. (http://msdn.microsoft.com/en-us/library/bb145322.aspx) + /// + /// Returns an IEnumDebugBoundBreakpoints2 object that enumerates all the breakpoints bound from + /// this event. + /// VSConstants.S_OK. + int IDebugBreakpointBoundEvent2.EnumBoundBreakpoints(out IEnumDebugBoundBreakpoints2 ppEnum) + { + IDebugBoundBreakpoint2[] boundBreakpoints = new IDebugBoundBreakpoint2[1]; + boundBreakpoints[0] = _boundBreakpoint; + ppEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); + return VSConstants.S_OK; + } + + /// + /// Gets the pending breakpoint that is being bound. (http://msdn.microsoft.com/en-us/library/bb146558.aspx) + /// + /// Returns the IDebugPendingBreakpoint2 object that represents the pending breakpoint being + /// bound. + /// VSConstants.S_OK. + int IDebugBreakpointBoundEvent2.GetPendingBreakpoint(out IDebugPendingBreakpoint2 ppPendingBP) + { + ppPendingBP = _pendingBreakpoint; + return VSConstants.S_OK; + } + + #endregion + } + + /// + /// The debug engine (DE) sends this interface to the session debug manager (SDM) when a program stops at a breakpoint. + /// (http://msdn.microsoft.com/en-us/library/bb145927.aspx) + /// + sealed class AD7BreakpointEvent : AD7StoppingEvent, IDebugBreakpointEvent2 + { + public const string IID = "501C1E21-C557-48B8-BA30-A1EAB0BC4A74"; + + private readonly IEnumDebugBoundBreakpoints2 _boundBreakpoints; + + /// + /// Constructor. + /// + /// The IEnumDebugBoundBreakpoints2 object that enumerates all the breakpoints associated with + /// the current code location. + public AD7BreakpointEvent(IEnumDebugBoundBreakpoints2 boundBreakpoints) + { + _boundBreakpoints = boundBreakpoints; + } + + #region IDebugBreakpointEvent2 Members + + /// + /// Creates an enumerator for all the breakpoints that fired at the current code location. + /// (http://msdn.microsoft.com/en-us/library/bb146247.aspx) + /// + /// Returns an IEnumDebugBoundBreakpoints2 object that enumerates all the breakpoints associated with + /// the current code location. + /// VSConstants.S_OK. + int IDebugBreakpointEvent2.EnumBreakpoints(out IEnumDebugBoundBreakpoints2 ppEnum) + { + ppEnum = _boundBreakpoints; + return VSConstants.S_OK; + } + + #endregion + } + + + /// + /// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when the program being debugged completes + /// a step into, a step over, or a step out of a line of source code or statement or instruction. + /// (http://msdn.microsoft.com/en-us/library/bb162189.aspx) + /// + sealed class AD7StepCompletedEvent : IDebugEvent2, IDebugStepCompleteEvent2 + { + public const string IID = "0F7F24C1-74D9-4EA6-A3EA-7EDB2D81441D"; + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + public static void Send(AD7Engine engine) + { + var eventObject = new AD7StepCompletedEvent(); + engine.Callback.Send(eventObject, IID, engine.CurrentThread()); + } + + #region IDebugEvent2 Members + + /// + /// Gets the attributes for this debug event. (http://msdn.microsoft.com/en-us/library/bb145575.aspx) + /// + /// A combination of flags from the enum_EVENTATTRIBUTES enumeration. + /// VSConstants.S_OK. + public int GetAttributes(out uint pdwAttributes) + { + pdwAttributes = (uint)(enum_EVENTATTRIBUTES.EVENT_ASYNC_STOP); + return VSConstants.S_OK; + } + + #endregion + } + + /// + /// The debug engine (DE) sends this interface to the session debug manager (SDM) when the program is about to execute its + /// first instruction of user code. (http://msdn.microsoft.com/en-us/library/bb161265.aspx) + /// + sealed class AD7EntryPointEvent : AD7SynchronousStoppingEvent, IDebugEntryPointEvent2 + { + public const string IID = "86D5A99E-C721-4625-A401-4D052DF38475"; + + /// + /// Sends the event. + /// + /// The AD7Engine object that represents the DE. + public static void Send(AD7Engine engine) + { + var eventObject = new AD7EntryPointEvent(); + engine.Callback.Send(eventObject, IID, engine.CurrentThread()); + } + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Expression.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Expression.cs new file mode 100644 index 00000000..be94a18e --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Expression.cs @@ -0,0 +1,139 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.NativeCore.Diagnostics; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents a parsed expression ready for binding and evaluating. + /// It is returned as a result of a successful call to IDebugExpressionContext2.ParseText + /// It allows the debugger to obtain the values of an expression in the debuggee. + /// (http://msdn.microsoft.com/en-ca/library/bb162308.aspx) + /// + public sealed class AD7Expression : IDebugExpression2 + { + /// + /// The expression to be evaluated. + /// + private readonly string _expression; + + /// + /// The class that manages debug events for the debug engine. + /// + private readonly EventDispatcher _eventDispatcher; + + /// + /// Current stack frame. + /// + private readonly AD7StackFrame _frame; + + /// + /// Constructor. + /// + /// The expression to be evaluated. + /// Current stack frame. + /// Represents the class that manages debug events for the debug engine. + public AD7Expression(string expression, AD7StackFrame frame, EventDispatcher dispatcher) + { + _expression = expression; + _eventDispatcher = dispatcher; + _frame = frame; + } + + #region IDebugExpression2 Members + + /// + /// This method cancels asynchronous expression evaluation as started by a call to the IDebugExpression2::EvaluateAsync method. + /// Not implemented yet because it was not needed yet. (http://msdn.microsoft.com/en-ca/library/bb145924.aspx) + /// + /// Not implemented. + int IDebugExpression2.Abort() + { + return EngineUtils.NotImplemented(); + } + + /// + /// Thread responsible for evaluating expressions asynchronously. + /// + public void EvaluatingAsync() + { + try + { + VariableInfo vi = VariableInfo.Get(_expression, _eventDispatcher, _frame); + AD7Property ppResult = new AD7Property(vi); + + _frame._engine.Callback.Send(new AD7ExpressionEvaluationCompleteEvent(this, ppResult), AD7ExpressionEvaluationCompleteEvent.IID, _frame._engine, _frame._thread); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to evaluate expression value"); + _frame._engine.Callback.Send(new AD7ExpressionEvaluationCompleteEvent(this, null), AD7ExpressionEvaluationCompleteEvent.IID, _frame._engine, _frame._thread); + } + } + + private void EvaluateAsyncCompleted(IAsyncResult ar) + { + // release async-call system resources: + var action = (Action) ar.AsyncState; + action.EndInvoke(ar); + } + + /// + /// This method evaluates the expression asynchronously. + /// This is primarily used for the immediate window. (http://msdn.microsoft.com/en-ca/library/bb146752.aspx) + /// + /// A combination of flags from the EVALFLAGS enumeration that control expression evaluation. + /// This parameter is always a null value. + /// VSConstants.S_OK. + int IDebugExpression2.EvaluateAsync(enum_EVALFLAGS dwFlags, IDebugEventCallback2 pExprCallback) + { + // Evaluate the expression asynchronously + var action = new Action(EvaluatingAsync); + action.BeginInvoke(EvaluateAsyncCompleted, action); + + return VSConstants.S_OK; + } + + /// + /// This method evaluates the expression synchronously. (http://msdn.microsoft.com/en-ca/library/bb146982.aspx) + /// + /// A combination of flags from the EVALFLAGS enumeration that control expression evaluation. + /// Maximum time, in milliseconds, to wait before returning from this method. Use INFINITE to wait + /// indefinitely. + /// This parameter is always a null value. + /// Returns the IDebugProperty2 object that contains the result of the expression evaluation. + /// VSConstants.S_OK. + int IDebugExpression2.EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult) + { + try + { + VariableInfo vi = VariableInfo.Get(_expression, _eventDispatcher, _frame); + ppResult = new AD7Property(vi); + return VSConstants.S_OK; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to evaluate expression value"); + ppResult = null; + return VSConstants.E_FAIL; + } + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7MemoryAddress.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7MemoryAddress.cs new file mode 100644 index 00000000..cb2f2332 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7MemoryAddress.cs @@ -0,0 +1,254 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// And implementation of IDebugCodeContext2 and IDebugMemoryContext2. + /// IDebugMemoryContext2 represents a position in the address space of the machine running the program being debugged. + /// IDebugCodeContext2 represents the starting position of a code instruction. For most run-time architectures today, a code + /// context can be thought of as an address in a program's execution stream. + /// + public sealed class AD7MemoryAddress : IDebugCodeContext2, IDebugCodeContext100 + { + /// + /// The AD7Engine object that represents the DE. + /// + private readonly AD7Engine _engine; + + /// + /// The current context's address. + /// + private readonly uint _address; + + /// + /// The IDebugDocumentContext2 object that corresponds to the code context. + /// + private IDebugDocumentContext2 _documentContext; + + /// + /// Constructor. + /// + /// The AD7Engine object that represents the DE. + /// The current context's address. + public AD7MemoryAddress(AD7Engine engine, uint address) + { + if (engine == null) + throw new ArgumentNullException("engine"); + + _engine = engine; + _address = address; + } + + /// + /// Sets the document context. + /// + /// The IDebugDocumentContext2 object that corresponds to the code context. + public void SetDocumentContext(IDebugDocumentContext2 docContext) + { + _documentContext = docContext; + } + + #region IDebugMemoryContext2 Members + + /// + /// Adds a specified value to the current context's address to create a new context. + /// (http://msdn.microsoft.com/en-ca/library/bb145861.aspx) + /// + /// The value to add to the current context. + /// Returns a new IDebugMemoryContext2 object. + /// VSConstants.S_OK. + public int Add(ulong dwCount, out IDebugMemoryContext2 newAddress) + { + newAddress = new AD7MemoryAddress(_engine, (uint)dwCount + _address); + return VSConstants.S_OK; + } + + /// + /// Compares the memory context to each context in the given array in the manner indicated by compare flags, + /// returning an index of the first context that matches. (http://msdn.microsoft.com/en-ca/library/bb161750.aspx) + /// + /// A value from the CONTEXT_COMPARE enumeration that determines the type of comparison. + /// An array of references to the IDebugMemoryContext2 objects to compare against. + /// The number of contexts in the compareToItems array. + /// Returns the index of the first memory context that satisfies the comparison. + /// If successful, returns S_OK; otherwise, returns an error code. + public int Compare(enum_CONTEXT_COMPARE uContextCompare, IDebugMemoryContext2[] compareToItems, uint compareToLength, out uint foundIndex) + { + foundIndex = uint.MaxValue; + + try + { + enum_CONTEXT_COMPARE contextCompare = uContextCompare; + + for (uint c = 0; c < compareToLength; c++) + { + // check if expected type and managed by the same debug-engine: + AD7MemoryAddress compareTo = compareToItems[c] as AD7MemoryAddress; + if (compareTo == null || !ReferenceEquals(_engine, compareTo._engine)) + { + continue; + } + + bool result; + + switch (contextCompare) + { + case enum_CONTEXT_COMPARE.CONTEXT_EQUAL: + result = _address == compareTo._address; + break; + + case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN: + result = _address < compareTo._address; + break; + + case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN: + result = _address > compareTo._address; + break; + + case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL: + result = _address <= compareTo._address; + break; + + case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL: + result = _address >= compareTo._address; + break; + + // The VSNDK debug engine doesn't understand scopes or functions + case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE: + case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION: + result = _address == compareTo._address; + break; + + case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE: + result = _address == compareTo._address; + break; + + case enum_CONTEXT_COMPARE.CONTEXT_SAME_PROCESS: + result = true; + break; + + default: + // A new comparison was invented that we don't support + return EngineUtils.NotImplemented(); + } + + if (result) + { + foundIndex = c; + return VSConstants.S_OK; + } + } + + return VSConstants.S_FALSE; + } + catch (Exception e) + { + return EngineUtils.UnexpectedException(e); + } + } + + /// + /// Gets information that describes this context. Not implemented. (http://msdn.microsoft.com/en-ca/library/bb145034.aspx) + /// + /// A combination of flags from the CONTEXT_INFO_FIELDS enumeration that indicate which fields of the + /// CONTEXT_INFO structure are to be fill in. + /// The CONTEXT_INFO structure that is filled in. + /// Not implemented. + public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) + { + return EngineUtils.NotImplemented(false); + } + + /// + /// Gets the user-displayable name for this context. This is not supported by the VSNDK debug engine. + /// (http://msdn.microsoft.com/en-ca/library/bb146997.aspx) + /// + /// Returns the name of the memory context. + /// Not implemented. + public int GetName(out string pbstrName) + { + pbstrName = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Subtracts a specified value from the current context's address to create a new context. + /// (http://msdn.microsoft.com/en-ca/library/bb146285.aspx) + /// + /// The number of memory bytes to decrement. + /// Returns a new IDebugMemoryContext2 object. + /// VSConstants.S_OK. + public int Subtract(ulong dwCount, out IDebugMemoryContext2 ppMemCxt) + { + ppMemCxt = new AD7MemoryAddress(_engine, (uint)dwCount - _address); + return VSConstants.S_OK; + } + + #endregion + + #region IDebugCodeContext2 Members + + /// + /// Gets the document context that corresponds to this code context. The document context represents a position in the source file + /// that corresponds to the source code that generated this instruction. (http://msdn.microsoft.com/en-ca/library/bb161811.aspx) + /// + /// Returns the IDebugDocumentContext2 object that corresponds to the code context. + /// VSConstants.S_OK. + public int GetDocumentContext(out IDebugDocumentContext2 ppSrcCxt) + { + ppSrcCxt = _documentContext; + return VSConstants.S_OK; + } + + /// + /// Gets the language information for this code context. (http://msdn.microsoft.com/en-ca/library/bb144925.aspx) + /// + /// Returns a string that contains the name of the language, such as "C++.". + /// Returns the GUID for the language of the code context, for example, guidCPPLang. + /// If successful, returns S_OK; otherwise, returns S_FALSE. + public int GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) + { + if (_documentContext != null) + { + _documentContext.GetLanguageInfo(ref pbstrLanguage, ref pguidLanguage); + return VSConstants.S_OK; + } + return VSConstants.S_FALSE; + } + + #endregion + + #region IDebugCodeContext100 Members + + /// + /// Returns the program being debugged. In the case of this VSNDK debug debug engine, AD7Engine implements IDebugProgram2 which + /// represents the program being debugged. + /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugcodecontext100.getprogram.aspx) + /// + /// Returns the program being debugged. + /// VSConstants.S_OK. + int IDebugCodeContext100.GetProgram(out IDebugProgram2 pProgram) + { + pProgram = _engine; + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Module.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Module.cs new file mode 100644 index 00000000..dad80fb1 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Module.cs @@ -0,0 +1,207 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents a module loaded in the debuggee process to the debugger. Not implemented, yet. + /// + /// It implements: + /// + /// IDebugModule2: This interface represents a modulethat is, an executable unit of a programsuch as a DLL. + /// (http://msdn.microsoft.com/en-ca/library/bb145360.aspx) + /// + /// IDebugModule3: This interface represents a module that supports alternate locations of symbols and JustMyCode states. + /// (http://msdn.microsoft.com/en-ca/library/bb145893.aspx) + /// + public sealed class AD7Module : IDebugModule2, IDebugModule3 + { + /// + /// Gets information about this module. (http://msdn.microsoft.com/en-ca/library/bb161975.aspx) + /// + /// A combination of flags from the MODULE_INFO_FIELDS enumeration that specify which fields of pInfo + /// are to be filled out. + /// A MODULE_INFO structure that is filled in with a description of the module. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugModule2.GetInfo(enum_MODULE_INFO_FIELDS flags, MODULE_INFO[] infoArray) + { + try + { + MODULE_INFO info = new MODULE_INFO(); + + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_NAME)) + { + info.m_bstrName = ""; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_NAME; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_URL)) + { + info.m_bstrUrl = ""; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_URL; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS)) + { + info.m_addrLoadAddress = 0; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS)) + { + // A debugger that actually supports showing the preferred base should crack the PE header and get + // that field. This debugger does not do that, so assume the module loaded where it was suppose to. + info.m_addrPreferredLoadAddress = 0; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_SIZE)) + { + info.m_dwSize = 0; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_SIZE; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_LOADORDER)) + { + info.m_dwLoadOrder = 0; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_LOADORDER; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION)) + { + info.m_bstrUrlSymbolLocation = ""; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_FLAGS)) + { + info.m_dwModuleFlags = 0; + info.m_dwModuleFlags |= (enum_MODULE_FLAGS.MODULE_FLAG_SYMBOLS); + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_FLAGS; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_VERSION)) + { + info.m_bstrVersion = ""; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_VERSION; + } + if (flags.HasFlag(enum_MODULE_INFO_FIELDS.MIF_DEBUGMESSAGE)) + { + info.m_bstrDebugMessage = ""; + info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_DEBUGMESSAGE; + } + + infoArray[0] = info; + return VSConstants.S_OK; + } + catch (Exception e) + { + return EngineUtils.UnexpectedException(e); + } + } + + #region Deprecated interface methods + // These methods are not called by the Visual Studio debugger, so they don't need to be implemented + + /// + /// OBSOLETE. DO NOT USE. Reloads the symbols for this module. (http://msdn.microsoft.com/en-ca/library/bb145113.aspx) + /// + /// The path to the symbol store. + /// Returns an informational message, such as a status or error message, that is displayed to the + /// right of the module name in the Modules window. + /// VSConstants.E_NOTIMPL. + int IDebugModule2.ReloadSymbols_Deprecated(string urlToSymbols, out string debugMessage) + { + debugMessage = null; + return EngineUtils.NotImplemented(); + } + + /// + /// This method is not presented in IDebugModule3 webpage but the debug engine fails to build without it. It should have the same + /// behavior as the above IDebugModule2.ReloadSymbols_Deprecated. (http://msdn.microsoft.com/en-ca/library/bb145893.aspx) + /// + /// + /// + /// Not implemented. + int IDebugModule3.ReloadSymbols_Deprecated(string urlToSymbols, out string pbstrDebugMessage) + { + pbstrDebugMessage = null; + return EngineUtils.NotImplemented(); + } + + #endregion + + /// + /// This method is not presented in IDebugModule3 webpage but the debug engine fails to build without it. + /// (http://msdn.microsoft.com/en-ca/library/bb145893.aspx). It should have the same behavior as the above + /// IDebugModule2.GetInfo, i.e., gets information about this module. (http://msdn.microsoft.com/en-ca/library/bb161975.aspx) + /// + /// A combination of flags from the MODULE_INFO_FIELDS enumeration that specify which fields of pInfo + /// are to be filled out. + /// A MODULE_INFO structure that is filled in with a description of the module. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugModule3.GetInfo(enum_MODULE_INFO_FIELDS flags, MODULE_INFO[] pinfo) + { + return ((IDebugModule2)this).GetInfo(flags, pinfo); + } + + /// + /// Returns a list of paths searched for symbols and the results of searching each path. + /// [http://msdn.microsoft.com/en-ca/library/bb161971(v=vs.100).aspx] + /// + /// A combination of flags from the SYMBOL_SEARCH_INFO_FIELDS enumeration specifying which fields + /// of pInfo are to be filled in. + /// A MODULE_SYMBOL_SEARCH_INFO structure whose members are to be filled in with the specified information. + /// If this is a null value, this method returns E_INVALIDARG. + /// VSConstants.S_OK. + int IDebugModule3.GetSymbolInfo(enum_SYMBOL_SEARCH_INFO_FIELDS flags, MODULE_SYMBOL_SEARCH_INFO[] pinfo) + { + pinfo[0] = new MODULE_SYMBOL_SEARCH_INFO(); + pinfo[0].dwValidFields = 1; // SSIF_VERBOSE_SEARCH_INFO; + pinfo[0].bstrVerboseSearchInfo = "Symbols not loaded"; + return VSConstants.S_OK; + } + + /// + /// Retrieves information on whether the module represents user code or not. Used to support the JustMyCode features of the + /// debugger. [http://msdn.microsoft.com/en-ca/library/bb146644(v=vs.100).aspx] + /// The VSNDK debug engine does not support JustMyCode and therefore all modules are considered "My Code" + /// + /// Nonzero (TRUE) if module represents user code, zero (FALSE) if it does not. + /// VSConstants.S_OK. + int IDebugModule3.IsUserCode(out int pIsUserCode) + { + pIsUserCode = 1; + return VSConstants.S_OK; + } + + /// + /// Loads and initializes symbols for the current module when the user explicitly asks for them to load. Not implemented. + /// [http://msdn.microsoft.com/en-ca/library/bb146634(v=vs.100).aspx] + /// + /// Not implemented. + int IDebugModule3.LoadSymbols() + { + return EngineUtils.NotImplemented(); + } + + /// + /// Specifies whether the module should be considered user code or not. Used to support the JustMyCode features of the debugger. + /// [http://msdn.microsoft.com/en-ca/library/bb146327(v=vs.100).aspx] + /// The VSNDK debug engine does not support JustMyCode so this is not implemented + /// + /// Nonzero (TRUE) if the module should be considered user code, zero (FALSE) if it should not. + /// Not implemented. + int IDebugModule3.SetJustMyCodeState(int fIsUserCode) + { + return EngineUtils.NotImplemented(); + } + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7PendingBreakpoint.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7PendingBreakpoint.cs new file mode 100644 index 00000000..c7f8bc03 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7PendingBreakpoint.cs @@ -0,0 +1,345 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System; +using System.Collections.Generic; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents a pending breakpoint that is ready to bind to a code location. A pending breakpoint is an abstract + /// representation of a breakpoint before it is bound. When a user creates a new breakpoint, the pending breakpoint is created + /// and is later bound. The bound breakpoints become children of the pending breakpoint. + /// + /// It implements IDebugPendingBreakpoint2: (http://msdn.microsoft.com/en-ca/library/bb161807.aspx) + /// + public sealed class AD7PendingBreakpoint : IDebugPendingBreakpoint2 + { + private readonly AD7Engine _engine; + + /// + /// The breakpoint request that resulted in this pending breakpoint being created. + /// + private readonly IDebugBreakpointRequest2 _breakpointRequest; + private BP_REQUEST_INFO _breakpointRequestInfo; + + private readonly List _boundBreakpoints; + private bool _enabled; + private bool _deleted; + + /// + /// Constructor. + /// + /// The breakpoint request used to create this pending breakpoint. + /// The AD7Engine object that represents the DE. + public AD7PendingBreakpoint(AD7Engine engine, IDebugBreakpointRequest2 breakpointRequest) + { + if (engine == null) + throw new ArgumentNullException("engine"); + if (breakpointRequest == null) + throw new ArgumentNullException("breakpointRequest"); + + BP_REQUEST_INFO[] requestInfo = new BP_REQUEST_INFO[1]; + _breakpointRequest = breakpointRequest; + _breakpointRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_BPLOCATION, requestInfo); // PH: FIXME: check return code here and in following calls... + _breakpointRequestInfo = requestInfo[0]; + _breakpointRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_CONDITION, requestInfo); + if (requestInfo[0].dwFields != 0) + { + _breakpointRequestInfo.bpCondition = requestInfo[0].bpCondition; + _breakpointRequestInfo.dwFields |= requestInfo[0].dwFields; + } + _breakpointRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_PASSCOUNT, requestInfo); + if (requestInfo[0].dwFields != 0) + { + _breakpointRequestInfo.bpPassCount = requestInfo[0].bpPassCount; + _breakpointRequestInfo.dwFields |= requestInfo[0].dwFields; + } + + _engine = engine; + _boundBreakpoints = new List(); + + _enabled = true; + _deleted = false; + } + + /// + /// Determines whether this pending breakpoint can bind to a code location. + /// + /// If successful, returns TRUE; otherwise, returns FALSE. + private bool CanBind + { + get + { + if (_deleted || !_engine.HasProcess) + return false; + + // The engine only supports these types of breakpoints: + // - file and line number + // - function name and offset + if (_breakpointRequestInfo.bpLocation.bpLocationType == (uint) enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE + || _breakpointRequestInfo.bpLocation.bpLocationType == (uint) enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) + return true; + + return false; + } + } + + /// + /// Remove all of the bound breakpoints for this pending breakpoint + /// + public void ClearBoundBreakpoints() + { + lock (_boundBreakpoints) + { + for (int i = _boundBreakpoints.Count - 1; i >= 0; i--) + { + _boundBreakpoints[i].Delete(); + } + } + } + + /// + /// Called by bound breakpoints when they are being deleted. + /// + /// A bound breakpoint. + public void OnBoundBreakpointDeleted(AD7BoundBreakpoint boundBreakpoint) + { + lock (_boundBreakpoints) + { + _boundBreakpoints.Remove(boundBreakpoint); + } + } + + #region IDebugPendingBreakpoint2 Members + + /// + /// Bind this breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145901.aspx) + /// + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugPendingBreakpoint2.Bind() + { + if (!DebugEngineStatus.IsRunning) + { + return VSConstants.S_FALSE; + } + + try + { + if (CanBind) + { + // Visual Studio returns a start position that is one less than it actually is + var boundBreakpoint = new AD7BoundBreakpoint(_engine, _breakpointRequestInfo, this); + + if (boundBreakpoint.GdbInfo.ID == 0) + { + return VSConstants.S_FALSE; + } + + // Set the enabled state of the bound breakpoint based on the pending breakpoint's enabled state + ((IDebugBoundBreakpoint2)boundBreakpoint).Enable(_enabled ? 1 : 0); + _boundBreakpoints.Add(boundBreakpoint); + + return VSConstants.S_OK; + } + + // PH: FIXME: + // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid + // expression, etc... The VSNDK debug engine does not support this, but a real world engine will want to send an + // instance of IDebugBreakpointErrorEvent2 to the UI and return a valid instance of IDebugErrorBreakpoint2 from + // IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then display information about why the + // breakpoint did not bind to the user. + return VSConstants.S_FALSE; + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + } + + /// + /// Determines whether this pending breakpoint can bind to a code location. (http://msdn.microsoft.com/en-ca/library/bb146753.aspx) + /// + /// Returns an IEnumDebugErrorBreakpoints2 object that contains a list of IDebugErrorBreakpoint2 + /// objects if there could be errors. + /// If successful, returns S_OK; otherwise, returns S_FALSE + int IDebugPendingBreakpoint2.CanBind(out IEnumDebugErrorBreakpoints2 ppErrorEnum) + { + ppErrorEnum = null; + + if (!CanBind) + { + // PH: FIXME: + // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid + // expression, etc... The VSNDK debug engine does not support this, but a real world engine will want to send an + // instance of IDebugBreakpointErrorEvent2 to the UI and return a valid instance of IDebugErrorBreakpoint2 from + // IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then display information about why the + // breakpoint did not bind to the user. + return VSConstants.S_FALSE; + } + + return VSConstants.S_OK; + } + + /// + /// Deletes this pending breakpoint and all breakpoints bound from it. (http://msdn.microsoft.com/en-ca/library/bb145918.aspx) + /// + /// VSConstants.S_OK. + int IDebugPendingBreakpoint2.Delete() + { + lock (_boundBreakpoints) + { + for (int i = _boundBreakpoints.Count - 1; i >= 0; i--) + { + _boundBreakpoints[i].Delete(); + } + } + + _enabled = false; + _deleted = true; + return VSConstants.S_OK; + } + + /// + /// Toggles the enabled state of this pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145046.aspx) + /// + /// Set to nonzero (TRUE) to enable a pending breakpoint, or to zero (FALSE) to disable. + /// VSConstants.S_OK. + int IDebugPendingBreakpoint2.Enable(int fEnable) + { + lock (_boundBreakpoints) + { + _enabled = fEnable != 0; + + foreach (var breakpoint in _boundBreakpoints) + { + breakpoint.Enable(fEnable); + } + } + + return VSConstants.S_OK; + } + + /// + /// Enumerates all breakpoints bound from this pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145139.aspx) + /// + /// Returns an IEnumDebugBoundBreakpoints2 object that enumerates the bound breakpoints. + /// VSConstants.S_OK. + int IDebugPendingBreakpoint2.EnumBoundBreakpoints(out IEnumDebugBoundBreakpoints2 ppEnum) + { + lock (_boundBreakpoints) + { + IDebugBoundBreakpoint2[] boundBreakpoints = _boundBreakpoints.ToArray(); + ppEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); + } + return VSConstants.S_OK; + } + + /// + /// Enumerates all error breakpoints that resulted from this pending breakpoint. + /// (http://msdn.microsoft.com/en-ca/library/bb145598.aspx) + /// + /// A combination of values from the enum_BP_ERROR_TYPE enumeration that selects the type of errors + /// to enumerate. + /// Returns an IEnumDebugErrorBreakpoints2 object that contains a list of IDebugErrorBreakpoint2 objects. + /// VSConstants.E_NOTIMPL. + int IDebugPendingBreakpoint2.EnumErrorBreakpoints(enum_BP_ERROR_TYPE bpErrorType, out IEnumDebugErrorBreakpoints2 ppEnum) + { + // PH: FIXME: + // Called when a pending breakpoint could not be bound. This may occur for many reasons such as an invalid location, an + // invalid expression, etc... The VSNDK debug engine does not support this, but a real world engine will want to send an + // instance of IDebugBreakpointErrorEvent2 to the UI and return a valid enumeration of IDebugErrorBreakpoint2 from + // IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then display information about why the breakpoint + // did not bind to the user. + ppEnum = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Gets the breakpoint request that was used to create this pending breakpoint. + /// (http://msdn.microsoft.com/en-ca/library/bb161770.aspx) + /// + /// Returns an IDebugBreakpointRequest2 object representing the breakpoint request that was used to + /// create this pending breakpoint. + /// VSConstants.S_OK. + int IDebugPendingBreakpoint2.GetBreakpointRequest(out IDebugBreakpointRequest2 ppBPRequest) + { + ppBPRequest = _breakpointRequest; + return VSConstants.S_OK; + } + + /// + /// Gets the state of this pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb162178.aspx) + /// + /// A PENDING_BP_STATE_INFO structure that is filled in with a description of this pending breakpoint. + /// VSConstants.S_OK. + int IDebugPendingBreakpoint2.GetState(PENDING_BP_STATE_INFO[] pState) + { + if (_deleted) + { + pState[0].state = (enum_PENDING_BP_STATE)enum_BP_STATE.BPS_DELETED; + return VSConstants.S_OK; + } + + if (!_enabled) + { + pState[0].state = (enum_PENDING_BP_STATE)enum_BP_STATE.BPS_DISABLED; + return VSConstants.S_OK; + } + + pState[0].state = (enum_PENDING_BP_STATE)enum_BP_STATE.BPS_ENABLED; + return VSConstants.S_OK; + } + + /// + /// Sets or changes the condition associated with the pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb144977.aspx). + /// Not implemented here, but a conditional breakpoint can be set using IDebugBoundBreakpoint2::SetCondition(). + /// + /// A BP_CONDITION structure that specifies the condition to set. + /// Not implemented. + int IDebugPendingBreakpoint2.SetCondition(BP_CONDITION bpCondition) + { + return EngineUtils.NotImplemented(); + } + + /// + /// Sets or changes the pass count associated with the pending breakpoint. (http://msdn.microsoft.com/en-ca/library/bb145038.aspx). + /// Not implemented here, but a pass count associated to a breakpoint can be set/changed using + /// IDebugBoundBreakpoint2::SetPassCount(). + /// + /// A BP_PASSCOUNT structure that contains the pass count. + /// Not implemented. + int IDebugPendingBreakpoint2.SetPassCount(BP_PASSCOUNT bpPassCount) + { + return EngineUtils.NotImplemented(); + } + + /// + /// Toggles the virtualized state of this pending breakpoint. When a pending breakpoint is virtualized, the debug engine will + /// attempt to bind it every time new code loads into the program. (http://msdn.microsoft.com/en-ca/library/bb146187.aspx) + /// The VSNDK debug engine does not support this. Not implemented. + /// + /// Set to nonzero (TRUE) to virtualize the pending breakpoint, or to zero (FALSE) to turn off + /// virtualization. + /// VSConstants.S_OK. + int IDebugPendingBreakpoint2.Virtualize(int fVirtualize) + { + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Port.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Port.cs new file mode 100644 index 00000000..fccbb0d3 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Port.cs @@ -0,0 +1,292 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Debugger; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.QConn; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio.Debugger.Interop; +using Microsoft.VisualStudio; +using System.Windows.Forms; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class implements a port. + /// + /// It implements: + /// + /// - IDebugPort2 - This interface represents a debug port on a machine. (http://msdn.microsoft.com/en-us/library/bb147021.aspx) + /// - IConnectionPointContainer - Supports connection points for connectable objects. Indicates to a client that the object is + /// connectable and provides the IConnectionPoint interface. (http://msdn.microsoft.com/en-CA/library/ms683857.aspx) + /// - IConnectionPoint - Supports connection points for connectable objects. (http://msdn.microsoft.com/en-us/library/ms694318.aspx) + /// + public sealed class AD7Port : IDebugPort2 + { + /// + /// Represents the request that was used to create the port. + /// + private readonly AD7PortRequest _request; + + /// + /// Represents the port supplier for this port. + /// + private readonly AD7PortSupplier _supplier; + + /// + /// Stores the last time that the list of running processes was refreshed. + /// Used to avoid issues in case the user spams the refresh button. + /// + private DateTime _lastTimeRefresh = DateTime.MinValue; + + /// + /// Stores the list of running processes in the simulator/device. + /// + private IDebugProcess2[] _processes; + + /// + /// Constructor. + /// + /// The port supplier for this port. + /// The request used to create the port. + /// The GUID that identifies the port. + /// The name of the port. + /// Description of the device it should communicate with. + /// The description of NDK installed on host machine. + public AD7Port(AD7PortSupplier supplier, AD7PortRequest request, Guid guid, string name, DeviceDefinition device, NdkDefinition ndk) + { + if (supplier == null) + throw new ArgumentNullException("supplier"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (device == null) + throw new ArgumentNullException("device"); + if (ndk == null) + throw new ArgumentNullException("ndk"); + + Name = name; + _request = request; + _supplier = supplier; + Guid = guid; + Device = device; + NDK = ndk; + } + + #region Properties + + /// + /// Gets or set the GUID that identifies the port. + /// + public Guid Guid + { + get; + private set; + } + + /// + /// Gets or sets the name of the port. + /// + public string Name + { + get; + private set; + } + + public DeviceDefinition Device + { + get; + private set; + } + + /// + /// Gets or sets the NDK reference. + /// + public NdkDefinition NDK + { + get; + private set; + } + + #endregion + + /// + /// Gets the list of processes running on this port. + /// + /// Returns the list of processes running on this port. + private AD7Process[] GetProcesses() + { + //////////////////////////////////////////////////////// + // "the old way", which seemed not to work on PlayBook + //var processesRequest = GdbWrapper.ListProcesses(NDK, Device); + //processesRequest.Processes... + + //////////////////////////////////////////////////////// + // "the new way" is using a dedicated separate connection to the device, + // that servers extra data for IDEs: + + // get QConnClient and connect to the device, if not yet connected: + SystemInfoProcess[] processes = null; + + try + { + var qClient = Targets.Get(Device, ConfigDefaults.SshPublicKeyPath, ConfigDefaults.SshPrivateKeyPath); + if (qClient != null) + { + processes = qClient.SysInfoService.LoadProcesses(); + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load list of processes"); + + // try to disconnect, so retry will have a clean-state: + Targets.Disconnect(Device); + } + + // timeout or other problem? + if (processes == null) + { + string deviceType = Device.Type == DeviceDefinitionType.Device ? "device" : "simulator"; + MessageBoxHelper.Show(string.Concat("Please, verify if the ", deviceType, " (", Device.IP, ") is defined correctly. It can be modified at \"BlackBerry -> Options -> Targets\" tab."), + "Connection failure or timeout", MessageBoxButtons.OK, MessageBoxIcon.Warning); + + return new AD7Process[0]; + } + + // ok, got the valid response + var result = new List(); + foreach (var p in processes) + { + result.Add(new AD7Process(this, p)); + } + + return result.ToArray(); + } + + #region Implementation of IDebugPort2 + + /// + /// Returns the port name. (http://msdn.microsoft.com/en-us/library/bb145890.aspx) + /// + /// Returns the name of the port. + /// VSConstants.S_OK. + public int GetPortName(out string pbstrName) + { + pbstrName = Name; + return VSConstants.S_OK; + } + + /// + /// Returns the port identifier. (http://msdn.microsoft.com/en-us/library/bb146747.aspx) + /// + /// Returns the GUID that identifies the port. + /// VSConstants.S_OK. + public int GetPortId(out Guid pguidPort) + { + pguidPort = Guid; + return VSConstants.S_OK; + } + + /// + /// Returns the request used to create a port. (http://msdn.microsoft.com/en-us/library/bb145127.aspx) + /// + /// Returns an IDebugPortRequest2 object representing the request that was used to create the port. + /// VSConstants.S_OK. + public int GetPortRequest(out IDebugPortRequest2 ppRequest) + { + ppRequest = _request; + return VSConstants.S_OK; + } + + /// + /// Returns the port supplier for this port. (http://msdn.microsoft.com/en-us/library/bb146688.aspx) + /// + /// Returns an IDebugPortSupplier2 object represents the port supplier for a port. + /// VSConstants.S_OK. + public int GetPortSupplier(out IDebugPortSupplier2 ppSupplier) + { + ppSupplier = _supplier; + return VSConstants.S_OK; + } + + /// + /// Returns the specified process running on a port. (http://msdn.microsoft.com/en-us/library/bb145867.aspx) + /// + /// An AD_PROCESS_ID structure that specifies the process identifier. + /// Returns an IDebugProcess2 object representing the process. + /// If successful, returns VSConstants.S_OK; otherwise, returns VSConstants.S_FALSE. + public int GetProcess(AD_PROCESS_ID processId, out IDebugProcess2 ppProcess) + { + IEnumerable list = GetProcesses(); + uint id = processId.dwProcessId; + + ppProcess = null; + foreach (var process in list) + { + if (process.ID == id) + { + ppProcess = process; + break; + } + } + return ppProcess != null ? VSConstants.S_OK : VSConstants.S_FALSE; + } + + /// + /// Enumerates all the processes running on a port. (http://msdn.microsoft.com/en-us/library/bb161302.aspx) + /// + /// Returns an IEnumDebugProcesses2 object that contains a list of all the processes running on a port. + /// VSConstants.S_OK. + public int EnumProcesses(out IEnumDebugProcesses2 ppEnum) + { + if (string.IsNullOrEmpty(Device.IP)) + { + _processes = new IDebugProcess2[0]; + } + else + { + DateTime now = DateTime.Now; + + TimeSpan diff = now - _lastTimeRefresh; + double seconds = diff.TotalSeconds; + + if (seconds > 1) + { + var processlist = GetProcesses(); + _processes = new IDebugProcess2[processlist.Length]; + int i = 0; + foreach (var debugProcess in processlist) + { + _processes[i] = debugProcess; + i++; + } + _lastTimeRefresh = DateTime.Now; + } + } + + ppEnum = new AD7ProcessEnum(_processes); + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7PortRequest.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7PortRequest.cs new file mode 100644 index 00000000..83074cf0 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7PortRequest.cs @@ -0,0 +1,76 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.NativeCore.Model; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class describes a port. This description is used to add the port to a port supplier. + /// + /// It implements IDebugPortRequest2 (http://msdn.microsoft.com/en-us/library/bb146168.aspx) + /// + public sealed class AD7PortRequest : IDebugPortRequest2 + { + /// + /// Constructor. + /// + /// The name of the port. + /// Detailed info about the device. + public AD7PortRequest(string name, DeviceDefinition device) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (device == null) + throw new ArgumentNullException("device"); + + Name = name; + Device = device; + } + + #region Properties + + public string Name + { + get; + private set; + } + + public DeviceDefinition Device + { + get; + private set; + } + + #endregion + + #region Implementation of IDebugPortRequest2 + + /// + /// Gets the name of the port to create. + /// + /// Returns the name of the port. + /// VSConstants.S_OK. + public int GetPortName(out string portName) + { + portName = Name; + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7PortSupplier.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7PortSupplier.cs new file mode 100644 index 00000000..8795a863 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7PortSupplier.cs @@ -0,0 +1,392 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Services; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using IServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class supplies ports to the Session Debug Manager (SDM). + /// + /// It implements: + /// + /// - IDebugPortSupplier2 - This interface supplies ports to the session debug manager (SDM). (http://msdn.microsoft.com/en-ca/library/bb145819.aspx) + /// - IDebugPortSupplierDescription2 - Enables the Visual Studio UI to display text inside the Transport Information section of + /// the Attach to Process dialog box. (http://msdn.microsoft.com/en-us/library/bb458056.aspx) + /// + /// It is needed to enable updating the list of processes in the "attach to process" user interface. + /// + [ComVisible(true)] + [Guid(ClassGuid)] + public sealed class AD7PortSupplier : IDebugPortSupplier2, IDebugPortSupplierDescription2, IDebugPortPicker + { + public const string PublicName = "BlackBerry Native Debugger"; + public const string ClassGuid = "BDC2218C-D50C-4A5A-A2F6-66BDC94FF8D6"; + public const string ClassName = "BlackBerry.DebugEngine.AD7PortSupplier"; + + /// + /// The NDK reference. + /// + private NdkDefinition _ndk; + private ServiceProvider _serviceProvider; + + /// + /// List of ports for this port supplier. + /// + private readonly Dictionary _ports = new Dictionary(); + + private IDebugPort2[] CreateDefaultPorts() + { + var ndk = NdkDefinition.Load(); + var devices = DeviceDefinition.LoadAll(); + + if (ndk == null || string.IsNullOrEmpty(ndk.ToolsPath)) + return null; + _ndk = ndk; + + var result = new List(); + + if (devices != null) + { + foreach (var device in devices) + { + result.Add(CreatePort(this, new AD7PortRequest(GetPortRequestName(device), device), _ndk)); + } + } + + return result.ToArray(); + } + + private static string GetPortRequestName(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + if (string.IsNullOrEmpty(device.Name)) + return string.Concat(DeviceHelper.GetTypeToString(device.Type), ": ", device.IP); + + return string.Concat(DeviceHelper.GetTypeToString(device.Type), ": ", device.Name, " (", device.IP, ")"); + } + + private static string GetAdHocPortRequestName(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + if (string.IsNullOrEmpty(device.Name)) + return string.Concat(DeviceHelper.GetTypeToString(device.Type), " ", device.IP, " ", device.Password); + return string.Concat(DeviceHelper.GetTypeToString(device.Type), " ", device.Name.Replace(' ', '_'), " ", device.IP, " ", device.Password); + } + + /// + /// Creates an AD7Port. + /// + private static AD7Port CreatePort(AD7PortSupplier supplier, AD7PortRequest request, NdkDefinition ndk) + { + if (request == null) + throw new ArgumentNullException("request"); + if (request.Device == null) + throw new ArgumentOutOfRangeException("request"); + + return new AD7Port(supplier, request, Guid.NewGuid(), request.Name, request.Device, ndk); + } + + #region Implementation of IDebugPortSupplier2 + + /// + /// Adds a port. (http://msdn.microsoft.com/en-ca/library/bb161980.aspx) + /// + /// An IDebugPortRequest2 object that describes the port to be added. + /// Returns an IDebugPort2 object that represents the port. + /// VSConstants.S_OK. + int IDebugPortSupplier2.AddPort(IDebugPortRequest2 request, out IDebugPort2 ppPort) + { + if (request == null || _ndk == null) + { + ppPort = null; + return VSConstants.S_OK; + } + + // is it one of the default requests created by the AD7PortSupplier? + var portRequest = request as AD7PortRequest; + if (portRequest != null) + { + var port = CreatePort(this, portRequest, _ndk); + _ports[port.Guid] = port; + ppPort = port; + return VSConstants.S_OK; + } + + string requestName; + if (request.GetPortName(out requestName) == VSConstants.S_OK) + { + requestName = requestName.Trim(); + var port = FindPort(requestName); + + // create something at hoc? + if (port == null) + { + var device = CreateAdHocDevice(requestName); + if (device != null) + { + ppPort = new AD7Port(this, null, Guid.NewGuid(), GetPortRequestName(device), device, _ndk); + return VSConstants.S_OK; + } + + MessageBoxHelper.Show("Too few information about device you are trying to connect.\n\nPlease, follow the pattern: \"(device|simulator) IP password\".", "Unable to create device connection", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + else + { + ppPort = port; + return VSConstants.S_OK; + } + } + + ppPort = null; + return VSConstants.E_FAIL; + } + + private AD7Port FindPort(string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + foreach (var port in _ports.Values) + { + if (port.Device.HasIdenticalIP(text) || port.Device.HasIdenticalName(text)) + return port; + } + + return null; + } + + private static DeviceDefinition CreateAdHocDevice(string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + var items = text.Split(new[] { ' ', '|', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); + if (items.Length < 2) + return null; + + int i = 0; + var type = DeviceDefinitionType.Device; + string name = "Ad-hoc Connection"; + string ip = null; + string password = null; + + try + { + type = DeviceHelper.GetTypeFromString(items[i++], true); + } + catch + { + // unable to decipher type: device/simulator... + return null; + } + + // name: + if (items.Length > i && items[i].IndexOf('.') < 0) + { + name = items[i++]; + } + + // ip: + if (items.Length > i && items[i].IndexOf('.') > 0) + { + ip = items[i++]; + } + + // password: + if (items.Length > i) + { + password = items[i]; + } + + // verify input: + if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(password)) + return null; + + return new DeviceDefinition(name, ip, password, type); + } + + /// + /// Verifies that a port supplier can add new ports. (http://msdn.microsoft.com/en-ca/library/bb145880.aspx) + /// + /// VSConstants.S_OK. + int IDebugPortSupplier2.CanAddPort() + { + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of all the ports supplied by a port supplier. (http://msdn.microsoft.com/en-ca/library/bb146984.aspx) + /// + /// Returns an IEnumDebugPorts2 object containing a list of ports supplied. + /// VSConstants.S_OK. + int IDebugPortSupplier2.EnumPorts(out IEnumDebugPorts2 ppEnum) + { + // Returning because VS can debug only one app at a time. + if (DebugEngineStatus.IsRunning) + { + MessageBoxHelper.Show("Visual Studio can debug only one BlackBerry application at a time.\n\nPlease, select a different transport or close the current debug session.", "Visual Studio is already debugging an application", MessageBoxButtons.OK, MessageBoxIcon.Warning); + ppEnum = null; + return VSConstants.S_FALSE; + } + + var defaultPorts = CreateDefaultPorts(); + if (defaultPorts == null) + { + MessageBoxHelper.Show("You must select an API Level to be able to attach to a running process.\n\nPlease, use \"BlackBerry -> Options -> API Level\" to download or select one.", "Missing NDK", MessageBoxButtons.OK, MessageBoxIcon.Warning); + ppEnum = null; + return VSConstants.S_FALSE; + } + if (defaultPorts.Length == 0) + { + MessageBoxHelper.Show("Missing Device/Simulator information. Please, use menu \"BlackBerry -> Options\" to add any of those information.", "Missing Device/Simulator Data", MessageBoxButtons.OK, MessageBoxIcon.Information); + ppEnum = null; + return VSConstants.S_FALSE; + } + + _ports.Clear(); + foreach (var port in defaultPorts) + { + Guid portGuid; + if (port.GetPortId(out portGuid) == VSConstants.S_OK) + { + _ports[portGuid] = (AD7Port) port; + } + } + + ppEnum = new AD7PortEnum(defaultPorts); + return VSConstants.S_OK; + } + + /// + /// Gets a port from a port supplier. (http://msdn.microsoft.com/en-ca/library/bb161812.aspx) + /// + /// Globally unique identifier (GUID) of the port. + /// Returns an IDebugPort2 object that represents the port. + /// VSConstants.S_OK. + int IDebugPortSupplier2.GetPort(ref Guid guidPort, out IDebugPort2 ppPort) + { + ppPort = _ports[guidPort]; + return VSConstants.S_OK; + } + + /// + /// Gets the port supplier identifier. (http://msdn.microsoft.com/en-ca/library/bb146617.aspx) + /// + /// Returns the GUID of the port supplier. + /// VSConstants.S_OK. + int IDebugPortSupplier2.GetPortSupplierId(out Guid pguidPortSupplier) + { + pguidPortSupplier = new Guid(ClassGuid); + return VSConstants.S_OK; + } + + /// + /// Gets the port supplier name. (http://msdn.microsoft.com/en-ca/library/bb162136.aspx) + /// + /// Returns the name of the port supplier. + /// VSConstants.S_OK. + int IDebugPortSupplier2.GetPortSupplierName(out string pbstrName) + { + pbstrName = PublicName; + return VSConstants.S_OK; + } + + /// + /// Removes a port. Not implemented. (http://msdn.microsoft.com/en-ca/library/bb162306.aspx) + /// + /// An IDebugPort2 object that represents the port to be removed. + /// Not implemented. It should returns S_OK if successful; or an error code. + int IDebugPortSupplier2.RemovePort(IDebugPort2 port) + { + return EngineUtils.NotImplemented(); + } + + #endregion + + #region Implementation of IDebugPortSupplierDescription2 + + /// + /// Retrieves the description for the port supplier. (http://msdn.microsoft.com/en-us/library/bb457978.aspx) + /// + /// Metadata flags for the description. + /// Description of the port supplier. + /// VSConstants.S_OK. + int IDebugPortSupplierDescription2.GetDescription(enum_PORT_SUPPLIER_DESCRIPTION_FLAGS[] pdwFlags, out string pbstrText) + { + pbstrText = "The BlackBerry Native Transport lets you select and attach to a process that is running on a device or simulator"; + return VSConstants.S_OK; + } + + #endregion + + /// + /// Sets the service provider. (http://msdn.microsoft.com/en-us/library/bb491408.aspx) + /// + /// Reference to the interface of the service provider. + int IDebugPortPicker.SetSite(IServiceProvider serviceProvider) + { + _serviceProvider = new ServiceProvider(serviceProvider); + return VSConstants.S_OK; + } + + /// + /// Displays the specified dialog box that allows the user to select a port. (http://msdn.microsoft.com/en-us/library/bb491260.aspx) + /// + /// Handle for the parent dialog box. + /// Port identifier string. + /// If successful, returns S_OK; otherwise, returns an error code. A return value of S_FALSE (or a return value of S_OK with the BSTR set to NULL) indicates that the user clicked Cancel. + int IDebugPortPicker.DisplayPortPicker(IntPtr hwndParentDialog, out string pbstrPortId) + { + var service = _serviceProvider != null ? _serviceProvider.GetService(typeof(IDeviceDiscoveryService)) as IDeviceDiscoveryService : null; + + if (service == null) + { + MessageBoxHelper.Show( + "Searching is not supported.\r\nPlease add more devices at \"BlackBerry -> Options -> Targets\", if you want to quickly switch between them. They will automatically appear, when \"Qualifier\" list is expanded.", + "Microsoft Visual Studio", MessageBoxButtons.OK, MessageBoxIcon.Information); + pbstrPortId = null; + return VSConstants.S_FALSE; + } + + var device = service.FindDevice(); + + // did we found the device? + if (device != null) + { + pbstrPortId = GetAdHocPortRequestName(device); + return VSConstants.S_OK; + } + + // or cancelled: + pbstrPortId = null; + return VSConstants.S_FALSE; + } + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Process.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Process.cs new file mode 100644 index 00000000..0b3b8700 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Process.cs @@ -0,0 +1,397 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Model; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents a process running on a port. If the port is the local port, then IDebugProcess2 usually represents a + /// physical process on the local machine. Not implemented completely. (http://msdn.microsoft.com/en-ca/library/bb147137.aspx). + /// + /// It also implements IDebugProcessEx2: This interface lets the session debug manager (SDM) notify a process that it is + /// attaching to or detaching from the process. (http://msdn.microsoft.com/en-us/library/bb145892.aspx) + /// + /// Process "Is a container for a set of programs". + /// + /// This interface is implemented by a custom port supplier to manage programs as a group. An IDebugProcess2 contains one or more + /// IDebugProgram2 interfaces. + /// + public sealed class AD7Process : IDebugProcess2, IDebugProcessEx2 + { + /// + /// The name and ID of the process running on target device. + /// + private readonly ProcessInfo _details; + + /// + /// The object that represents the port used in Attach to Process UI or on which the process was launched. + /// + private IDebugPort2 _port; + + private readonly bool _attaching; + + /// + /// The list of programs that are running in this process. + /// + private readonly List _listOfPrograms; + + /// + /// Constructor. + /// + /// The IDebugPort2 object that represents the port on which the process was launched. + /// The ID of the process running on the device and local path to the executable. + /// Description of the device the process is running programs on. + public AD7Process(IDebugPort2 port, ProcessInfo details, DeviceDefinition device) + { + if (port == null) + throw new ArgumentNullException("port"); + if (details == null) + throw new ArgumentNullException("details"); + if (device == null) + throw new ArgumentNullException("device"); + + _port = port; + _attaching = false; + _details = details; + Device = device; + _listOfPrograms = new List(); + UID = Guid.NewGuid(); + } + + /// + /// Constructor. + /// + /// The AD7Port object that represents the port used in Attach to Process UI. + /// The name and ID of the process running on device. + public AD7Process(AD7Port port, ProcessInfo details) + { + if (port == null) + throw new ArgumentNullException("port"); + if (port.Device == null) + throw new ArgumentOutOfRangeException("port"); + if (details == null) + throw new ArgumentNullException("details"); + + _port = port; + _attaching = true; + _details = details; + Device = port.Device; + _listOfPrograms = new List(); + UID = Guid.NewGuid(); + } + + #region Properties + + public uint ID + { + get { return _details.ID; } + } + + public Guid UID + { + get; + private set; + } + + public ProcessInfo Details + { + get { return _details; } + } + + public IDebugPort2 Port + { + get { return _port; } + } + + public DeviceDefinition Device + { + get; + private set; + } + + #endregion + + /// + /// Attaches the session debug manager (SDM) to the process. Not implemented. Currently using IDebugEngine2.Attach. + /// (http://msdn.microsoft.com/en-ca/library/bb145875.aspx) + /// + /// An IDebugEventCallback2 object that is used for debug event notification. + /// An array of GUIDs of debug engines to be used to debug programs running in the process. + /// This parameter can be a null value. + /// The number of debug engines in the rgguidSpecificEngines array and the size of the + /// rghrEngineAttach array. + /// An array of HRESULT codes returned by the debug engines. + /// VSConstants.S_OK. + public int Attach(IDebugEventCallback2 pCallback, Guid[] rgguidSpecificEngines, uint celtSpecificEngines, int[] rghrEngineAttach) + { + return VSConstants.S_OK; + } + + /// + /// Determines if the session debug manager (SDM) can detach the process. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb145567.aspx) + /// + /// VSConstants.S_OK. + public int CanDetach() + { + return VSConstants.S_OK; + } + + /// + /// Requests that the next program that is running code in this process halt and send an IDebugBreakEvent2 event object. + /// Not implemented. (http://msdn.microsoft.com/en-us/library/bb162292.aspx) + /// + /// VSConstants.S_OK. + public int CauseBreak() + { + return VSConstants.S_OK; + } + + /// + /// Detaches the debugger from this process by detaching all of the programs in the process. + /// (http://msdn.microsoft.com/en-us/library/bb162197.aspx) + /// + /// VSConstants.S_OK. + public int Detach() + { + _port = null; + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of all the programs contained by this process. + /// (http://msdn.microsoft.com/en-us/library/bb162305.aspx) + /// + /// Returns an IEnumDebugPrograms2 object that contains a list of all the programs in the process. + /// VSConstants.S_OK. + public int EnumPrograms(out IEnumDebugPrograms2 ppEnum) + { + if (_listOfPrograms.Count == 0) + { + AD7ProgramNodeAttach pn = new AD7ProgramNodeAttach(this); + _listOfPrograms.Add(pn); + } + + ppEnum = new AD7ProgramEnum(_listOfPrograms.ToArray()); + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of all the threads running in all programs in the process. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb144981.aspx) + /// + /// Returns an IEnumDebugThreads2 object that contains a list of all threads in all programs in the + /// process. + /// VSConstants.S_OK. + public int EnumThreads(out IEnumDebugThreads2 ppEnum) + { + ppEnum = null; + return VSConstants.S_OK; + } + + /// + /// Gets the name of the session that is debugging the process. [DEPRECATED. SHOULD ALWAYS RETURN E_NOTIMPL.] + /// (http://msdn.microsoft.com/en-us/library/bb146718.aspx) + /// + /// DEPRECATED. Return null. + /// This method should always return E_NOTIMPL. + public int GetAttachedSessionName(out string pbstrSessionName) + { + pbstrSessionName = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Gets a description of the process. (http://msdn.microsoft.com/en-us/library/bb145895.aspx) + /// + /// A combination of values from the PROCESS_INFO_FIELDS enumeration that specifies which fields of + /// the pProcessInfo parameter are to be filled in. + /// A PROCESS_INFO structure that is filled in with a description of the process. + /// VSConstants.S_OK. + public int GetInfo(enum_PROCESS_INFO_FIELDS fields, PROCESS_INFO[] pProcessInfo) + { + try + { + if ((fields & enum_PROCESS_INFO_FIELDS.PIF_FILE_NAME) != 0) + { + pProcessInfo[0].bstrFileName = _details.ExecutablePath; + pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_FILE_NAME; + } + if ((fields & enum_PROCESS_INFO_FIELDS.PIF_BASE_NAME) != 0) + { + pProcessInfo[0].bstrBaseName = _details.Name; + pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_BASE_NAME; + } + if ((fields & enum_PROCESS_INFO_FIELDS.PIF_TITLE) != 0) + { + pProcessInfo[0].bstrTitle = _details.ShortExecutablePath; + pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_TITLE; + } + if ((fields & enum_PROCESS_INFO_FIELDS.PIF_PROCESS_ID) != 0) + { + pProcessInfo[0].ProcessId.dwProcessId = _details.ID; + pProcessInfo[0].ProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; + pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_PROCESS_ID; + } + + if ((fields & enum_PROCESS_INFO_FIELDS.PIF_SESSION_ID) != 0) + { + //pProcessInfo[0].dwSessionId = 0; + pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_SESSION_ID; + } + if ((fields & enum_PROCESS_INFO_FIELDS.PIF_ATTACHED_SESSION_NAME) != 0) + { + //pProcessInfo[0].bstrAttachedSessionName = null; + pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_ATTACHED_SESSION_NAME; + } + if ((fields & enum_PROCESS_INFO_FIELDS.PIF_CREATION_TIME) != 0) + { + //pProcessInfo[0].CreationTime.dwHighDateTime = 0; + //pProcessInfo[0].CreationTime.dwLowDateTime = 0; + pProcessInfo[0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_CREATION_TIME; + } + + return VSConstants.S_OK; + } + catch (Exception e) + { + return EngineUtils.UnexpectedException(e); + } + } + + /// + /// Gets the name of the process. (http://msdn.microsoft.com/en-us/library/bb161270.aspx) + /// + /// A value from the GETNAME_TYPE enumeration that specifies what type of name to return. + /// Returns the name of the process. + /// VSConstants.S_OK. + public int GetName(enum_GETNAME_TYPE type, out string pbstrName) + { + pbstrName = _details.Name; + return VSConstants.S_OK; + } + + /// + /// Gets the system process identifier. (http://msdn.microsoft.com/en-us/library/bb146648.aspx) + /// + /// An AD_PROCESS_ID structure that is filled in with the system process identifier information. + /// VSConstants.S_OK. + public int GetPhysicalProcessId(AD_PROCESS_ID[] pProcessId) + { + if (_attaching) + { + // attaching to existing process on the target + pProcessId[0].dwProcessId = _details.ID; + pProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; + } + else + { + // running in app in debug + pProcessId[0].guidProcessId = UID; + pProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; + } + + return VSConstants.S_OK; + } + + /// + /// Gets the port that the process is running on. (http://msdn.microsoft.com/en-us/library/bb162121.aspx) + /// + /// Returns an IDebugPort2 object that represents the port on which the process was launched. + /// VSConstants.S_OK. + public int GetPort(out IDebugPort2 ppPort) + { + ppPort = _port; + return VSConstants.S_OK; + } + + /// + /// Gets the GUID for this process. (http://msdn.microsoft.com/en-us/library/bb161938.aspx) + /// + /// Returns the GUID for this process. + /// VSConstants.S_OK. + public int GetProcessId(out Guid pguidProcessId) + { + pguidProcessId = UID; + return VSConstants.S_OK; + } + + /// + /// Gets the server that this process is running on. Not implemented completely because _server has no value assigned to it. + /// (http://msdn.microsoft.com/en-us/library/bb147017.aspx) + /// + /// Returns an IDebugCoreServer2 object that represents the server on which this process is running. + /// VSConstants.S_OK. + public int GetServer(out IDebugCoreServer2 ppServer) + { + ppServer = null; + return VSConstants.S_OK; + } + + + /// + /// Terminates the process. Not implemented. (http://msdn.microsoft.com/en-us/library/bb146226.aspx) + /// + /// VSConstants.S_OK. + public int Terminate() + { + return VSConstants.S_OK; + } + + #region IDebugProcessEx2 Members + + /// + /// Informs the process that a session is now debugging the process. (http://msdn.microsoft.com/en-us/library/bb162300.aspx) + /// + /// A value that uniquely identifies the session attaching to this process. + /// VSConstants.S_OK. + public int Attach(IDebugSession2 session) + { + return VSConstants.S_OK; + } + + /// + /// Informs the process that a session is no longer debugging the process. (http://msdn.microsoft.com/en-us/library/bb146313.aspx) + /// + /// A value that uniquely identifies the session to detach this process from. + /// VSConstants.S_OK. + public int Detach(IDebugSession2 session) + { + return VSConstants.S_OK; + } + + /// + /// Adds program nodes for a list of debug engines. (http://msdn.microsoft.com/en-us/library/bb146990.aspx) + /// In this project, it is used only one debug engine, that's why its GUID is assigned to the guidLaunchingEngine explicitly. + /// + /// The GUID of a DE that is to be used to launch programs (and is assumed to add its own + /// program nodes). + /// Array of GUIDs of DEs for which program nodes will be added. + /// The number of GUIDs in the rgguidSpecificEngines array. + /// VSConstants.S_OK. + public int AddImplicitProgramNodes(ref Guid guidLaunchingEngine, Guid[] rgguidSpecificEngines, uint celtSpecificEngines) + { + guidLaunchingEngine = new Guid(AD7Engine.DebugEngineGuid); + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramNode.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramNode.cs new file mode 100644 index 00000000..776ba14b --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramNode.cs @@ -0,0 +1,185 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using BlackBerry.NativeCore.Debugger.Model; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class implements IDebugProgramNode2. (http://msdn.microsoft.com/en-ca/library/bb146735.aspx) + /// This interface represents a program that can be debugged. + /// A running process is viewed as a ProgramNode by VS. + /// A debug engine (DE) or a custom port supplier implements this interface to represent a program that can be debugged. + /// + public sealed class AD7ProgramNode : IDebugProgramNode2 + { + /// + /// The GUID of the hosting process. + /// + private readonly Guid _processGuid; + + private readonly ProcessInfo _details; + + /// + /// Constructor. + /// At this moment, used only for testing purposes, because GetProviderProcessData (AD7ProgramProvider.cs) needs a program node. + /// + /// The GUID for this process. + public AD7ProgramNode(Guid processGuid) + { + _processGuid = processGuid; + } + + /// + /// Constructor. + /// + /// The description of the the debugged program. + /// The GUID for this process. + /// The GUID of the VSNDK debug engine. + public AD7ProgramNode(ProcessInfo details, Guid processGuid) + { + if (details == null) + throw new ArgumentNullException("details"); + + _details = details; + _processGuid = processGuid; + } + + /// + /// Constructor. + /// + /// The process associated with the node. + public AD7ProgramNode(AD7Process process) + { + if (process == null) + throw new ArgumentNullException("process"); + if (process.Details == null) + throw new ArgumentOutOfRangeException("process"); + + _details = process.Details; + _processGuid = process.UID; + } + + #region Properties + + public string Name + { + get { return _details.Name; } + } + + #endregion + + #region IDebugProgramNode2 Members + + + /// + /// Gets the name and identifier of the DE running this program. (http://msdn.microsoft.com/en-ca/library/bb146303.aspx) + /// + /// Returns the name of the DE running the program (C++-specific: this can be a null pointer + /// indicating that the caller is not interested in the name of the engine). + /// Returns the globally unique identifier of the DE running the program (C++-specific: this can + /// be a null pointer indicating that the caller is not interested in the GUID of the engine). + /// VSConstants.S_OK. + int IDebugProgramNode2.GetEngineInfo(out string engineName, out Guid engineGuid) + { + engineName = string.Empty; + engineGuid = new Guid(AD7Engine.DebugEngineGuid); + + return VSConstants.S_OK; + } + + /// + /// Gets the system process identifier for the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb162159.aspx) + /// + /// Returns the system process identifier for the hosting process. + /// VSConstants.S_OK. + int IDebugProgramNode2.GetHostPid(AD_PROCESS_ID[] pHostProcessId) + { + // According to the MSDN documentation (http://msdn.microsoft.com/en-us/library/bb162159.aspx), + // it should return the process id of the hosting process, but what is expected is the program ID... + pHostProcessId[0].ProcessIdType = (uint) enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; + pHostProcessId[0].guidProcessId = _processGuid; + + return VSConstants.S_OK; + } + + /// + /// Gets the name of the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb145135.aspx) + /// + /// A value from the GETHOSTNAME_TYPE enumeration that specifies the type of name to return. + /// Returns the name of the hosting process. + /// VSConstants.S_OK. + int IDebugProgramNode2.GetHostName(enum_GETHOSTNAME_TYPE type, out string processName) + { + if (type == enum_GETHOSTNAME_TYPE.GHN_FILE_NAME) + processName = "(BB-pid = " + _details.ID + ") " + _details.ExecutablePath; + else + processName = _details.Name; + return VSConstants.S_OK; + } + + /// + /// Gets the name of a program. (http://msdn.microsoft.com/en-us/library/bb145928.aspx) + /// + /// Returns the name of the program. + /// VSConstants.S_OK. + int IDebugProgramNode2.GetProgramName(out string programName) + { + programName = _details.Name; + return VSConstants.S_OK; + } + + #endregion + + #region Deprecated interface methods + // These methods are not called by the Visual Studio debugger, so they don't need to be implemented + + /// + /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161399.aspx) + /// + /// The IDebugProgram2 interface that represents the program to attach to. + /// The IDebugEventCallback2 interface to be used to send debug events to the SDM. + /// A value from the ATTACH_REASON enumeration that specifies the reason for attaching. + /// VSConstants.E_NOTIMPL. + int IDebugProgramNode2.Attach_V7(IDebugProgram2 program, IDebugEventCallback2 pCallback, uint reason) + { + return EngineUtils.NotImplemented(); + } + + /// + /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161803.aspx) + /// + /// VSConstants.E_NOTIMPL. + int IDebugProgramNode2.DetachDebugger_V7() + { + return EngineUtils.NotImplemented(); + } + + /// + /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161297.aspx) + /// + /// Returns the name of the machine in which the program is running. + /// VSConstants.E_NOTIMPL. + int IDebugProgramNode2.GetHostMachineName_V7(out string hostMachineName) + { + hostMachineName = null; + return EngineUtils.NotImplemented(); + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramNodeAttach.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramNodeAttach.cs new file mode 100644 index 00000000..1eb4d9f0 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramNodeAttach.cs @@ -0,0 +1,404 @@ +using System; +using System.Diagnostics; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class is used only when the user wants to Attach to a running process and it implements: + /// - IDebugProgramNode2. (http://msdn.microsoft.com/en-ca/library/bb146735.aspx) + /// - and IDebugProgram2. (http://msdn.microsoft.com/en-us/library/bb147004.aspx) + /// + /// The Debug Engine does not use this class. It uses AD7ProgramNode.cs. This class is used only to represent each of the running + /// processes that can be attached to the debug engine. When the debug engine attaches to a running process, an AD7ProgramNode + /// class is used to represent the chosen running program. That's why some methods were not implemented. + /// + /// This interface represents a program that can be debugged. + /// A running process is viewed as a ProgramNode by VS. + /// A debug engine (DE) or a custom port supplier implements this interface to represent a program that can be debugged. + /// + sealed class AD7ProgramNodeAttach : IDebugProgramNode2, IDebugProgram2 + { + /// + /// The hosting process. + /// + private readonly AD7Process _process; + + /// + /// Constructor. + /// + /// The process on the target device engine is supposed to attach. + /// The GUID of a debug engine. + public AD7ProgramNodeAttach(AD7Process process) + { + if (process == null) + throw new ArgumentNullException("process"); + if (process.Details == null) + throw new ArgumentOutOfRangeException("process"); + + _process = process; + } + + #region Properties + + public AD7Process Process + { + get { return _process; } + } + + #endregion + + #region IDebugProgram2 Members + + /// + /// Determines if a debug engine (DE) can detach from the program. (http://msdn.microsoft.com/en-us/library/bb161967.aspx) + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// VSConstants.S_OK. + public int CanDetach() + { + // The VSNDK debug engine always supports detach + return VSConstants.S_OK; + } + + /// + /// Requests that the program stop execution the next time one of its threads attempts to run. The debugger calls CauseBreak + /// when the user clicks on the pause button in VS. The debugger should respond by entering breakmode. + /// (http://msdn.microsoft.com/en-us/library/bb145018.aspx) + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// VSConstants.S_OK. + public int CauseBreak() + { + return VSConstants.S_OK; + } + + /// + /// Continues running this program from a stopped state. Any previous execution state (such as a step) is preserved, and + /// the program starts executing again. (http://msdn.microsoft.com/en-us/library/bb162148.aspx). + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// An IDebugThread2 object that represents the thread. + /// VSConstants.S_OK. + public int Continue(IDebugThread2 thread) + { + // This method is not called by the debug engine. + return VSConstants.S_OK; + } + + /// + /// Detaches a debug engine from the program. (http://msdn.microsoft.com/en-us/library/bb146228.aspx) + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// VSConstants.S_OK. + public int Detach() + { + // This method is not called by the debug engine. + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of the code contexts for a given position in a source file. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb145902.aspx) + /// + /// An object representing an abstract position in a source file known to the IDE. + /// Returns an IEnumDebugCodeContexts2 object that contains a list of the code contexts. + /// Not implemented. + public int EnumCodeContexts(IDebugDocumentPosition2 docPos, out IEnumDebugCodeContexts2 ppEnum) + { + ppEnum = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Retrieves a list of the code paths for a given position in a source file. EnumCodePaths is used for the step-into specific + /// feature -- right click on the current statement and decide which function to step into. This is not something that the + /// VSNDK debug engine supports. (http://msdn.microsoft.com/en-us/library/bb162326.aspx) + /// + /// The word under the cursor in the Source or Disassembly view in the IDE. + /// An IDebugCodeContext2 object representing the current code context. + /// An IDebugStackFrame2 object representing the stack frame associated with the current breakpoint. + /// Nonzero (TRUE) if in the Source view, or zero (FALSE) if in the Disassembly view. + /// Returns an IEnumCodePaths2 object containing a list of the code paths. + /// Returns an IDebugCodeContext2 object representing an additional code context to be set as a + /// breakpoint in case the chosen code path is skipped. This can happen in the case of a short-circuited Boolean expression, + /// for example. + /// VSConstants.E_NOTIMPL. + public int EnumCodePaths(string hint, IDebugCodeContext2 start, IDebugStackFrame2 frame, int fSource, out IEnumCodePaths2 pathEnum, out IDebugCodeContext2 safetyContext) + { + pathEnum = null; + safetyContext = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Retrieves a list of the modules that this program has loaded and is executing. + /// (http://msdn.microsoft.com/en-us/library/bb146980.aspx) + /// + /// Returns an IEnumDebugModules2 object that contains a list of the modules. + /// VSConstants.S_OK. + public int EnumModules(out IEnumDebugModules2 ppEnum) + { + // Setting ppEnum to null because we are not adding/working with this feature now. It was causing an error + // when opening Threads Window and ppEnum = new AD7ModuleEnum(new[] { m_module }). + ppEnum = null; + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of the threads that are running in the program. (http://msdn.microsoft.com/en-us/library/bb145110.aspx) + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// Returns an IEnumDebugThreads2 object that contains a list of the threads. + /// If successful, returns S_OK; otherwise, returns an error code. + public int EnumThreads(out IEnumDebugThreads2 ppEnum) + { + ppEnum = null; + return VSConstants.S_OK; + } + + /// + /// Gets the program's properties. The VSNDK debug engine does not support this. + /// (http://msdn.microsoft.com/en-us/library/bb161801.aspx) + /// + /// Returns an IDebugProperty2 object that represents the program's properties. + /// Not implemented. + public int GetDebugProperty(out IDebugProperty2 ppProperty) + { + ppProperty = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Gets the disassembly stream for this program or a part of this program. + /// The sample engine does not support dissassembly so it returns E_NOTIMPL + /// + /// Specifies a value from the DISASSEMBLY_STREAM_SCOPE enumeration that defines the scope of the + /// disassembly stream. + /// An object that represents the position of where to start the disassembly stream. + /// Returns an IDebugDisassemblyStream2 object that represents the disassembly stream. + /// VSConstants.E_NOTIMPL. + public int GetDisassemblyStream(enum_DISASSEMBLY_STREAM_SCOPE scope, IDebugCodeContext2 codeContext, out IDebugDisassemblyStream2 disassemblyStream) + { + disassemblyStream = null; + return EngineUtils.NotImplemented(); + } + + /// + /// This method gets the Edit and Continue (ENC) update for this program. A custom debug engine always returns E_NOTIMPL + /// + /// Returns an internal interface that can be used to update this program. + /// VSConstants.S_OK. + public int GetENCUpdate(out object update) + { + // The VSNDK debug engine does not participate in managed edit & continue. + update = null; + return VSConstants.S_OK; + } + + /// + /// Retrieves the memory bytes occupied by the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145291.aspx) + /// + /// Returns an IDebugMemoryBytes2 object that represents the memory bytes of the program. + /// Not implemented. + public int GetMemoryBytes(out IDebugMemoryBytes2 ppMemoryBytes) + { + ppMemoryBytes = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Gets the name of the program. The name returned by this method is always a friendly, user-displayable name that describes + /// the program. (http://msdn.microsoft.com/en-us/library/bb161279.aspx) + /// + /// Returns the name of the program. + /// VSConstants.S_OK. + public int GetName(out string programName) + { + programName = _process.Details != null ? _process.Details.Name : string.Empty; + return VSConstants.S_OK; + } + + /// + /// Gets a GUID for this program. A debug engine (DE) must return the program identifier originally passed to the + /// IDebugProgramNodeAttach2::OnAttach or IDebugEngine2::Attach methods. This allows identification of the program + /// across debugger components. (http://msdn.microsoft.com/en-us/library/bb145581.aspx) + /// + /// Returns the GUID for this program. + /// VSConstants.S_OK. + public int GetProgramId(out Guid guidProgramId) + { + guidProgramId = _process.UID; + return VSConstants.S_OK; + } + + /// + /// Performs a step. This method is deprecated. Use the IDebugProcess3::Step method instead. + /// (http://msdn.microsoft.com/en-us/library/bb162134.aspx) + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// An IDebugThread2 object that represents the thread being stepped. + /// A value from the STEPKIND enumeration that specifies the kind of step. + /// A value from the STEPUNIT enumeration that specifies the unit of step. + /// If successful, returns S_OK; otherwise, returns an error code. + public int Step(IDebugThread2 thread, enum_STEPKIND stepKind, enum_STEPUNIT step) + { + return VSConstants.S_OK; + } + + /// + /// Terminates the program. (http://msdn.microsoft.com/en-us/library/bb145919.aspx) + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// VSConstants.S_OK. + public int Terminate() + { + return VSConstants.S_OK; + } + + /// + /// Writes a dump to a file. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145827.aspx) + /// + /// A value from the DUMPTYPE enumeration that specifies the type of dump, for example, short or + /// long. + /// The URL to write the dump to. Typically, this is in the form of file://c:\path\filename.ext, + /// but may be any valid URL. + /// VSConstants.E_NOTIMPL. + public int WriteDump(enum_DUMPTYPE type, string dumpUrl) + { + // The VSNDK debugger does not support creating or reading mini-dumps. + return EngineUtils.NotImplemented(); + } + + /// + /// Get the process that this program is running in. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145293.aspx) + /// + /// Returns the IDebugProcess2 interface that represents the process. + /// VSConstants.E_NOTIMPL. + public int GetProcess(out IDebugProcess2 ppProcess) + { + ppProcess = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Attaches to the program. Not implemented. (http://msdn.microsoft.com/en-us/library/bb161973.aspx) + /// + /// An IDebugEventCallback2 object to be used for debug event notification. + /// VSConstants.E_NOTIMPL. + public int Attach(IDebugEventCallback2 callback) + { + return EngineUtils.NotImplemented(); + } + + /// + /// Continues running this program from a stopped state. Any previous execution state (such as a step) is cleared, and the + /// program starts executing again. Not implemented. (http://msdn.microsoft.com/en-us/library/bb162315.aspx) + /// Not implemented because this class is not used by the debug engine. Read the description of this class at the top. + /// + /// VSConstants.S_OK. + public int Execute() + { + return VSConstants.S_OK; + } + + #endregion + + #region IDebugProgramNode2 Members + + /// + /// Gets the name and GUID of the debug engine running this program. (http://msdn.microsoft.com/en-ca/library/bb146303.aspx) + /// + /// Returns the name of the DE running this program. + /// Returns the GUID of the DE running this program. + /// VSConstants.S_OK. + public int GetEngineInfo(out string engineName, out Guid engineGuid) + { + engineName = _process.Device.Architecture; + engineGuid = new Guid(AD7Engine.DebugEngineGuid); + + return VSConstants.S_OK; + } + + /// + /// Gets the system process identifier for the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb162159.aspx) + /// + /// Returns the system process identifier for the hosting process. + /// VSConstants.S_OK. + public int GetHostPid(AD_PROCESS_ID[] pHostProcessId) + { + // According to the MSDN documentation (http://msdn.microsoft.com/en-us/library/bb162159.aspx), + // it should return the process id of the hosting process, but what is expected is the program ID... + pHostProcessId[0].ProcessIdType = (uint) enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; + pHostProcessId[0].guidProcessId = _process.UID; + + return VSConstants.S_OK; + } + + /// + /// Gets the name of the process hosting a program. (http://msdn.microsoft.com/en-us/library/bb145135.aspx) + /// + /// A value from the GETHOSTNAME_TYPE enumeration that specifies the type of name to return. + /// Returns the name of the hosting process. + /// VSConstants.S_OK. + public int GetHostName(enum_GETHOSTNAME_TYPE type, out string processName) + { + if (type == enum_GETHOSTNAME_TYPE.GHN_FILE_NAME) + processName = "(BB-pid = " + _process.Details.ID + ") " + _process.Details.ExecutablePath; + else + processName = _process.Details.Name; + return VSConstants.S_OK; + } + + /// + /// Gets the name of a program. (http://msdn.microsoft.com/en-us/library/bb145928.aspx) + /// + /// Returns the name of the program. + /// VSConstants.S_OK. + int IDebugProgramNode2.GetProgramName(out string programName) + { + programName = _process.Details.Name; + return VSConstants.S_OK; + } + + #endregion + + #region Deprecated interface methods + // These methods are not called by the Visual Studio debugger, so they don't need to be implemented + + /// + /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161399.aspx) + /// + /// The IDebugProgram2 interface that represents the program to attach to. + /// The IDebugEventCallback2 interface to be used to send debug events to the SDM. + /// A value from the ATTACH_REASON enumeration that specifies the reason for attaching. + /// VSConstants.E_NOTIMPL. + public int Attach_V7(IDebugProgram2 program, IDebugEventCallback2 callback, uint reason) + { + return EngineUtils.NotImplemented(); + } + + /// + /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161803.aspx) + /// + /// VSConstants.E_NOTIMPL. + public int DetachDebugger_V7() + { + return EngineUtils.NotImplemented(); + } + + /// + /// DEPRECATED. DO NOT USE. (http://msdn.microsoft.com/en-us/library/bb161297.aspx) + /// + /// Returns the name of the machine in which the program is running. + /// VSConstants.E_NOTIMPL. + public int GetHostMachineName_V7(out string hostMachineName) + { + hostMachineName = null; + return EngineUtils.NotImplemented(); + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramProvider.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramProvider.cs new file mode 100644 index 00000000..789d7480 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7ProgramProvider.cs @@ -0,0 +1,136 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class implements IDebugProgramProvider2. (http://msdn.microsoft.com/en-us/library/bb161298.aspx) + /// This registered interface allows the session debug manager (SDM) to obtain information about programs + /// that have been "published" through the IDebugProgramPublisher2 interface. + /// + /// Partially implemented and not used at this moment. + /// + [ComVisible(true)] + [Guid(ClassGuid)] + public sealed class AD7ProgramProvider : IDebugProgramProvider2 + { + public const string ClassGuid = "AD06FD46-C790-4D5C-A274-8815DF9511B8"; + public const string ClassName = "BlackBerry.DebugEngine.AD7ProgramProvider"; + + #region IDebugProgramProvider2 Members + + /// + /// Obtains information about programs running, filtered in a variety of ways. + /// (http://msdn.microsoft.com/en-us/library/bb147025.aspx) + /// + /// A combination of flags from the PROVIDER_FLAGS enumeration. + /// The port the calling process is running on. + /// An AD_PROCESS_ID structure holding the ID of the process that contains the program in question. + /// An array of GUIDs for debug engines assigned to debug this process (these will be used to filter + /// the programs that are actually returned based on what the supplied engines support; if no engines are specified, then all + /// programs will be returned). + /// A PROVIDER_PROCESS_DATA structure that is filled in with the requested information. + /// If successful, returns S_OK; otherwise, returns VSConstants.S_FALSE. + int IDebugProgramProvider2.GetProviderProcessData(enum_PROVIDER_FLAGS flags, IDebugDefaultPort2 port, AD_PROCESS_ID processId, CONST_GUID_ARRAY engineFilter, PROVIDER_PROCESS_DATA[] processArray) + { + processArray[0] = new PROVIDER_PROCESS_DATA(); + + if (((uint)flags & (uint)enum_PROVIDER_FLAGS.PFLAG_GET_PROGRAM_NODES) != 0) + { + // The debugger is asking the engine to return the program nodes it can debug. The VSNDK debug engine claims that it can + // debug all processes, and returns exactly one program node for each process. A full-featured debugger may wish to + // examine the target process and determine if it understands how to debug it. + + IDebugProgramNode2 node = new AD7ProgramNode(processId.guidProcessId); + + IntPtr[] programNodes = { Marshal.GetComInterfaceForObject(node, typeof(IDebugProgramNode2)) }; + + IntPtr destinationArray = Marshal.AllocCoTaskMem(IntPtr.Size * programNodes.Length); + Marshal.Copy(programNodes, 0, destinationArray, programNodes.Length); + + processArray[0].Fields = enum_PROVIDER_FIELDS.PFIELD_PROGRAM_NODES; + processArray[0].ProgramNodes.Members = destinationArray; + processArray[0].ProgramNodes.dwCount = (uint)programNodes.Length; + + return VSConstants.S_OK; + } + + return VSConstants.S_FALSE; + } + + + /// + /// Gets a program node, given a specific process ID. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb162155.aspx) + /// + /// A combination of flags from the PROVIDER_FLAGS enumeration. + /// The port the calling process is running on. + /// An AD_PROCESS_ID structure holding the ID of the process that contains the program in question. + /// GUID of the debug engine that the program is attached to (if any). + /// ID of the program for which to get the program node. + /// An IDebugProgramNode2 object representing the requested program node. + /// VSConstants.E_NOTIMPL. + int IDebugProgramProvider2.GetProviderProgramNode(enum_PROVIDER_FLAGS flags, IDebugDefaultPort2 port, AD_PROCESS_ID processId, ref Guid guidEngine, ulong programId, out IDebugProgramNode2 programNode) + { + // This method is used for Just-In-Time debugging support, which this program provider does not support + programNode = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Establishes a locale for any language-specific resources needed by the DE. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/bb161383.aspx) + /// + /// Language ID to establish. For example, 1033 for English. + /// VSConstants.S_OK. + int IDebugProgramProvider2.SetLocale(ushort langID) + { + return VSConstants.S_OK; + } + + /// + /// Establishes a callback to watch for provider events associated with specific kinds of processes, allowing the process to + /// be notified of port events. Not implemented. (http://msdn.microsoft.com/en-us/library/bb145594.aspx) + /// + /// A combination of flags from the PROVIDER_FLAGS enumeration. + /// The port the calling process is running on. + /// An AD_PROCESS_ID structure holding the ID of the process that contains the program in question. + /// An array of GUIDs of debug engines associated with the process. + /// GUID of the debug engine that launched this process (if any). + /// An IDebugPortNotify2 object that receives the event notifications. + /// VSConstants.S_OK. + int IDebugProgramProvider2.WatchForProviderEvents(enum_PROVIDER_FLAGS flags, IDebugDefaultPort2 port, AD_PROCESS_ID processId, CONST_GUID_ARRAY engineFilter, ref Guid guidLaunchingEngine, IDebugPortNotify2 eventCallback) + { + // The VSNDK debug engine is a native debugger, and can therefore always provide a program node + // in GetProviderProcessData. Non-native debuggers may wish to implement this method as a way + // of monitoring the process before code for their runtime starts. For example, if implementing a + // 'foo script' debug engine, one could attach to a process which might eventually run 'foo script' + // before this 'foo script' started. + // + // To implement this method, an engine would monitor the target process and call AddProgramNode + // when the target process started running code which was debuggable by the engine. The + // enum_PROVIDER_FLAGS.PFLAG_ATTACHED_TO_DEBUGGEE flag indicates if the request is to start + // or stop watching the process. + + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Property.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Property.cs new file mode 100644 index 00000000..bd7c9eba --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Property.cs @@ -0,0 +1,363 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System.Collections; + +namespace BlackBerry.DebugEngine +{ + /// + /// An implementation of IDebugProperty2. (http://msdn.microsoft.com/en-ca/library/bb161287.aspx) + /// This interface represents a stack frame property, a program document property, or some other property. + /// The property is usually the result of an expression evaluation. + /// + sealed class AD7Property : IDebugProperty2 + { + /// + /// Object that contains all information about a variable / expression. + /// + private readonly VariableInfo _variableInfo; + + /// + /// Object that contains all information about a stack frame. + /// + private readonly AD7StackFrame _stackFrame; + + /// + /// Constructor. + /// + /// Contains all information about a variable / expression. + public AD7Property(AD7StackFrame vi) + { + _stackFrame = vi; + } + + /// + /// Constructor. + /// + /// Contains all information about a variable / expression. + public AD7Property(VariableInfo vi) + { + _variableInfo = vi; + } + + /// + /// Construct a DEBUG_PROPERTY_INFO representing this local or parameter. + /// + /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which variables are + /// to be filled in. + /// The Property info. + public DEBUG_PROPERTY_INFO ConstructDebugPropertyInfo(enum_DEBUGPROP_INFO_FLAGS flags) + { + DEBUG_PROPERTY_INFO propertyInfo = new DEBUG_PROPERTY_INFO(); + + if (_variableInfo != null) + { + string name = _variableInfo._name; + if ((flags & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME) != 0) + { + propertyInfo.bstrFullName = name; + propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME)); + } + + if ((flags & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME) != 0) + { + propertyInfo.bstrName = name; + propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME)); + } + + if ((flags & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE) != 0) + { + propertyInfo.bstrType = _variableInfo._type; + propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE)); + } + + if ((flags & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE) != 0) + { + propertyInfo.bstrValue = _variableInfo._value; + propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE)); + } + + if ((flags & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB) != 0) + { + if (_variableInfo._children != null) + { + propertyInfo.dwAttrib |= (enum_DBG_ATTRIB_FLAGS)DBG_ATTRIB_FLAGS.DBG_ATTRIB_OBJ_IS_EXPANDABLE; + } + } + + // If the debugger has asked for the property, or the property has children (meaning it is a pointer in the sample) + // then set the pProperty field so the debugger can call back when the chilren are enumerated. + if ((flags & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP) != 0 || _variableInfo._children != null) + { + propertyInfo.pProperty = this; + propertyInfo.dwFields = (enum_DEBUGPROP_INFO_FLAGS)((uint)propertyInfo.dwFields | (uint)(DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP)); + } + + } + return propertyInfo; + } + + #region IDebugProperty2 Members + + /// + /// Enumerates the children of a property. This provides support for dereferencing pointers, displaying members of an array, or + /// fields of a class or struct. (http://msdn.microsoft.com/en-us/library/bb161791.aspx) + /// + /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in + /// the enumerated DEBUG_PROPERTY_INFO structures are to be filled in. + /// Specifies the radix to be used in formatting any numerical information. + /// GUID of the filter used with the dwAttribFilter and pszNameFilter parameters to select which + /// DEBUG_PROPERTY_INFO children are to be enumerated. For example, guidFilterLocals filters for local variables. + /// A combination of flags from the DBG_ATTRIB_FLAGS enumeration that specifies what type of + /// objects to enumerate, for example DBG_ATTRIB_METHOD for all methods that might be children of this property. Used in + /// combination with the guidFilter and pszNameFilter parameters. + /// The name of the filter used with the guidFilter and dwAttribFilter parameters to select which + /// DEBUG_PROPERTY_INFO children are to be enumerated. For example, setting this parameter to "MyX" filters for all children + /// with the name "MyX." + /// Specifies the maximum time, in milliseconds, to wait before returning from this method. Use + /// INFINITE to wait indefinitely. + /// Returns an IEnumDebugPropertyInfo2 object containing a list of the child properties. + /// If successful, returns S_OK; otherwise returns S_FALSE. + public int EnumChildren(enum_DEBUGPROP_INFO_FLAGS flags, uint radix, ref Guid guidFilter, enum_DBG_ATTRIB_FLAGS attributesFilter, string nameFilter, uint timeout, out IEnumDebugPropertyInfo2 ppEnum) + { + ppEnum = null; + + if (_variableInfo != null) + { + if (_variableInfo._children != null) + { + if (_variableInfo._children.Count == 0) + { + // This is an array, struct, union, or pointer. + // Create a variable object so we can list this variable's children. + + // Some VS variable names cannot be used by GDB. When that happens, it is added the prefix VsNdK_ to the GDB variable + // name and it is stored in the GDBNames array. At the same time, the VS name is stored in the VSNames array using the + // same index position. This bool variable just indicate if this prefix is used or not. + bool hasVsNDK; + string numChildren = AD7StackFrame._dispatcher.CreateVariable(_variableInfo._name, out hasVsNDK); + + ArrayList GDBNames = new ArrayList(); + ArrayList VSNames = new ArrayList(); + + if (hasVsNDK) + { + _variableInfo._GDBName = "VsNdK_" + _variableInfo._name; + GDBNames.Add("VsNdK_" + _variableInfo._name); + VSNames.Add(_variableInfo._name); + } + + try // Catch non-numerical data + { + if (Convert.ToInt32(numChildren) > 0) // If the variable has children evaluate + { + if (_variableInfo._type.Contains("struct")) + if (_variableInfo._type[_variableInfo._type.Length - 1] == '*') + _variableInfo.ListChildren(AD7StackFrame._dispatcher, "*", GDBNames, VSNames, hasVsNDK, null); + else if (_variableInfo._type.Contains("[")) + _variableInfo.ListChildren(AD7StackFrame._dispatcher, "struct[]", GDBNames, VSNames, hasVsNDK, null); + else + _variableInfo.ListChildren(AD7StackFrame._dispatcher, "struct", GDBNames, VSNames, hasVsNDK, null); + else if (_variableInfo._type.Contains("[")) + _variableInfo.ListChildren(AD7StackFrame._dispatcher, "[]", GDBNames, VSNames, hasVsNDK, null); + else if (_variableInfo._type.Contains("*")) + _variableInfo.ListChildren(AD7StackFrame._dispatcher, "*", GDBNames, VSNames, hasVsNDK, null); + else + _variableInfo.ListChildren(AD7StackFrame._dispatcher, "", GDBNames, VSNames, hasVsNDK, null); + + } + } + catch (FormatException) + { + } + AD7StackFrame._dispatcher.DeleteVariable(_variableInfo._name, hasVsNDK); + } + DEBUG_PROPERTY_INFO[] properties = new DEBUG_PROPERTY_INFO[_variableInfo._children.Count]; + int i = 0; + foreach (VariableInfo child in _variableInfo._children) + { + VariableInfo.EvaluateExpression(child._name, out child._value, child._GDBName); + properties[i] = new AD7Property(child).ConstructDebugPropertyInfo(flags); + i++; + } + ppEnum = new AD7PropertyEnum(properties); + return VSConstants.S_OK; + } + } + else if (_stackFrame != null) + { + uint elementsReturned; + _stackFrame.CreateLocalsPlusArgsProperties(flags, out elementsReturned, out ppEnum); + return VSConstants.S_OK; + } + + return VSConstants.S_FALSE; + } + + /// + /// Returns the property that describes the most-derived property of a property. + /// (http://msdn.microsoft.com/en-ca/library/bb161781.aspx) + /// This is called to support object oriented languages. It allows the debug engine to return an IDebugProperty2 for the + /// most-derived object in a hierarchy. + /// The VSNDK debug engine does not support this. Not implemented. + /// + /// Returns an IDebugProperty2 object that represents the derived-most property. + /// Not implemented. + public int GetDerivedMostProperty(out IDebugProperty2 ppDerivedMost) + { + ppDerivedMost = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Returns the extended information of a property. (http://msdn.microsoft.com/en-ca/library/bb145070.aspx) + /// This method exists for the purpose of retrieving information that does not lend itself to being retrieved by calling the + /// IDebugProperty2::GetPropertyInfo method. This includes information about custom viewers, managed type slots and other + /// information. + /// The VSNDK debug engine does not support this. Not implemented. + /// + /// GUID that determines the type of extended information to be retrieved. + /// Returns a VARIANT (C++) or object (C#) that can be used to retrieve the extended property + /// information. For example, this parameter might return an IUnknown interface that can be queried for an IDebugDocumentText2 + /// interface. + /// Not implemented. + public int GetExtendedInfo(ref Guid guidExtendedInfo, out object pExtendedInfo) + { + pExtendedInfo = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Returns the memory bytes that compose the value of a property. (http://msdn.microsoft.com/en-ca/library/bb161360.aspx) + /// Not implemented. + /// + /// Returns an IDebugMemoryBytes2 object that can be used to retrieve the memory that contains + /// the value of the property. + /// Not implemented. + public int GetMemoryBytes(out IDebugMemoryBytes2 ppMemoryBytes) + { + ppMemoryBytes = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Returns the memory context for a property value. (http://msdn.microsoft.com/en-ca/library/bb147028.aspx) + /// Not implemented. + /// + /// Returns the IDebugMemoryContext2 object that represents the memory associated with this property. + /// Not implemented. + public int GetMemoryContext(out IDebugMemoryContext2 ppMemory) + { + ppMemory = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Returns the parent of a property. (http://msdn.microsoft.com/en-ca/library/bb146184.aspx) + /// Not implemented. + /// + /// Returns an IDebugProperty2 object that represents the parent of the property. + /// Not implemented. + public int GetParent(out IDebugProperty2 ppParent) + { + ppParent = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Fills in a DEBUG_PROPERTY_INFO structure that describes a property. (http://msdn.microsoft.com/en-ca/library/bb145852.aspx) + /// + /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields are to + /// be filled out in the pPropertyInfo structure. + /// Radix to be used in formatting any numerical information. + /// Specifies the maximum time, in milliseconds, to wait before returning from this method. Use + /// INFINITE to wait indefinitely. + /// Reserved for future use; set to a null value. + /// Reserved for future use; set to zero. + /// A DEBUG_PROPERTY_INFO structure that is filled in with the description of the property. + /// VSConstants.S_OK. + public int GetPropertyInfo(enum_DEBUGPROP_INFO_FLAGS flags, uint radix, uint timeout, IDebugReference2[] rgpArgs, uint argCount, DEBUG_PROPERTY_INFO[] pPropertyInfo) + { + pPropertyInfo[0] = new DEBUG_PROPERTY_INFO(); + pPropertyInfo[0] = ConstructDebugPropertyInfo(flags); + + return VSConstants.S_OK; + } + + /// + /// Returns a reference to the property's value. IDebugProperty2 represents a property, while IDebugReference2 represents a + /// reference to a property, typically a reference to an object in the program being debugged. Not implemented. + /// (http://msdn.microsoft.com/en-ca/library/bb145600.aspx) + /// + /// Returns an IDebugReference2 object representing a reference to the property's value. + /// Not implemented. + public int GetReference(out IDebugReference2 ppReference) + { + ppReference = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Returns the size, in bytes, of the property value. Not implemented. (http://msdn.microsoft.com/en-ca/library/bb145093.aspx) + /// + /// Returns the size, in bytes, of the property value. + /// Not implemented. + public int GetSize(out uint pSize) + { + pSize = 0; + return EngineUtils.NotImplemented(); + } + + /// + /// Sets the value of the property from the value of a given reference. (http://msdn.microsoft.com/en-ca/library/bb145613.aspx) + /// The debugger will call this when the user tries to edit the property's values. As the sample has set the read-only flag on + /// its properties, this should not be called. + /// Not implemented. + /// + /// An array of arguments to pass to the managed code property setter. If the property setter does not + /// take arguments or if this IDebugProperty2 object does not refer to such a property setter, rgpArgs should be a null value. + /// This parameter is typically a null value. + /// The number of arguments in the rgpArgs array. + /// A reference, in the form of an IDebugReference2 object, to the value to use to set this property. + /// How long to take to set the value, in milliseconds. A typical value is INFINITE. This affects + /// the length of time that any possible evaluation can take. + /// Not implemented. + public int SetValueAsReference(IDebugReference2[] rgpArgs, uint argCount, IDebugReference2 value, uint timeout) + { + return EngineUtils.NotImplemented(); + } + + /// + /// Sets the value of a property from a given string. (http://msdn.microsoft.com/en-ca/library/bb160956.aspx) + /// The debugger will call this when the user tries to edit the property's values in one of the debugger windows. + /// + /// A string containing the value to be set. + /// A radix to be used in interpreting any numerical information. This can be 0 to attempt to determine + /// the radix automatically. + /// Specifies the maximum time, in milliseconds, to wait before returning from this method. Use + /// INFINITE to wait indefinitely. + /// VSConstants.S_OK. + public int SetValueAsString(string value, uint radix, uint timeout) + { + string result; + VariableInfo.EvaluateExpression(_variableInfo._name + "=" + value, out result, null); + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7StackFrame.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7StackFrame.cs new file mode 100644 index 00000000..756c7f55 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7StackFrame.cs @@ -0,0 +1,810 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections; +using BlackBerry.NativeCore.Debugger; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// Represents a logical stack frame on the thread stack. + /// + /// It implements: + /// + /// IDebugStackFrame2: Represents a single stack frame in a call stack in a particular thread. + /// (http://msdn.microsoft.com/en-us/library/bb161683.aspx) + /// + /// IDebugExpressionContext: Represents a context for expression evaluation, which allows expression evaluation and watch windows. + /// (http://msdn.microsoft.com/en-ca/library/bb146178.aspx) + /// + public sealed class AD7StackFrame : IDebugStackFrame2, IDebugExpressionContext2 + { + /// + /// The class that manages debug events for the debug engine. + /// + public static EventDispatcher _dispatcher; + + /// + /// The AD7Engine object that represents the DE. + /// + public readonly AD7Engine _engine; + + /// + /// Represents the thread for this stack frame. + /// + public readonly AD7Thread _thread; + + /// + /// The short path file name that contains the source code of this stack frame. + /// + private readonly string _documentName; + + /// + /// The function name associated to this stack frame. + /// + public string _functionName = ""; + + /// + /// Represents the current position (line number) in m_documentName. + /// + private readonly uint _lineNum; + + /// + /// Boolean value that indicates if this stack frame has an associated source code to present. + /// + private readonly bool _hasSource; + + /// + /// The current context's address. + /// + private readonly uint _address; + + /// + /// List of variables that we want to filter from the locals window. + /// + private string[] _variableFilter = { "__func__" }; + + /// + /// Contains the locals variables to this stack frame. + /// + public ArrayList _locals; + + /// + /// Contains the parameters used to call the method/function that originated this stack frame. + /// + public ArrayList _arguments; + + /// + /// Search the __stackframes cache for the internal representation of the stack frame associated to the GDB frameInfo + /// information. If successful, returns the stack frame; otherwise, creates a new one and return it. + /// + /// The AD7Engine object that represents the DE. + /// Represents the thread for this stack frame. + /// Array of strings with the information provided by GDB about this stack frame. + /// Boolean value that indicates if a new object for this stack frame was created or not. + /// Returns the created/found stack frame. + public static AD7StackFrame Create(AD7Engine engine, AD7Thread thread, string[] frameInfo, ref bool created) + { + created = false; + if (thread.__stackFrames != null) + { + foreach (AD7StackFrame frame in thread.__stackFrames) + { + if (frame._documentName != null && frame._functionName != null) + { + if (frame._documentName == frameInfo[3] && frame._functionName == frameInfo[2]) // frameInfo[2] = func, frameInfo[3] = file + return frame; + } + } + } + else + thread.__stackFrames = new ArrayList(); + + AD7StackFrame newFrame = new AD7StackFrame(engine, thread, frameInfo); + thread.__stackFrames.Add(newFrame); + created = true; + return newFrame; + } + + /// + /// Constructor. + /// + /// The AD7Engine object that represents the DE. + /// Represents the thread for this stack frame. + /// Array of strings with the information provided by GDB about this stack frame. + public AD7StackFrame(AD7Engine engine, AD7Thread thread, string[] frameInfo) + { + _lineNum = 0; + _engine = engine; + _thread = thread; + _dispatcher = _engine.EventDispatcher; + + uint level = Convert.ToUInt32(frameInfo[0]); + string address = frameInfo[1]; + _functionName = frameInfo[2]; + _documentName = frameInfo[3]; + + if (!uint.TryParse(frameInfo[4], out _lineNum)) + { + _lineNum = 0; + } + + _locals = new ArrayList(); + _arguments = new ArrayList(); + _hasSource = _lineNum != 0; + ArrayList evaluatedVars = new ArrayList(); + + // Add the variable filter list to the evaluatedVars list. + // Causes named variables to be ignored. + evaluatedVars.AddRange(_variableFilter); + + if (address.StartsWith("0x")) + address = address.Remove(0, 2); + _address = uint.Parse(address, System.Globalization.NumberStyles.AllowHexSpecifier); + + // Query GDB for parameters and locals. + string variablesResponse = _engine.EventDispatcher.GetVariablesForFrame(level, _thread._id).Replace("#;;;", ""); + if (variablesResponse == null || variablesResponse == "ERROR" || variablesResponse == "") + return; + variablesResponse = variablesResponse.Substring(3); + + string[] variableStrings = variablesResponse.Split('#'); + + foreach (string variableString in variableStrings) + { + bool arg = false; + string type = null; + string value = null; + + string[] variableProperties = variableString.Split(';'); + + if (variableProperties[0] != "") + { + if (!evaluatedVars.Contains(variableProperties[0])) + { + string name = variableProperties[0]; + evaluatedVars.Add(variableProperties[0]); + if (variableProperties[1] != "") + arg = true; + if (variableProperties[2] != "") + type = variableProperties[2]; + if (variableProperties[3] != "") + value = variableProperties[3]; + if (arg) + _arguments.Add(VariableInfo.Create(name, type, value, _engine.EventDispatcher)); + else + _locals.Add(VariableInfo.Create(name, type, value, _engine.EventDispatcher)); + } + } + } + } + + #region Non-interface methods + + /// + /// Construct a FRAMEINFO for this stack frame with the requested information. + /// + /// A combination of flags from the FRAMEINFO_FLAGS enumeration that specifies which fields of the + /// frameInfo parameter are to be filled in. + /// A FRAMEINFO structure that is filled in with the description of the stack frame. + public void SetFrameInfo(enum_FRAMEINFO_FLAGS flags, out FRAMEINFO frameInfo) + { + frameInfo = new FRAMEINFO(); + + // The debugger is asking for the formatted name of the function which is displayed in the callstack window. + // There are several optional parts to this name including the module, argument types and values, and line numbers. + // The optional information is requested by setting flags in the dwFieldSpec parameter. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME) != 0) + { + // If there is source information, construct a string that contains the module name, function name, and optionally argument names and values. + if (_hasSource) + { + frameInfo.m_bstrFuncName = ""; + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0) + { +// frameInfo.m_bstrFuncName = System.IO.Path.GetFileName(module.Name) + "!"; + } + + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_RETURNTYPE) != 0) + { + // Adds the return type to the m_bstrFuncName field. + //frameInfo.m_bstrFuncName += _returnType; + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LANGUAGE) != 0) + { + // Adds the language to the m_bstrFuncName field. + if (_documentName.EndsWith(".c")) + frameInfo.m_bstrFuncName += "(C) "; + else if (_documentName.EndsWith(".cpp") || _documentName.EndsWith(".c++")) + frameInfo.m_bstrFuncName += "(C++) "; + } + + frameInfo.m_bstrFuncName += _functionName; + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS) != 0) + { + // Add the arguments to the m_bstrFuncName field. + frameInfo.m_bstrFuncName += "("; + bool all = (flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_ALL) != 0; + int i = 0; + foreach (VariableInfo arg in _arguments) + { + if (all || (flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES) != 0) + { + frameInfo.m_bstrFuncName += arg._type + " "; + } + + if (all || (flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES) != 0) + { + frameInfo.m_bstrFuncName += arg._name; + } + + if (all || (flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES) != 0) + { + frameInfo.m_bstrFuncName += "=" + arg._value; + } + + if (i < _arguments.Count - 1) + { + frameInfo.m_bstrFuncName += ", "; + } + i++; + } + frameInfo.m_bstrFuncName += ")"; + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES) != 0) + { + frameInfo.m_bstrFuncName += " Line: " + _lineNum.ToString(); + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_OFFSET) != 0) + { + // TODO: + // Adds to the m_bstrFuncName field the offset in bytes from the start of the line if FIF_FUNCNAME_LINES is specified. + // If FIF_FUNCNAME_LINES is not specified, or if line numbers are not available, adds the offset in bytes from the start of the function. + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_FORMAT) != 0) + { + // TODO: + // Formats the function name. The result is returned in the m_bstrFuncName field and no other fields are filled out. + // According to http://msdn.microsoft.com/en-us/library/bb145138.aspx, this flag "Specify the FIF_FUNCNAME_FORMAT + // flag to format the function name into a single string". This method already works on this way. + } + } + else + { + // No source information, so only return the module name and the instruction pointer. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0) + { + if ((_functionName != "") && (_functionName != "??")) + frameInfo.m_bstrFuncName = _functionName; + else + frameInfo.m_bstrFuncName = "[External Code]"; + } + else + { + frameInfo.m_bstrFuncName = "[External Code]"; + } + + } + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME; + } + + // The debugger is requesting the name of the module for this stack frame. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_MODULE) != 0) + { + frameInfo.m_bstrModule = ""; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_MODULE; + } + + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_RETURNTYPE) != 0) + { + // TODO: + // Initialize/use the m_bstrReturnType field. + frameInfo.m_bstrReturnType = ""; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_RETURNTYPE; + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_ARGS) != 0) + { + // Initialize/use the m_bstrArgs field. + frameInfo.m_bstrArgs = ""; + bool all = (flags & enum_FRAMEINFO_FLAGS.FIF_ARGS_ALL) != 0; + int i = 0; + foreach (VariableInfo arg in _arguments) + { + if (all || (flags & enum_FRAMEINFO_FLAGS.FIF_ARGS_TYPES) != 0) + { + frameInfo.m_bstrArgs += arg._type + " "; + } + + if (all || (flags & enum_FRAMEINFO_FLAGS.FIF_ARGS_NAMES) != 0) + { + frameInfo.m_bstrArgs += arg._name; + } + + if (all || (flags & enum_FRAMEINFO_FLAGS.FIF_ARGS_VALUES) != 0) + { + frameInfo.m_bstrArgs += "=" + arg._value; + } + + if (i < _arguments.Count - 1) + { + frameInfo.m_bstrArgs += ", "; + } + i++; + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_ARGS_NO_TOSTRING) != 0) + { + // TODO: + // Do not allow ToString() function evaluation or formatting when returning function arguments. + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_ARGS_NO_FUNC_EVAL) != 0) + { + // TODO: + // Specifies that function (property) evaluation should not be used when retrieving argument values. + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_ARGS_NOFORMAT) != 0) + { + // TODO: + // Specifies that the arguments are not be formatted (for example, do not add opening and closing parentheses around + // the argument list nor add a separator between arguments). + } + + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_ARGS; + } + + if ((flags & enum_FRAMEINFO_FLAGS.FIF_LANGUAGE) != 0) + { + // Initialize/use the m_bstrLanguage field. + if (_documentName != null) + { + if (_documentName.EndsWith(".c")) + frameInfo.m_bstrLanguage = "C"; + else if (_documentName.EndsWith(".cpp") || _documentName.EndsWith(".c++")) + frameInfo.m_bstrLanguage = "C++"; + else + frameInfo.m_bstrLanguage = ""; + } + else + frameInfo.m_bstrLanguage = ""; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_LANGUAGE; + } + + // The debugger would like a pointer to the IDebugModule2 that contains this stack frame. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP) != 0) + { + frameInfo.m_pModule = _engine.Module; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP; + } + + // The debugger is requesting the range of memory addresses for this frame. + // For the sample engine, this is the contents of the frame pointer. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_STACKRANGE) != 0) + { + // TODO: + // Initialize/use the m_addrMin and m_addrMax (stack range) fields. + + frameInfo.m_addrMin = 0; + frameInfo.m_addrMax = 0; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STACKRANGE; + } + + // The debugger is requesting the IDebugStackFrame2 value for this frame info. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FRAME) != 0) + { + frameInfo.m_pFrame = this; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FRAME; + } + + // Does this stack frame of symbols loaded? + if ((flags & enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO) != 0) + { + frameInfo.m_fHasDebugInfo = _hasSource ? 1 : 0; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO; + } + + // Is this frame stale? + if ((flags & enum_FRAMEINFO_FLAGS.FIF_STALECODE) != 0) + { + frameInfo.m_fStaleCode = 0; + frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STALECODE; + } + + // The debug engine is to filter non-user code frames so they are not included. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_FILTER_NON_USER_CODE ) != 0) + { + } + + // Frame information should be gotten from the hosted app-domain rather than the hosting process. + if ((flags & enum_FRAMEINFO_FLAGS.FIF_DESIGN_TIME_EXPR_EVAL) != 0) + { + } + } + + /// + /// Construct an instance of IEnumDebugPropertyInfo2 for the combined locals and parameters. + /// + /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in + /// the enumObject are to be filled in. + /// Returns the number of elements in the enumeration. + /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. + public void CreateLocalsPlusArgsProperties(enum_DEBUGPROP_INFO_FLAGS flags, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) + { + elementsReturned = 0; + int localsLength = 0; + + if (_locals != null) + { + localsLength = _locals.Count; + elementsReturned += (uint)localsLength; + } + + if (_arguments != null) + { + elementsReturned += (uint)_arguments.Count; + } + DEBUG_PROPERTY_INFO[] propInfo = new DEBUG_PROPERTY_INFO[elementsReturned]; + + if (_locals != null) + { + int i = 0; + foreach(VariableInfo var in _locals) + { + AD7Property property = new AD7Property(var); + propInfo[i] = property.ConstructDebugPropertyInfo(flags); + i++; + } + } + + if (_arguments != null) + { + int i = 0; + foreach (VariableInfo arg in _arguments) + { + AD7Property property = new AD7Property(arg); + propInfo[localsLength + i] = property.ConstructDebugPropertyInfo(flags); + i++; + } + } + + enumObject = new AD7PropertyInfoEnum(propInfo); + } + + /// + /// Construct an instance of IEnumDebugPropertyInfo2 for the locals collection only. + /// + /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in + /// the enumObject are to be filled in. + /// Returns the number of elements in the enumeration. + /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. + private void CreateLocalProperties(enum_DEBUGPROP_INFO_FLAGS flags, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) + { + elementsReturned = (uint)_locals.Count; + DEBUG_PROPERTY_INFO[] propInfo = new DEBUG_PROPERTY_INFO[_locals.Count]; + + int i = 0; + foreach (VariableInfo var in _locals) + { + AD7Property property = new AD7Property(var); + propInfo[i] = property.ConstructDebugPropertyInfo(flags); + i++; + } + + enumObject = new AD7PropertyInfoEnum(propInfo); + } + + /// + /// Construct an instance of IEnumDebugPropertyInfo2 for the parameters collection only. + /// + /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in + /// the enumObject are to be filled in. + /// Returns the number of elements in the enumeration. + /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. + private void CreateParameterProperties(enum_DEBUGPROP_INFO_FLAGS flags, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) + { + elementsReturned = (uint)_arguments.Count; + DEBUG_PROPERTY_INFO[] propInfo = new DEBUG_PROPERTY_INFO[_arguments.Count]; + + int i = 0; + foreach (VariableInfo arg in _arguments) + { + AD7Property property = new AD7Property(arg); + propInfo[i] = property.ConstructDebugPropertyInfo(flags); + i++; + } + + enumObject = new AD7PropertyInfoEnum(propInfo); + } + + #endregion + + #region IDebugStackFrame2 Members + + /// + /// Creates an enumerator for properties associated with the stack frame, such as local variables. + /// (http://msdn.microsoft.com/en-us/library/bb145607.aspx). + /// + /// A combination of flags from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields in + /// the enumerated DEBUG_PROPERTY_INFO structures are to be filled in. + /// The radix to be used in formatting any numerical information. + /// A GUID of a filter used to select which DEBUG_PROPERTY_INFO structures are to be enumerated, such as guidFilterLocals. + /// Maximum time, in milliseconds, to wait before returning from this method. Use INFINITE to wait indefinitely. + /// Returns the number of properties enumerated. This is the same as calling the IEnumDebugPropertyInfo2::GetCount method. + /// Returns an IEnumDebugPropertyInfo2 object containing a list of the desired properties. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugStackFrame2.EnumProperties(enum_DEBUGPROP_INFO_FLAGS flags, uint radix, ref Guid guidFilter, uint timeout, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject) + { + elementsReturned = 0; + enumObject = null; + + try + { + if (guidFilter == AD7Guids.guidFilterLocalsPlusArgs || + guidFilter == AD7Guids.guidFilterAllLocalsPlusArgs || + guidFilter == AD7Guids.guidFilterAllLocals) + { + CreateLocalsPlusArgsProperties(flags, out elementsReturned, out enumObject); + return VSConstants.S_OK; + } + if (guidFilter == AD7Guids.guidFilterLocals) + { + CreateLocalProperties(flags, out elementsReturned, out enumObject); + return VSConstants.S_OK; + } + if (guidFilter == AD7Guids.guidFilterArgs) + { + CreateParameterProperties(flags, out elementsReturned, out enumObject); + return VSConstants.S_OK; + } + return EngineUtils.NotImplemented(); + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + } + + /// + /// Gets the code context for this stack frame. The code context represents the current instruction pointer in this stack frame. + /// (http://msdn.microsoft.com/en-us/library/bb147046.aspx) + /// + /// Returns an IDebugCodeContext2 object that represents the current instruction pointer in this stack frame. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugStackFrame2.GetCodeContext(out IDebugCodeContext2 pMemoryAddress) + { + pMemoryAddress = null; + try + { + pMemoryAddress = new AD7MemoryAddress(_engine, _address); + return VSConstants.S_OK; + } + catch (Exception e) + { + return EngineUtils.UnexpectedException(e); + } + } + + /// + /// Gets a description of the properties associated with a stack frame. + /// (http://msdn.microsoft.com/en-us/library/bb144920.aspx) + /// + /// Returns an IDebugProperty2 object that describes the properties of this stack frame. + /// VSConstants.S_OK. + int IDebugStackFrame2.GetDebugProperty(out IDebugProperty2 pProperty) + { + pProperty = new AD7Property(this); + return VSConstants.S_OK; + } + + /// + /// Gets the document context for this stack frame. The debugger will call this when the current stack frame is changed and + /// will use it to open the correct source document for this stack frame. (http://msdn.microsoft.com/en-us/library/bb146338.aspx) + /// + /// Returns an IDebugDocumentContext2 object that represents the current position in a source + /// document. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugStackFrame2.GetDocumentContext(out IDebugDocumentContext2 pDocContext) + { + _engine.CleanEvaluatedThreads(); + pDocContext = null; + + try + { + pDocContext = new AD7DocumentContext(_documentName, _lineNum > 0 ? _lineNum - 1 : 0, null); + return VSConstants.S_OK; + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + } + + /// + /// Gets an evaluation context for expression evaluation within the current context of a stack frame and thread. + /// Generally, an expression evaluation context can be thought of as a scope for performing expression evaluation. + /// Call the IDebugExpressionContext2::ParseText method to parse an expression and then call the resulting + /// IDebugExpression2::EvaluateSync or IDebugExpression2::EvaluateAsync methods to evaluate the parsed expression. + /// (http://msdn.microsoft.com/en-us/library/bb161269.aspx) + /// + /// Returns an IDebugExpressionContext2 object that represents a context for expression evaluation. + /// VSConstants.S_OK. + int IDebugStackFrame2.GetExpressionContext(out IDebugExpressionContext2 ppExprCxt) + { + ppExprCxt = this; + return VSConstants.S_OK; + } + + /// + /// Gets a description of the stack frame. (http://msdn.microsoft.com/en-us/library/bb145146.aspx) + /// + /// A combination of flags from the FRAMEINFO_FLAGS enumeration that specifies which fields of the + /// pFrameInfo parameter are to be filled in. + /// The radix to be used in formatting any numerical information. + /// A FRAMEINFO structure that is filled in with the description of the stack frame. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugStackFrame2.GetInfo(enum_FRAMEINFO_FLAGS flags, uint radix, FRAMEINFO[] pFrameInfo) + { + try + { + SetFrameInfo(flags, out pFrameInfo[0]); + + int frame = 0; + if (_thread.__stackFrames != null) + { + foreach (AD7StackFrame sf in _thread.__stackFrames) + { + if (sf._functionName == _functionName) + break; + frame++; + } + } + + if (_thread._id != _engine.CurrentThread()._id) + _engine.EventDispatcher.SelectThread(_thread._id); + + // Waits for the parsed response for the GDB/MI command that changes the selected frame. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) + GdbWrapper.SendCommand("-stack-select-frame " + frame, 5); + + if (_thread._id != _engine.CurrentThread()._id) + _engine.EventDispatcher.SelectThread(_engine.CurrentThread()._id); + + _engine.CleanEvaluatedThreads(); + + return VSConstants.S_OK; + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + } + + /// + /// Gets the language associated with this stack frame. (http://msdn.microsoft.com/en-us/library/bb145096.aspx) + /// + /// Returns the name of the language that implements the method associated with this stack frame. + /// Returns the GUID of the language. + /// VSConstants.S_OK. + int IDebugStackFrame2.GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) + { + if (_documentName.EndsWith(".c")) + { + pbstrLanguage = "C"; + pguidLanguage = AD7Guids.guidLanguageCpp; + } + else if (_documentName.EndsWith(".cpp") || _documentName.EndsWith(".c++")) + { + pbstrLanguage = "C++"; + pguidLanguage = AD7Guids.guidLanguageCpp; + } + + return VSConstants.S_OK; + } + + /// + /// Gets the name of the stack frame. The name of a stack frame is typically the name of the method being executed. + /// Not implemented. (http://msdn.microsoft.com/en-us/library/bb145002.aspx) + /// + /// Returns the name of the stack frame. + /// Not implemented. + int IDebugStackFrame2.GetName(out string name) + { + name = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Gets a machine-dependent representation of the range of physical addresses associated with a stack frame. + /// Not implemented. (http://msdn.microsoft.com/en-us/library/bb145597.aspx) + /// + /// Returns the lowest physical address associated with this stack frame. + /// Returns the highest physical address associated with this stack frame. + /// Not implemented. + int IDebugStackFrame2.GetPhysicalStackRange(out ulong addressMin, out ulong addressMax) + { + addressMin = 0; + addressMax = 0; + return EngineUtils.NotImplemented(); + } + + /// + /// Gets the thread associated with a stack frame. (http://msdn.microsoft.com/en-us/library/bb161776.aspx) + /// + /// Returns an IDebugThread2 object that represents the thread. + /// VSConstants.S_OK. + int IDebugStackFrame2.GetThread(out IDebugThread2 pThread) + { + pThread = _thread; + return VSConstants.S_OK; + } + + #endregion + + #region IDebugExpressionContext2 Members + + /// + /// Retrieves the name of the evaluation context. The name is the description of this evaluation context. It is typically + /// something that can be parsed by an expression evaluator that refers to this exact evaluation context. For example, in + /// C++ the name is as follows: "{ function-name, source-file-name, module-file-name }" + /// Not implemented. (http://msdn.microsoft.com/en-ca/library/bb161724.aspx) + /// + /// Returns the name of the evaluation context. + /// Not implemented. + int IDebugExpressionContext2.GetName(out string pbstrName) + { + pbstrName = null; + return EngineUtils.NotImplemented(); + } + + /// + /// Parses a text-based expression for evaluation. (http://msdn.microsoft.com/en-ca/library/bb162304.aspx). + /// GDB will parse and evaluate the expression, returning the result or an error in the expression. So, the only task for this + /// method is to create the IDebugExpression2 object that will be sent indirectly to the methods responsible for the evaluation. + /// + /// The expression to be parsed. + /// A combination of flags from the PARSEFLAGS enumeration that controls parsing. + /// The radix to be used in parsing any numerical information in pszCode. + /// Returns the IDebugExpression2 object that represents the parsed expression, which is ready for binding and evaluation. + /// Returns the error message if the expression contains an error. + /// Returns the character index of the error in pszCode if the expression contains an error. + /// VSConstants.S_OK. + int IDebugExpressionContext2.ParseText(string pszCode, + enum_PARSEFLAGS dwFlags, + uint nRadix, + out IDebugExpression2 ppExpr, + out string pbstrError, + out uint pichError) + { + pbstrError = ""; + pichError = 0; + ppExpr = new AD7Expression(pszCode, this, _engine.EventDispatcher); + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/AD7.Impl/AD7Thread.cs b/src_vs2010/DebugEngine/AD7.Impl/AD7Thread.cs new file mode 100644 index 00000000..f1bcda49 --- /dev/null +++ b/src_vs2010/DebugEngine/AD7.Impl/AD7Thread.cs @@ -0,0 +1,666 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.NativeCore; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Debugger.Interop; +using System.Collections; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class represents a thread running in a program and it implements: + /// + /// IDebugThread2: (http://msdn.microsoft.com/en-ca/library/bb145332.aspx) + /// + /// IDebugThread100: (http://msdn.microsoft.com/en-us/library/ff471152.aspx) + /// + public sealed class AD7Thread : IDebugThread2, IDebugThread100 + { + #region Internal Types + + /// + /// Thread's category, from http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/807e26cc-4f3f-4e90-a9a8-b550d484b8c1 + /// + enum enum_THREADCATEGORY + { + THREADCATEGORY_Worker = 0, + THREADCATEGORY_UI = (THREADCATEGORY_Worker + 1), + THREADCATEGORY_Main = (THREADCATEGORY_UI + 1), + THREADCATEGORY_RPC = (THREADCATEGORY_Main + 1), + THREADCATEGORY_Unknown = (THREADCATEGORY_RPC + 1) + } + + #endregion + + /// + /// The AD7Engine object that represents the DE. + /// + public AD7Engine _engine; + + /// + /// Thread's name. + /// + public string _threadDisplayName; + + /// + /// The suspend count determines how many times the IDebugThread2::Suspend method has been called so far. + /// + public uint _suspendCount; + + /// + /// Full long path file name. + /// + public string _filename; + + /// + /// Line number. + /// + public uint _line; + + /// + /// Contains flags that specifies the information that were already verified about this thread's stack frame object. + /// Used to avoid reevaluating stack frames that were already evaluated. + /// + public int _alreadyEvaluated; + + /// + /// Contains the stack frames for this thread + /// + public ArrayList __stackFrames; + + /// + /// A FRAMEINFO structure that is filled in with the description of the previous stack frame that works as a cache, to avoid + /// reevaluate the stack frame again. + /// + public FRAMEINFO[] previousFrameInfoArray = new FRAMEINFO[0]; + + /// + /// Thread's ID. + /// + public string _id; + + /// + /// Thread's state. + /// + public string _state; + + /// + /// Process' ID + Thread's ID. + /// + public string _targetID; + + /// + /// Thread's priority. + /// + public string _priority; + + + /// + /// Constructor. + /// + /// The AD7Engine object that represents the DE. + /// Thread's ID. + /// Process' ID + Thread's ID. + /// Thread's state. + /// Thread's priority. + /// Thread's name. + /// Full short path file name. + /// Line number. + public AD7Thread(AD7Engine engine, string id, string targetID, string state, string priority, string name, string filename, string line) + { + if (engine == null) + throw new ArgumentNullException("engine"); + + _engine = engine; + _suspendCount = 0; + if (id == "1") + _threadDisplayName = "Main Thread"; + else + _threadDisplayName = (name != "") ? name : ""; + + _filename = NativeMethods.GetLongPathName(filename); + uint.TryParse(line, out _line); // stopping on that exception was just horrible... + _id = id; + _state = state; + _targetID = targetID; + _priority = priority; + } + + /// + /// Called by EventDipatcher to set the current location during break mode. + /// + /// Full short path file name. + /// Line number. + public void SetCurrentLocation(string filename, uint line) + { + _filename = NativeMethods.GetLongPathName(filename); + _line = line; + } + + /// + /// Gets the function name. + /// + /// If successful, returns the function name; otherwise, returns "". + public string GetFunctionName() + { + string func = ""; + + if ((_id != "") && (_id != _engine.CurrentThread()._id)) + _engine.EventDispatcher.SelectThread(_id); + + string stackResponse = _engine.EventDispatcher.GetStackFrames().Replace("#;;;;", ""); + + if (stackResponse != "") + { + string[] frameStrings = stackResponse.Split('#'); + + // Query the stack depth without inquiring GDB. + int numStackFrames = frameStrings.Length; + + if (numStackFrames > 30) // limiting the amount of stackFrames to avoid VS crashing. + numStackFrames = 30; + + for (int i = 0; i < numStackFrames; i++) + { + string[] frameInfo = frameStrings[i].Split(';'); + if (frameInfo.Length >= 2) + { + if ((frameInfo[2] != "") && (frameInfo[2] != "??") && (!frameInfo[2].Contains("object."))) + { + func = frameInfo[2]; + break; + } + } + } + + if ((_id != "") && (_id != _engine.CurrentThread()._id)) + _engine.EventDispatcher.SelectThread(_engine.CurrentThread()._id); + } + + return func; + } + + /// + /// Determines whether the next statement can be set to the given stack frame and code context. Not implemented. + /// (http://msdn.microsoft.com/en-ca/library/bb146582.aspx) + /// + /// Reserved for future use; set to a null value. If this is a null value, use the current + /// stack frame. + /// An IDebugCodeContext2 object that describes the code location about to be executed and + /// its context. + /// VSConstants.S_OK. + int IDebugThread2.CanSetNextStatement(IDebugStackFrame2 stackFrame, IDebugCodeContext2 codeContext) + { + return VSConstants.S_OK; + } + + /// + /// Retrieves a list of the stack frames for this thread. (http://msdn.microsoft.com/en-ca/library/bb145138.aspx) + /// + /// A combination of flags from the FRAMEINFO_FLAGS enumeration that specifies which fields of the FRAMEINFO structures are to be filled out. + /// Radix used in formatting numerical information in the enumerator. + /// Returns an IEnumDebugFrameInfo2 object that contains a list of FRAMEINFO structures describing the stack frame. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugThread2.EnumFrameInfo(enum_FRAMEINFO_FLAGS flags, uint radix, out IEnumDebugFrameInfo2 ppEnum) + { + if (_id == "") + { + ppEnum = null; + return VSConstants.S_FALSE; + } + + if (_engine.EvaluatedTheseFlags(_id, flags)) + { + ppEnum = new AD7FrameInfoEnum(previousFrameInfoArray); + return VSConstants.S_OK; + } + + // Ask for general stack information. + if ((_id != "") && (_id != _engine.CurrentThread()._id)) + _engine.EventDispatcher.SelectThread(_id); + + string stackResponse = _engine.EventDispatcher.GetStackFrames().Replace("#;;;;", ""); + if (stackResponse == "") + { + ppEnum = null; + return VSConstants.S_FALSE; + } + string[] frameStrings = stackResponse.Split('#'); + + // Query the stack depth without inquiring GDB. + int numStackFrames = frameStrings.Length; + + if (numStackFrames > 30) // limiting the amount of stackFrames to avoid VS crashing. + numStackFrames = 30; + + ppEnum = null; + try + { + bool created = false; + FRAMEINFO[] frameInfoArray = new FRAMEINFO[numStackFrames]; + for (int i = 0; i < numStackFrames; i++) + { + string[] frameInfo = frameStrings[i].Split(';'); + if (frameInfo.Length >= 3) + { + frameInfo[3] = NativeMethods.GetLongPathName(frameInfo[3]); + AD7StackFrame frame = AD7StackFrame.Create(_engine, this, frameInfo, ref created); + frame.SetFrameInfo(flags, out frameInfoArray[i]); + } + } + if ((previousFrameInfoArray.Length != frameInfoArray.Length) || created) + { + previousFrameInfoArray = frameInfoArray; + ppEnum = new AD7FrameInfoEnum(frameInfoArray); + } + else + { + bool isEqual = true; + for (int i = 0; i < frameInfoArray.Length; i++) + { + if (frameInfoArray[i].m_bstrFuncName != previousFrameInfoArray[i].m_bstrFuncName) + { + isEqual = false; + break; + } + if (frameInfoArray[i].m_dwValidFields != previousFrameInfoArray[i].m_dwValidFields) + { + isEqual = false; + break; + } + if (frameInfoArray[i].m_bstrLanguage != previousFrameInfoArray[i].m_bstrLanguage) + { + isEqual = false; + break; + } + } + if (!isEqual) + { + previousFrameInfoArray = frameInfoArray; + ppEnum = new AD7FrameInfoEnum(frameInfoArray); + } + else + { + ppEnum = new AD7FrameInfoEnum(previousFrameInfoArray); + } + } + + if ((_id != "") && (_id != _engine.CurrentThread()._id)) + _engine.EventDispatcher.SelectThread(_engine.CurrentThread()._id); + + return VSConstants.S_OK; + } + catch (Exception ex) + { + if ((_id != "") && (_id != _engine.CurrentThread()._id)) + _engine.EventDispatcher.SelectThread(_engine.CurrentThread()._id); + return EngineUtils.UnexpectedException(ex); + } + } + + /// + /// Gets the logical thread associated with this physical thread. Not implemented. + /// (http://msdn.microsoft.com/en-ca/library/bb161676.aspx) + /// + /// An IDebugStackFrame2 object that represents the stack frame. + /// Returns an IDebugLogicalThread2 interface that represents the associated logical + /// thread. A debug engine implementation should set this to a null value. + /// VSConstants.S_OK. + int IDebugThread2.GetLogicalThread(IDebugStackFrame2 stackFrame, out IDebugLogicalThread2 ppLogicalThread) + { + ppLogicalThread = null; + return VSConstants.S_OK; + } + + /// + /// Gets the name of a thread. (http://msdn.microsoft.com/en-ca/library/bb162273.aspx) + /// + /// Returns the name of the thread. + /// VSConstants.S_OK. + int IDebugThread2.GetName(out string pbstrName) + { + pbstrName = _threadDisplayName; + return VSConstants.S_OK; + } + + /// + /// Gets the program in which a thread is running. (http://msdn.microsoft.com/en-ca/library/bb147002.aspx) + /// + /// Returns an IDebugProgram2 object that represents the program this thread is running in. + /// VSConstants.S_OK. + int IDebugThread2.GetProgram(out IDebugProgram2 ppProgram) + { + ppProgram = _engine.Program; + return VSConstants.S_OK; + } + + /// + /// Gets the system thread identifier. (http://msdn.microsoft.com/en-ca/library/bb161964.aspx) + /// + /// Returns the system thread identifier. + /// VSConstants.S_OK. + int IDebugThread2.GetThreadId(out uint pThreadId) + { + try + { + pThreadId = Convert.ToUInt32(_id); + } + catch + { + pThreadId = 0; + } + return VSConstants.S_OK; + } + + /// + /// Gets the properties that describe this thread. (http://msdn.microsoft.com/en-ca/library/bb145602.aspx) + /// + /// A combination of flags from the THREADPROPERTY_FIELDS enumeration that determines which fields of + /// ptp are to be filled in. + /// A THREADPROPERTIES structure that that is filled in with the properties of the thread. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugThread2.GetThreadProperties(enum_THREADPROPERTY_FIELDS fields, THREADPROPERTIES[] pThreadProperties) + { + try + { + if ((fields & enum_THREADPROPERTY_FIELDS.TPF_ID) != 0) + { + try + { + pThreadProperties[0].dwThreadId = Convert.ToUInt32(_id); + } + catch + { + pThreadProperties[0].dwThreadId = 0; + } + pThreadProperties[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_ID; + } + if ((fields & enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT) != 0) + { + // VSNDK debug engine doesn't support suspending threads + pThreadProperties[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT; + } + if ((fields & enum_THREADPROPERTY_FIELDS.TPF_STATE) != 0) + { + if (_state == "running") + pThreadProperties[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_RUNNING; + else + pThreadProperties[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_STOPPED; + pThreadProperties[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_STATE; + } + if ((fields & enum_THREADPROPERTY_FIELDS.TPF_PRIORITY) != 0) + { + pThreadProperties[0].bstrPriority = "Normal"; + pThreadProperties[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_PRIORITY; + } + if ((fields & enum_THREADPROPERTY_FIELDS.TPF_NAME) != 0) + { + pThreadProperties[0].bstrName = _threadDisplayName; + pThreadProperties[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_NAME; + } + if ((fields & enum_THREADPROPERTY_FIELDS.TPF_LOCATION) != 0) + { + pThreadProperties[0].bstrLocation = ""; + if (__stackFrames != null) + { + foreach (AD7StackFrame frame in __stackFrames) + { + if (frame._functionName != "") + { + pThreadProperties[0].bstrLocation = frame._functionName; + break; + } + } + } + if (pThreadProperties[0].bstrLocation == "") + pThreadProperties[0].bstrLocation = "[External Code]"; + + pThreadProperties[0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_LOCATION; + } + + return VSConstants.S_OK; + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + } + + /// + /// Resumes execution of a thread. (http://msdn.microsoft.com/en-ca/library/bb145813.aspx) + /// + /// Returns the suspend count after the resume operation. + /// VSConstants.S_OK. + int IDebugThread2.Resume(out uint pSuspendCount) + { + _suspendCount--; + pSuspendCount = _suspendCount; + if (_suspendCount == 0) + { + // Send GDB command to resume execution of thread + } + return VSConstants.S_OK; + } + + /// + /// Sets the next statement to the given stack frame and code context. Not implemented. + /// (http://msdn.microsoft.com/en-ca/library/bb160944.aspx) + /// + /// Reserved for future use; set to a null value. + /// An IDebugCodeContext2 object that describes the code location about to be executed and + /// its context. + /// VSConstants.S_OK. + int IDebugThread2.SetNextStatement(IDebugStackFrame2 stackFrame, IDebugCodeContext2 codeContext) + { + return VSConstants.S_OK; + } + + /// + /// Sets the name of the thread. (http://msdn.microsoft.com/en-ca/library/bb162322.aspx) + /// + /// The name of the thread. + /// VSConstants.S_OK. + int IDebugThread2.SetThreadName(string name) + { + _threadDisplayName = name; + return VSConstants.S_OK; + } + + /// + /// Suspends a thread. (http://msdn.microsoft.com/en-us/library/bb145297.aspx) + /// + /// Returns the suspend count after the suspend operation. + /// VSConstants.S_OK + int IDebugThread2.Suspend(out uint pSuspendCount) + { + _suspendCount++; + pSuspendCount = _suspendCount; + return VSConstants.S_OK; + } + + #region IDebugThread100 Members + + /// + /// Sets the name of the thread. + /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.setthreaddisplayname.aspx) + /// + /// The name of the thread. + /// VSConstants.S_OK. + int IDebugThread100.SetThreadDisplayName(string name) + { + _threadDisplayName = name; + return VSConstants.S_OK; + } + + /// + /// Gets the name of a thread. + /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.getthreaddisplayname.aspx) + /// + /// Returns the name of the thread. + /// VSConstants.S_OK. + int IDebugThread100.GetThreadDisplayName(out string name) + { + name = _threadDisplayName; + return VSConstants.S_OK; + } + + /// + /// Returns whether this thread can be used to do function/property evaluation. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.candofunceval.aspx) + /// + /// VSConstants.S_FALSE. + int IDebugThread100.CanDoFuncEval() + { + return VSConstants.S_FALSE; + } + + /// + /// Set flags. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.setflags.aspx) + /// + /// Flags. + /// VSConstants.E_NOTIMPL. + int IDebugThread100.SetFlags(uint flags) + { + // Not necessary to implement in the debug engine. Instead it is implemented in the SDM. + return EngineUtils.NotImplemented(); + } + + /// + /// Get flags. Not implemented. + /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.getflags.aspx) + /// + /// Flags. + /// VSConstants.E_NOTIMPL. + int IDebugThread100.GetFlags(out uint flags) + { + // Not necessary to implement in the debug engine. Instead it is implemented in the SDM. + flags = 0; + return EngineUtils.NotImplemented(); + } + + /// + /// Gets the properties that describe this thread. + /// (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debugger.interop.idebugthread100.getthreadproperties100.aspx) + /// + /// A combination of flags from the THREADPROPERTIES100 enumeration that determines which fields of + /// ptp are to be filled in. + /// A THREADPROPERTIES100 structure that that is filled in with the properties of the thread. + /// If successful, returns S_OK; otherwise, returns an error code. + int IDebugThread100.GetThreadProperties100(uint fields, THREADPROPERTIES100[] pThreadproperties) + { + try + { + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_ID) != 0) + { + try + { + pThreadproperties[0].dwThreadId = Convert.ToUInt32(_id); + } + catch + { + pThreadproperties[0].dwThreadId = 0; + } + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_ID; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_SUSPENDCOUNT) != 0) + { + // VSNDK debug engine doesn't support suspending threads + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_SUSPENDCOUNT; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_STATE) != 0) + { + if (_state == "running") + pThreadproperties[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_RUNNING; + else + pThreadproperties[0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_STOPPED; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_STATE; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY) != 0) + { + pThreadproperties[0].bstrPriority = "Normal"; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_NAME) != 0) + { + pThreadproperties[0].bstrName = _threadDisplayName; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_NAME; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME) != 0) + { + // Thread display name is being requested + pThreadproperties[0].bstrDisplayName = _threadDisplayName; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME; + + // Give this display name a higher priority than the default (0) + // so that it will actually be displayed + pThreadproperties[0].DisplayNamePriority = 10; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME_PRIORITY; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_LOCATION) != 0) + { + pThreadproperties[0].bstrLocation = ""; + if (__stackFrames != null) + { + foreach (AD7StackFrame frame in __stackFrames) + { + if ((frame._functionName != "") && (frame._functionName != "??")) + { + pThreadproperties[0].bstrLocation = frame._functionName; + break; + } + } + } + else + pThreadproperties[0].bstrLocation = GetFunctionName(); + + if (pThreadproperties[0].bstrLocation == "") + pThreadproperties[0].bstrLocation = "[External Code]"; + + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_LOCATION; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_CATEGORY) != 0) + { + if (_id == "1") + pThreadproperties[0].dwThreadCategory = (uint)enum_THREADCATEGORY.THREADCATEGORY_Main; + else + pThreadproperties[0].dwThreadCategory = (uint)enum_THREADCATEGORY.THREADCATEGORY_Worker; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_CATEGORY; + } + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_AFFINITY) != 0) + { + // Thread cpu affinity is being requested + pThreadproperties[0].AffinityMask = 0; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_AFFINITY; + } + + if ((fields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY_ID) != 0) + { + // Thread display name is being requested + pThreadproperties[0].priorityId = 0; + pThreadproperties[0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY_ID; + } + return VSConstants.S_OK; + } + catch (Exception ex) + { + return EngineUtils.UnexpectedException(ex); + } + } + + #endregion + } +} diff --git a/src_vs2010/DebugEngine/BlackBerry.DebugEngine.csproj b/src_vs2010/DebugEngine/BlackBerry.DebugEngine.csproj new file mode 100644 index 00000000..b4343f42 --- /dev/null +++ b/src_vs2010/DebugEngine/BlackBerry.DebugEngine.csproj @@ -0,0 +1,126 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {59A7B188-E307-4495-A3AF-4ED76B086A87} + Library + Properties + BlackBerry.DebugEngine + BlackBerry.DebugEngine + v4.0 + 512 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2010 + prompt + 4 + true + AnyCPU + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2010 + prompt + 4 + AnyCPU + + + + + False + C:\Program Files (x86)\Microsoft Visual Studio 2010 SDK SP1\VisualStudioIntegration\Common\Assemblies\v4.0\Microsoft.VisualStudio.Shell.10.0.dll + + + + False + True + C:\Program Files (x86)\Microsoft Visual Studio 2010 SDK SP1\VisualStudioIntegration\Common\Assemblies\v2.0\Microsoft.VisualStudio.Shell.Interop.10.0.dll + + + False + C:\Program Files (x86)\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\Assemblies\Microsoft.VisualStudio.Shell.Interop.8.0.dll + + + False + C:\Program Files (x86)\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\Assemblies\Microsoft.VisualStudio.Shell.Interop.9.0.dll + + + + + False + ..\..\..\..\..\..\..\Program Files\Microsoft Visual Studio 2010 SDK\VisualStudioIntegration\Common\Assemblies\v2.0\Microsoft.VisualStudio.Debugger.Interop.10.0.dll + + + False + ..\..\..\..\..\Microsoft.VisualStudio.Debugger.InteropA.dll + + + + + NativeMethods.cs + + + Helpers\MessageBoxHelper.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {36D4495B-9A92-478F-BF95-AEA13804A7BA} + BlackBerry.NativeCore + + + + + + + + + \ No newline at end of file diff --git a/src_vs2010/DebugEngine/DebugEngineStatus.cs b/src_vs2010/DebugEngine/DebugEngineStatus.cs new file mode 100644 index 00000000..76159c3f --- /dev/null +++ b/src_vs2010/DebugEngine/DebugEngineStatus.cs @@ -0,0 +1,14 @@ +namespace BlackBerry.DebugEngine +{ + public static class DebugEngineStatus + { + /// + /// Gets or sets an indication, if the DebugEngine is running. + /// + public static bool IsRunning + { + get; + set; + } + } +} diff --git a/src_vs2010/DebugEngine/Engine.Impl/BreakpointManager.cs b/src_vs2010/DebugEngine/Engine.Impl/BreakpointManager.cs new file mode 100644 index 00000000..147edee1 --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/BreakpointManager.cs @@ -0,0 +1,150 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using BlackBerry.NativeCore.Debugger.Model; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class manages breakpoints for the engine. + /// + public sealed class BreakpointManager + { + /// + /// The AD7Engine object that represents the DE. + /// + private readonly AD7Engine _engine; + + /// + /// List of pending breakpoints. + /// + private readonly List _pendingBreakpoints; + + /// + /// List of active breakpoints. + /// + private readonly List _activeBPs; + + /// + /// Breakpoint manager constructor. + /// + /// Associated Debug Engine. + public BreakpointManager(AD7Engine engine) + { + if (engine == null) + throw new ArgumentNullException("engine"); + + _engine = engine; + _pendingBreakpoints = new List(); + _activeBPs = new List(); + } + + /// + /// A helper method used to construct a new pending breakpoint. + /// + /// An IDebugBreakpointRequest2 object that describes the pending breakpoint to create. + /// Returns an IDebugPendingBreakpoint2 object that represents the pending breakpoint. + public void CreatePendingBreakpoint(IDebugBreakpointRequest2 request, out IDebugPendingBreakpoint2 ppPendingBreakpoint) + { + AD7PendingBreakpoint pendingBreakpoint = new AD7PendingBreakpoint(_engine, request); + ppPendingBreakpoint = pendingBreakpoint; + _pendingBreakpoints.Add(pendingBreakpoint); + } + + /// + /// Return the active bound breakpoint matching the given GDB ID. + /// + /// Breakpoint ID in GDB. + /// If successful, returns the active bound breakpoint; otherwise, returns null. + public AD7BoundBreakpoint GetBoundBreakpointForGDBID(uint gdbID) + { + foreach (AD7BoundBreakpoint breakpoint in _activeBPs) + { + if (breakpoint != null && breakpoint.GdbInfo.ID == gdbID) + { + return breakpoint; + } + } + return null; + } + + /// + /// Called from the engine's detach method to remove the debugger's breakpoint instructions. + /// + public void ClearBoundBreakpoints() + { + foreach (AD7PendingBreakpoint breakpoint in _pendingBreakpoints) + { + breakpoint.ClearBoundBreakpoints(); + } + } + + /// + /// Creates an entry and remotely enables the breakpoint in the debug stub. + /// + /// The bound breakpoint to add. + /// Info about GDB breakpoint. + public void RemoteAdd(AD7BoundBreakpoint breakpoint, out BreakpointInfo info) + { + // Call GDB to set a breakpoint based on filename and line no. in aBBP + bool ret = false; + + info = null; + if (breakpoint.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) + { + ret = _engine.EventDispatcher.SetBreakpoint(breakpoint.m_filename, breakpoint.m_line, out info); + } + else if (breakpoint.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) + { + ret = _engine.EventDispatcher.SetBreakpoint(breakpoint.m_func, out info); + } + + if (ret && info != null) + { + _activeBPs.Add(breakpoint); + } + } + + /// + /// Enable bound breakpoint. + /// + /// The Bound breakpoint to enable. + public void RemoteEnable(AD7BoundBreakpoint breakpoint) + { + _engine.EventDispatcher.EnableBreakpoint(breakpoint.GdbInfo.ID, true); + } + + /// + /// Disable bound breakpoint. + /// + /// The Bound breakpoint to disable. + public void RemoteDisable(AD7BoundBreakpoint breakpoint) + { + _engine.EventDispatcher.EnableBreakpoint(breakpoint.GdbInfo.ID, false); + } + + /// + /// Remove the associated bound breakpoint. + /// + /// The breakpoint to remove. + public void RemoteDelete(AD7BoundBreakpoint breakpoint) + { + _activeBPs.Remove(breakpoint); + _engine.EventDispatcher.DeleteBreakpoint(breakpoint.GdbInfo.ID); + } + } +} diff --git a/src_vs2010/DebugEngine/Engine.Impl/EngineCallback.cs b/src_vs2010/DebugEngine/Engine.Impl/EngineCallback.cs new file mode 100644 index 00000000..230a84ad --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/EngineCallback.cs @@ -0,0 +1,216 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// Used to send events to the debugger. Some examples of these events are thread create, exception thrown, module load. + /// + public sealed class EngineCallback + { + /// + /// The IDebugEventCallback2 object that receives debugger events. + /// + private readonly IDebugEventCallback2 _ad7Callback; + + /// + /// The AD7Engine object that represents the DE. + /// + private readonly AD7Engine _engine; + + /// + /// Constructor. + /// + /// The AD7Engine object that represents the DE. + /// The IDebugEventCallback2 object that receives debugger events. + public EngineCallback(AD7Engine engine, IDebugEventCallback2 ad7Callback) + { + if (engine == null) + throw new ArgumentNullException("engine"); + if (ad7Callback == null) + throw new ArgumentNullException("ad7Callback"); + + _engine = engine; + _ad7Callback = ad7Callback; + } + + /// + /// Send events to the debugger. + /// + /// Event object to be sent to the debugger. + /// ID of the event. + /// A program that is running in a process. + /// A thread running in a program. + public void Send(IDebugEvent2 eventObject, string iidEvent, IDebugProgram2 program, IDebugThread2 thread) + { + uint attributes; + Guid riidEvent = new Guid(iidEvent); + + EngineUtils.RequireOK(eventObject.GetAttributes(out attributes)); + + if ((thread == null) && (_engine != null) && (_engine.Threads != null) && (program != null) && (eventObject != null) && (riidEvent != null) && (attributes != 0)) + { + if (_engine._currentThreadIndex != -1) + { + EngineUtils.RequireOK(_ad7Callback.Event(_engine, null, program, _engine.Threads[_engine._currentThreadIndex], eventObject, ref riidEvent, attributes)); + } + else + { + if (_engine.Threads != null) + EngineUtils.RequireOK(_ad7Callback.Event(_engine, null, program, _engine.Threads[0], eventObject, ref riidEvent, attributes)); + else + EngineUtils.RequireOK(_ad7Callback.Event(_engine, null, program, null, eventObject, ref riidEvent, attributes)); + } + } + else + EngineUtils.RequireOK(_ad7Callback.Event(_engine, null, program, thread, eventObject, ref riidEvent, attributes)); + } + + /// + /// Call the method that will send the event to the debugger with all the arguments. + /// + /// Event object to be sent to the debugger. + /// ID of the event. + /// A thread running in a program. + public void Send(IDebugEvent2 eventObject, string iidEvent, IDebugThread2 thread) + { + Send(eventObject, iidEvent, _engine, thread); + } + + /// + /// IDebugErrorEvent2 is used to report error messages to the user when something goes wrong in the debug engine. + /// The VSNDK debug engine doesn't take advantage of this. Not implemented. + /// + /// + public void OnError(int hrErr) + { + } + + /// + /// The VSNDK debug engine does not support binding breakpoints as modules load since the primary exe is the only module + /// symbols are loaded for. A production debugger will need to bind breakpoints when a new module is loaded. + /// + /// A module loaded in the debugged process. + public void OnModuleLoad(AD7Module debuggedModule) + { + AD7ModuleLoadEvent eventObject = new AD7ModuleLoadEvent(debuggedModule, true /* this is a module load */); + Send(eventObject, AD7ModuleLoadEvent.IID, null); + } + + /// + /// Send to the session debug manager (SDM) an event to output a string. + /// Not used. + /// + /// The output string. + public void OnOutputString(string outputString) + { + AD7OutputDebugStringEvent eventObject = new AD7OutputDebugStringEvent(outputString); + Send(eventObject, AD7OutputDebugStringEvent.IID, null); + } + + /// + /// Send an event to SDM with the breakpoint that was hit. + /// + /// The thread running in a program. + /// List of bound breakpoints. At this moment, this list has only one element. + public void OnBreakpoint(AD7Thread thread, IList clients) + { + IDebugBoundBreakpoint2[] boundBreakpoints = new IDebugBoundBreakpoint2[clients.Count]; + + int i = 0; + foreach (var breakpoint in clients) + { + boundBreakpoints[i++] = breakpoint; + } + + AD7BoundBreakpointsEnum boundBreakpointsEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); + AD7BreakpointEvent eventObject = new AD7BreakpointEvent(boundBreakpointsEnum); + Send(eventObject, AD7BreakpointEvent.IID, thread); + } + + /// + // Exception events are sent when an exception occurs in the debugged that the debugger was not expecting. + // The VSNDK debug engine does not support these. Not implemented. + /// + public void OnException() + { + EngineUtils.NotImplemented(); + } + + /// + /// Step complete is sent when a step has finished. Not implemented. + /// + public void OnStepComplete() + { + EngineUtils.NotImplemented(); + // AD7StepCompletedEvent.Send(m_engine); + // TODO: implement this method... + } + + /// + /// This will get called when the engine receives the breakpoint event that is created when the user + /// hits the pause button in VS. + /// + /// The thread running in a program. + public void OnAsyncBreakComplete(AD7Thread thread) + { + AD7AsyncBreakCompleteEvent eventObject = new AD7AsyncBreakCompleteEvent(); + Send(eventObject, AD7AsyncBreakCompleteEvent.IID, thread); + } + + /// + /// Engines notify the debugger about the results of a symbol search by sending an instance of IDebugSymbolSearchEvent2. + /// Not used. + /// + /// + /// + /// + public void OnSymbolSearch(AD7Module module, string status, uint dwStatusFlags) + { + string statusString = (dwStatusFlags == 1 ? "Symbols loaded - " : "No symbols loaded - ") + status; + + AD7SymbolSearchEvent eventObject = new AD7SymbolSearchEvent(module, statusString, dwStatusFlags); + Send(eventObject, AD7SymbolSearchEvent.IID, null); + } + + /// + /// Engines notify the debugger that a breakpoint has bound through the breakpoint bound event. + /// + /// The bounded breakpoint. + /// 0. + public void OnBreakpointBound(object objBoundBreakpoint, uint address) + { + AD7BoundBreakpoint boundBreakpoint = (AD7BoundBreakpoint)objBoundBreakpoint; + IDebugPendingBreakpoint2 pendingBreakpoint; + ((IDebugBoundBreakpoint2)boundBreakpoint).GetPendingBreakpoint(out pendingBreakpoint); + + AD7BreakpointBoundEvent eventObject = new AD7BreakpointBoundEvent((AD7PendingBreakpoint)pendingBreakpoint, boundBreakpoint); + Send(eventObject, AD7BreakpointBoundEvent.IID, null); + } + + /// + /// Send an event to notify the SDM that this thread was created. + /// + /// The new thread running in a program. + public void OnThreadStart(AD7Thread debuggedThread) + { + AD7ThreadCreateEvent eventObject = new AD7ThreadCreateEvent(); + Send(eventObject, AD7ThreadCreateEvent.IID, debuggedThread); + } + } +} diff --git a/src_vs2010/DebugEngine/Engine.Impl/EngineUtils.cs b/src_vs2010/DebugEngine/Engine.Impl/EngineUtils.cs new file mode 100644 index 00000000..a481f149 --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/EngineUtils.cs @@ -0,0 +1,95 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.NativeCore.Diagnostics; +using Microsoft.VisualStudio; +using System.Diagnostics; + +namespace BlackBerry.DebugEngine +{ + /// + /// Some utilities used in VSNDK debug engine projects. + /// + public static class EngineUtils + { + /// + /// + /// + /// An integer result of COM operation. + public static void RequireOK(int hr) + { + if (hr != VSConstants.S_OK) + { + throw new InvalidOperationException(); + } + } + + /// + /// + /// + /// Exception. + /// VSConstants.E_NOTIMPL. + public static int UnexpectedException(Exception ex) + { + TraceLog.WriteException(ex); + + Debug.Fail("Unexpected exception: " + ex); + return VSConstants.E_FAIL; + } + + /// + /// Default handler for 'non-implemented' method. + /// It will conditionally stop the debugger, when called. + /// + [DebuggerStepThrough] + public static int NotImplemented(bool canBreak) + { + TraceLog.WriteLine("Hit not implemented method \"{0}\"!", GetMethodName(2)); + if (canBreak && Debugger.IsAttached) + Debugger.Break(); + + return VSConstants.E_NOTIMPL; + } + + /// + /// Default handler for 'non-implemented' method. + /// It will stop the debugger, when called, as the original place was not supposed to be called by Visual Studio. + /// + [DebuggerStepThrough] + public static int NotImplemented() + { + TraceLog.WriteLine("Hit not implemented method \"{0}\"!", GetMethodName(2)); + if (Debugger.IsAttached) + Debugger.Break(); + + return VSConstants.E_NOTIMPL; + } + + /// + /// Gets the name of the method from stack. + /// + [DebuggerStepThrough] + private static string GetMethodName(int backCalls) + { + StackTrace stack = new StackTrace(); + StackFrame frame = stack.GetFrame(backCalls); + + var method = frame.GetMethod(); + if (method != null && method.DeclaringType != null) + return string.Concat(method.DeclaringType.Name, "::", method.Name, "()"); + return ""; + } + } +} diff --git a/src_vs2010/DebugEngine/Engine.Impl/EventDispatcher.cs b/src_vs2010/DebugEngine/Engine.Impl/EventDispatcher.cs new file mode 100644 index 00000000..b83c246c --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/EventDispatcher.cs @@ -0,0 +1,922 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Debugger; +using BlackBerry.NativeCore.Debugger.Model; +using Microsoft.VisualStudio.Debugger.Interop; +using System.Threading; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class manages debug events for the debug engine. + /// + /// Process GDB's output by classifying it by type (e.g. breakpoint event) and providing relevant data. + /// Send GDB commands as appropriate for the received event (e.g. call -exec-continue to resume execution after a breakpoint is + /// inserted). + /// Call debug engine methods to notify the SDM of an event (e.g. if a breakpoint is hit, call EngineCallback.OnBreakpoint()). + /// + public sealed class EventDispatcher : IDisposable + { + #region Internal Classes + + /// + /// Process asynchronous GDB's output by classifying it by type (e.g. breakpoint event). + /// + sealed class GdbOutput + { + /// + /// This object manages debug events in the engine. + /// + private readonly EventDispatcher _eventDispatcher; + + /// + /// This object manages breakpoints events. + /// + private HandleBreakpoints _hBreakpoints; + + /// + /// This object manages events related to execution control (processes, threads, programs). + /// + private HandleProcessExecution _hProcExe; + + /// + /// This object manages events related to output messages. + /// + private HandleOutputs _hOutputs; + + /// + /// Constructor. + /// + /// This object manages debug events in the engine. + public GdbOutput(EventDispatcher ed) + { + _eventDispatcher = ed; + IsRunning = true; + GdbWrapper.Received += GdbOnReceivedResponse; + GdbWrapper.UnexpectedlyClosed += GdbOnUnexpectedlyClosed; + } + + private void GdbOnUnexpectedlyClosed(object sender, EventArgs e) + { + Dispose(); + _eventDispatcher.EndDebugSession(0); + } + + private void GdbOnReceivedResponse(object sender, ResponseParsedEventArgs e) + { + Debug.Assert(e != null && e.Response != null && e.Response.RawData != null, "Invalid response object received"); + ProcessingGdbOutput(e.ParsedResult); + } + + public void Dispose() + { + GdbWrapper.UnexpectedlyClosed -= GdbOnUnexpectedlyClosed; + GdbWrapper.Received -= GdbOnReceivedResponse; + } + + #region Properties + + /// + /// Corresponds to the event-dispatcher status. When false, exit the event dispatch loop. + /// + public bool IsRunning + { + get; + set; + } + + #endregion + + /// + /// Thread responsible for handling asynchronous GDB output. + /// + private void ProcessingGdbOutput(string parsedResponse) + { + string[] events = parsedResponse.Replace("\r\n", "@").Split('@'); + foreach (string ev in events) + { + if (ev.Length > 1) // only to avoid empty events, when there are two delimiters characters together. + { + if (_eventDispatcher.countSIGINT > 0) + if ((ev.Substring(0, 2) != "50") && (ev.Substring(0, 2) != "80")) + _eventDispatcher.countSIGINT = 0; // Reset the counter, if GDB has recovered from a GDB bug. + switch (ev[0]) + { + case '0': // Events related to starting GDB. + break; + case '1': // Not used. + break; + case '2': // Events related to breakpoints (including breakpoint hits). + _hBreakpoints = new HandleBreakpoints(_eventDispatcher); + _hBreakpoints.Handle(ev); + break; + case '3': // Not used. + break; + case '4': // Events related to execution control (processes, threads, programs) 1. + _hProcExe = new HandleProcessExecution(_eventDispatcher); + _hProcExe.Handle(ev); + break; + case '5': // Events related to execution control (processes, threads, programs and GDB Bugs) 2. + _hProcExe = new HandleProcessExecution(_eventDispatcher); + _hProcExe.Handle(ev); + break; + case '6': // Events related to evaluating expressions. Not used. + break; + case '7': // Events related to stack frames. Not used. + break; + case '8': // Events related to output. + _hOutputs = new HandleOutputs(_eventDispatcher); + _hOutputs.Handle(ev); + break; + case '9': // Not used. + break; + } + } + } + } + } + + #endregion + + /// + /// Represents the object that process asynchronous GDB's output by classifying it by type (e.g. breakpoint event). + /// + private readonly GdbOutput _gdbOutput; + + /// + /// Boolean variable that indicates if the current code is known or unknown, i.e., if there is a source code file associated. + /// + public static bool _unknownCode; + + /// + /// Object used to control the access to the critical section that exists in the "lockedBreakpoint" method. + /// + private readonly object _lockBreakpoint = new object(); + + /// + /// Object used to control the access to the critical section that exists in the "unlockBreakpoint" method. + /// + private readonly object _unlockBreakpoint = new object(); + + /// + /// Object used to control the access to the critical section that exists in the "enterCriticalRegion" method. + /// + private readonly object _criticalRegion = new object(); + + /// + /// Object used to control the access to the critical section that exists in the "leaveCriticalRegion" method. + /// + private readonly object _leaveCriticalRegion = new object(); + + /// + /// Boolean variable that indicates the GDB state: TRUE -> run mode; FALSE -> break mode. + /// + public static bool _GDBRunMode = true; + + /// + /// Variable that is manipulated only in methods enterCriticalRegion and leaveCriticalRegion + /// + public bool _inCriticalRegion; + + /// + /// There is a GDB bug that causes a message "Quit (expect signal SIGINT when the program is resumed)". If this message occurs + /// 5 times, VSNDK will end the debug session. That's why this variable is needed, to count the amount of this kind of message + /// that is received in a sequence. + /// + public int countSIGINT; + + #region Properties + + /// + /// The public AD7Engine object that represents the DE. + /// + public AD7Engine Engine + { + get; + private set; + } + + #endregion + + /// + /// Constructor. Starts the thread responsible for handling asynchronous GDB output. + /// + /// The AD7Engine object that represents the DE. + public EventDispatcher(AD7Engine engine) + { + if (engine == null) + throw new ArgumentNullException("engine"); + + Engine = engine; + + _gdbOutput = new GdbOutput(this); + } + + #region IDisposable Implementation + + ~EventDispatcher() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + _gdbOutput.Dispose(); + } + + #endregion + + /// + /// Ends the debug session by closing GDB, sending the appropriate events to the SDM, and breaking out of all + /// buffer- and event-listening loops. + /// + /// The exit code. + public void EndDebugSession(uint exitCode) + { + // Exit the event dispatch loop. + _gdbOutput.IsRunning = false; + + // Send events to the SDM. + AD7ThreadDestroyEvent.Send(Engine, exitCode, null); + AD7ProgramDestroyEvent.Send(Engine, exitCode); + + // Exit GDB. + GdbWrapper.Exit(); + + // Notify the AddIn that this debug session has ended. + DebugEngineStatus.IsRunning = false; + } + + /// + /// Interrupt the debugged process if necessary before changing a breakpoint. + /// + public void PrepareToModifyBreakpoint() + { + if (Engine.State != AD7Engine.DebugEngineState.Design + && Engine.State != AD7Engine.DebugEngineState.Break) + { + HandleProcessExecution.NeedsResumeAfterInterrupt = true; + Engine.CauseBreak(); + } + } + + /// + /// If the process was running when the breakpoint was changed, resume the process. + /// + public void ResumeFromInterrupt() + { + if (HandleProcessExecution.NeedsResumeAfterInterrupt) + { + HandleProcessExecution.NeedsResumeAfterInterrupt = false; + ContinueExecution(); + } + } + + /// + /// Code to set the breakpoint in GDB and then confirm and set in Visual Studio + /// + /// Initial command to set the breakpoint in GDB, with the entire path when setting + /// a breakpoint in a given line number. + /// Initial command to set the breakpoint in GDB, with only the file name when setting + /// a breakpoint in a given line number, or "" when setting a breakpoint in a function. + /// Returns the breakpoint info from GDB. + /// If successful, returns true; otherwise, returns false. + private bool SetBreakpointImpl(string command, string command2, out BreakpointInfo breakpointInfo) + { + string response; + string bpointAddress; + string bpointStopPoint; + + if (DebugEngineStatus.IsRunning) + { + PrepareToModifyBreakpoint(); + + // Gets the parsed response for the GDB/MI command that inserts breakpoint in a given line or a given function. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) + response = GdbWrapper.SendCommand(command, 6); + + if ((command2 != "") && ((response.Contains("")))) + { + response = GdbWrapper.SendCommand(command2, 6); + } + + if (((response.Length < 2) && (DebugEngineStatus.IsRunning == false)) || (response == "Function not found!")) + { + breakpointInfo = null; + ResumeFromInterrupt(); + return false; + } + + HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); + hBreakpoints.Handle(response); + + if (hBreakpoints.Address != "" && hBreakpoints.Address != "") + { + //** Run Code to verify breakpoint stop point. + + // Gets the parsed response for the GDB command that print information about the specified breakpoint, in this + // case, only its address. (http://sourceware.org/gdb/onlinedocs/gdb/Set-Breaks.html) + bpointAddress = GdbWrapper.SendCommand("info b " + hBreakpoints.Number, 18); + + // Gets the parsed response for the GDB command that inquire what source line covers a particular address. + // (http://sourceware.org/gdb/onlinedocs/gdb/Machine-Code.html) + bpointStopPoint = GdbWrapper.SendCommand("info line *" + bpointAddress, 18); + + var line = (uint)Convert.ToInt64(bpointStopPoint.Trim()); + uint address = 0; + + if (hBreakpoints.Address != null && hBreakpoints.Address.Length > 2) + { + uint.TryParse(hBreakpoints.Address.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out address); + } + breakpointInfo = new BreakpointInfo((uint)hBreakpoints.Number, hBreakpoints.FileName, line, address); + } + else + { + var line = (uint)hBreakpoints.LinePosition; + breakpointInfo = new BreakpointInfo((uint)hBreakpoints.Number, hBreakpoints.FileName, line, 0); + } + + ResumeFromInterrupt(); + return true; + } + + breakpointInfo = null; + return false; + } + + /// + /// Set a breakpoint given a filename and line number. + /// + /// Full path and filename for the code source. + /// The line number for the breakpoint. + /// Info of GDB breakpoint. + /// If successful, returns true; otherwise, returns false. + public bool SetBreakpoint(string filename, uint line, out BreakpointInfo breakpoint) + { + string cmd = @"-break-insert --thread-group i1 -f " + filename + ":" + line; + string cmd2 = @"-break-insert --thread-group i1 -f " + NativeMethods.GetShortPathName(filename) + ":" + line; + return SetBreakpointImpl(cmd, cmd2, out breakpoint); + } + + /// + /// Set a breakpoint given a function name. + /// + /// Function name. + /// Info of GDB breakpoint. + /// If successful, returns true; otherwise, returns false. + public bool SetBreakpoint(string functionName, out BreakpointInfo breakpoint) + { + string cmd = @"-break-insert " + functionName; + return SetBreakpointImpl(cmd, "", out breakpoint); + } + + /// + /// Ignore a given number of hit counts in GDB. + /// + /// Breakpoint ID in GDB. + /// Number of hit counts to ignore. + /// If successful, returns true; otherwise, returns false. + public bool IgnoreHitCount(uint GDB_ID, int ignore) + { + ignore -= 1; // The given number is decreased by one, because the VS command means to break when hit count is equal or greater + // than X hits. So, the equivalent GDB command is to break after (X - 1) hit counts. + + if (ignore < 0) + { + // Had to ignore the biggest number of times to keep the breakpoint enabled and to avoid stopping on it. + ignore = int.MaxValue; + } + + // Gets the parsed response for the GDB/MI command that makes the breakpoint "GDB_ID" ignore "ignore" hit counts. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) + string response = GdbWrapper.SendCommand(@"-break-after " + GDB_ID + " " + ignore, 18); + + if (response == "") + return false; + + HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); + hBreakpoints.Handle(response); + + return true; + } + + /// + /// Reset current hit count in GDB. There is no way to reset hit counts in GDB. To implement this functionality, the specified GDB + /// breakpoint is deleted and a new one is created with the same conditions, substituting the GDB_ID of the VS breakpoint. + /// + /// The VS breakpoint. + /// Is false when this method is called by SetCondition, true if not. Used to avoid setting + /// breakpoint conditions again in case it is called by SetCondition method. + /// If successful, returns true; otherwise, returns false. + public bool ResetHitCount(AD7BoundBreakpoint bbp, bool resetCondition) + { + // Declare local Variables + BreakpointInfo info = null; + + // Deleting GDB breakpoint. + DeleteBreakpoint(bbp.GdbInfo.ID); + + // Creating a new GDB breakpoint. + bool ret = false; + if (bbp.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) + { + ret = SetBreakpoint(bbp.m_filename, bbp.m_line, out info); + } + else if (bbp.m_bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) + { + ret = SetBreakpoint(bbp.m_func, out info); + } + + if (ret && info != null) + { + bbp.GdbInfo = info; + bbp._hitCount = 0; + bbp.SetPassCount(bbp.m_bpPassCount); + if (resetCondition) + bbp.SetCondition(bbp.m_bpCondition); + + return true; + } + return false; + } + + /// + /// Set breakpoint condition in GDB. + /// + /// Breakpoint ID in GDB. + /// Condition to be set. When empty (""), means to remove any previous condition. + /// If successful, returns true; otherwise, returns false. + public bool SetBreakpointCondition(uint GDB_ID, string condition) + { + // Gets the parsed response for the GDB/MI command that sets a condition to the breakpoint "GDB_ID". If there is no + // condition, any previous one associated to this breakpoint will be removed. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) + string response = GdbWrapper.SendCommand(string.Concat(@"-break-condition ", GDB_ID, string.IsNullOrEmpty(condition) ? string.Empty : " ", condition ?? string.Empty), 19); + + if (response == "") + return false; + + HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); + hBreakpoints.Handle(response); + return true; + } + + /// + /// Delete a breakpoint in GDB. + /// + /// Breakpoint ID in GDB. + /// If successful, returns true; otherwise, returns false. + public bool DeleteBreakpoint(uint GDB_ID) + { + if (_gdbOutput.IsRunning) + { + PrepareToModifyBreakpoint(); + + // Gets the parsed response for the GDB/MI command that deletes the breakpoint "GDB_ID". + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) + string response = GdbWrapper.SendCommand(@"-break-delete " + GDB_ID, 7); + if (string.IsNullOrEmpty(response)) + { + ResumeFromInterrupt(); + return false; + } + + HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); + hBreakpoints.Handle(response); + uint retID = (uint)hBreakpoints.Number; + + ResumeFromInterrupt(); + + if (GDB_ID != retID) + { + return false; + } + } + + return true; + } + + /// + /// Enable or disable a breakpoint. + /// + /// Breakpoint ID in GDB. + /// If true, enable the breakpoint. If false, disable it. + /// If successful, returns true; otherwise, returns false. + public bool EnableBreakpoint(uint GDB_ID, bool enable) + { + PrepareToModifyBreakpoint(); + + // Gets the parsed response for the GDB/MI command that enables or disables the breakpoint "GDB_ID". + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html) + string response = GdbWrapper.SendCommand(@"-break-" + (enable ? "enable" : "disable") + " " + GDB_ID, 8); + + HandleBreakpoints hBreakpoints = new HandleBreakpoints(this); + hBreakpoints.Handle(response); + uint retID = (uint)hBreakpoints.Number; + + ResumeFromInterrupt(); + if (GDB_ID != retID) + { + return false; + } + + return true; + } + + /// + /// Update hit count. + /// + /// Breakpoint ID in GDB. + /// Hit count. + public void UpdateHitCount(uint id, uint hitCount) + { + var bbp = Engine.BreakpointManager.GetBoundBreakpointForGDBID(id); + if (bbp != null) + { + if (!bbp._breakWhenCondChanged) + { + ((IDebugBoundBreakpoint2) bbp).SetHitCount(hitCount); + } + } + } + + /// + /// Lock a breakpoint before updating its hit counts and/or condition. This is done to avoid a race condition that can happen when + /// user modifies a breakpoint condition at run time and the same breakpoint is hit. When that happens, only one event will be + /// handled at a time. + /// + /// Breakpoint to be locked. + /// True if user is adding/modifying count and conditions upon which a breakpoint is fired. It is also true + /// when event dispatcher is handling a breakpoint hit. + /// True if user is adding/modifying conditions under which a conditional breakpoint fires. It is also true + /// when event dispatcher is handling a breakpoint hit. + /// If successful, returns true; otherwise, returns false. + public bool LockedBreakpoint(AD7BoundBreakpoint bbp, bool hit, bool cond) + { + lock (_lockBreakpoint) + { + if (hit && cond) + { + if ((!bbp._blockedPassCount) && (!bbp._blockedConditional)) + { + bbp._blockedPassCount = true; + bbp._blockedConditional = true; + return true; + } + } + else if (hit) + { + if (!bbp._blockedPassCount) + { + bbp._blockedPassCount = true; + return true; + } + } + else if (cond) + { + if (!bbp._blockedConditional) + { + bbp._blockedConditional = true; + return true; + } + } + return false; + } + } + + /// + /// Unlock a breakpoint after updating its hit counts and/or condition. This is done to avoid a race condition that can happen when + /// user modifies a breakpoint condition at run time and the same breakpoint is hit. When that happens, only one event will be + /// handled at a time. + /// + /// Breakpoint to be locked. + /// True if user is adding/modifying count and conditions upon which a breakpoint is fired. It is also true + /// when event dispatcher is handling a breakpoint hit. + /// True if user is adding/modifying conditions under which a conditional breakpoint fires. It is also true + /// when event dispatcher is handling a breakpoint hit. + public void UnlockBreakpoint(AD7BoundBreakpoint bbp, bool hit, bool cond) + { + lock (_unlockBreakpoint) + { + if (hit && cond) + { + bbp._blockedPassCount = false; + bbp._blockedConditional = false; + } + else if (hit) + { + bbp._blockedPassCount = false; + } + else if (cond) + { + bbp._blockedConditional = false; + } + } + } + + /// + /// Control access to a critical region, that manipulates some of the debug engine variables, like its state. This is done to + /// avoid a race condition that can happen when user modifies a breakpoint condition at run time and the same breakpoint is hit. + /// When that happens, only one event will be handled at a time. + /// + /// If successful, returns true; otherwise, returns false. + public bool EnterCriticalRegion() + { + lock (_criticalRegion) + { + if (!_inCriticalRegion) + { + _inCriticalRegion = true; + return true; + } + return false; + } + } + + /// + /// Leave the critical region, that manipulates some of the debug engine variables, like its state. This is done to + /// avoid a race condition that can happen when user modifies a breakpoint condition at run time and the same breakpoint is hit. + /// When that happens, only one event will be handled at a time. + /// + public void LeaveCriticalRegion() + { + lock (_leaveCriticalRegion) + { + _inCriticalRegion = false; + } + } + + /// + /// Update VS when a breakpoint is hit in GDB. + /// + /// Breakpoint ID from GDB. + /// Thread ID. + public void BreakpointHit(uint id, string threadID) + { + var xBoundBreakpoints = new List(); + + // Search the active bound BPs and find ones that match the ID. + var bbp = Engine.BreakpointManager.GetBoundBreakpointForGDBID(id); + + if (bbp != null) + xBoundBreakpoints.Add(bbp); + + if (bbp == null || xBoundBreakpoints.Count == 0) + { + // if no matching breakpoints are found then its one of the following: + // - Stepping operation + // - Code based break + // - Asm stepping + } + else + { + if (LockedBreakpoint(bbp, true, true)) + { + while (!EnterCriticalRegion()) + { + Thread.Sleep(0); + } + + bool breakExecution = true; + + if (bbp._breakWhenCondChanged) + { + string result; + bool valid = VariableInfo.EvaluateExpression(bbp.m_bpCondition.bstrCondition, out result, null); + if ((valid) && (bbp._previousCondEvaluation != result)) // check if condition evaluation has changed + { + if ((bbp.m_bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL) && (bbp._hitCount != bbp.m_bpPassCount.dwPassCount)) + { + breakExecution = false; + } + else if ((bbp.m_bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL_OR_GREATER) && (bbp._hitCount < bbp.m_bpPassCount.dwPassCount)) + { + breakExecution = false; + } + else if ((bbp.m_bpPassCount.stylePassCount == enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_MOD) && ((bbp._hitCount % bbp.m_bpPassCount.dwPassCount) != 0)) + { + breakExecution = false; + } + bbp._previousCondEvaluation = result; + } + else + breakExecution = false; + } + if (!breakExecution) // must continue the execution + { + bool hitBreakAll = Engine._running.WaitOne(0); + if (hitBreakAll) + { + Engine.State = AD7Engine.DebugEngineState.Run; + + // Sends the GDB command that resumes the execution of the inferior program. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand(@"-exec-continue --thread-group i1"); + _GDBRunMode = true; + Engine._running.Set(); + } + } + else + { + if (bbp._breakWhenCondChanged) + bbp._hitCount += 1; + + // Transition DE state + _GDBRunMode = false; + Engine.State = AD7Engine.DebugEngineState.Break; + + // Found a bound breakpoint + Engine.Callback.OnBreakpoint(Engine.SelectThread(threadID), xBoundBreakpoints.AsReadOnly()); + + if (bbp._isHitCountEqual) + { + // Have to ignore the biggest number of times to keep the breakpoint enabled and to avoid stopping on it. + IgnoreHitCount(id, int.MaxValue); + } + else if (bbp._hitCountMultiple != 0) + { + IgnoreHitCount(id, (int)(bbp._hitCountMultiple - (bbp._hitCount % bbp._hitCountMultiple))); + } + } + LeaveCriticalRegion(); + UnlockBreakpoint(bbp, true, true); + } + else + { + while (!EnterCriticalRegion()) + { + Thread.Sleep(0); + } + + bool hitBreakAll = Engine._running.WaitOne(0); + if (hitBreakAll) + { + Engine.State = AD7Engine.DebugEngineState.Run; + + // Sends the GDB command that resumes the execution of the inferior program. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand(@"-exec-continue --thread-group i1"); + _GDBRunMode = true; + Engine._running.Set(); + } + + LeaveCriticalRegion(); + } + } + } + + /// + /// Return the depth of the stack. + /// + /// Thread ID. + /// Returns the stack depth. + public int GetStackDepth(string threadID) + { + // Returns the parsed response for the GDB/MI command that inquires about the depth of the stack. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) + return Convert.ToInt32(GdbWrapper.SendCommand(@"-stack-info-depth --thread " + threadID + " --frame 0", 9)); + } + + /// + /// List the frames currently on the stack. + /// + /// Returns a string with the frames currently on the stack. + public string GetStackFrames() + { + // Returns the parsed response for the GDB/MI command that list the frames currently on the stack. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) + return GdbWrapper.SendCommand(@"-stack-list-frames", 10); + } + + /// + /// List the names of local variables and function arguments for the selected frame. + /// + /// Frame number. + /// Thread ID. + /// Returns a string with the names of local variables and function arguments for the selected frame. + public string GetVariablesForFrame(uint frameIndex, string threadID) + { + // Returns the parsed response for the GDB/MI command that list the names of local variables and function arguments for the + // selected frame. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html) + return GdbWrapper.SendCommand(@"-stack-list-variables --thread " + threadID + " --frame " + frameIndex + " --simple-values", 11); + } + + /// + /// Make "id" the current thread. + /// + /// Thread ID. + public void SelectThread(string id) + { + // Waits for the parsed response for the GDB/MI command that make "id" the current thread. + // (http://www.sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html) + GdbWrapper.SendCommand(@"-thread-select " + id, 12); + } + + /// + /// Creates a variable object. + /// + /// Name of the variable. + /// Boolean value that indicates if the variable name has the prefix VsNdK_. + /// If successful, returns the variable's number of children; otherwise, returns string "ERROR". + public string CreateVariable(string name, out bool hasVsNdK) + { + hasVsNdK = false; + + // Gets the variable's number of children after sending the following GDB/MI command to create a variable object. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html) + string response = GdbWrapper.SendCommand("-var-create " + name + " \"*\" " + name, 13); + if (response == "ERROR") + { + // The -var-create GDB/MI command can return an error when the variable name starts with some characters, like '_'. + // So, in case of an error, add the prefix VsNdK_ to the variable name and try to create it again. + response = GdbWrapper.SendCommand("-var-create VsNdK_" + name + " \"*\" " + name, 13); + if (response != "ERROR") + hasVsNdK = true; + } + return response; + } + + /// + /// Deletes a previously created variable object and all of its children. + /// + /// Name of the variable. + /// Boolean value that indicates if the variable name has the prefix VsNdK_. + public void DeleteVariable(string name, bool hasVsNdK) + { + // Waits for the parsed response for the GDB/MI command that deletes a previously created variable object and all of + // its children. (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html) + if (!hasVsNdK) + GdbWrapper.SendCommand("-var-delete " + name, 14); + else + GdbWrapper.SendCommand("-var-delete VsNdK_" + name, 14); + } + + /// + /// Return a list of the children of the specified variable object. + /// + /// Variable name. + /// Return a string that contains the list of the children of the specified variable object. + public string ListChildren(string name) + { + // Returns the parsed response for the GDB/MI command that list the children of the specified variable object. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html) + return GdbWrapper.SendCommand("-var-list-children --all-values " + name + " 0 50", 15); + } + + /// + /// Kill the child process in which your program is running under gdb. + /// + public void KillProcess() + { + // Waits for the parsed response for the GDB command that kills the child process in which your program is running. + // (http://sourceware.org/gdb/onlinedocs/gdb/Kill-Process.html#Kill-Process) + GdbWrapper.SendCommand("kill", 16); + } + + /// + /// Called after the debug engine has set the initial breakpoints, or to resume a process that was interrupted. + /// + public void ContinueExecution() + { + //** Transition DE state + bool hitBreakAll = Engine._running.WaitOne(0); + if (hitBreakAll) + { + Engine.State = AD7Engine.DebugEngineState.Run; + + // Sends the GDB command that resumes the execution of the inferior program. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Program-Execution.html) + GdbWrapper.PostCommand(@"-exec-continue --thread-group i1"); + _GDBRunMode = true; + Engine._running.Set(); + } + } + } +} diff --git a/src_vs2010/DebugEngine/Engine.Impl/HandleBreakpoints.cs b/src_vs2010/DebugEngine/Engine.Impl/HandleBreakpoints.cs new file mode 100644 index 00000000..690508fc --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/HandleBreakpoints.cs @@ -0,0 +1,315 @@ +using System; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class manages breakpoints events. + /// + public sealed class HandleBreakpoints + { + /// + /// GDB breakpoint ID. + /// + private int _number = -1; + + /* + /// + /// Boolean variable that indicates if this breakpoint is enable (true) or disable (false). + /// + private bool _enabled; + */ + + /// + /// Breakpoint address. + /// + private string _address = ""; + + /// + /// Name of the function that contains this breakpoint. + /// + private string _functionName = ""; + + /// + /// File name that contains this breakpoint. + /// + private string _fileName = ""; + + /// + /// Line number for this breakpoint. + /// + private int _line = -1; + + /// + /// Number of hits for this breakpoint. + /// + private int _hits = -1; + + /// + /// Number of hits to be ignored by this breakpoint. + /// + private int _ignoreHits = -1; + + /// + /// Condition associated to this breakpoint. + /// + private string _condition = ""; + + /// + /// Thread ID that was interrupted when this breakpoint was hit. + /// + private string _threadID = ""; + + /// + /// This object manages debug events in the engine. + /// + private readonly EventDispatcher _eventDispatcher; + + /// + /// GDB_ID Property + /// + public int Number + { + get { return _number; } + } + + /// + /// GDB Line Position Property + /// + public int LinePosition + { + get { return _line; } + } + + /// + /// GDB File name + /// + public string FileName + { + get { return _fileName; } + } + + /// + /// GDB Address + /// + public string Address + { + get { return _address; } + } + + /// + /// Constructor. + /// + /// This object manages debug events in the engine. + public HandleBreakpoints(EventDispatcher ed) + { + _eventDispatcher = ed; + } + + /// + /// This method manages breakpoints events by classifying each of them by sub-type (e.g. breakpoint inserted, modified, etc.). + /// + /// String that contains the event description. + public void Handle(string ev) + { + int ini; + int end; + switch (ev[1]) + { + case '0': + // Breakpoint inserted (synchronous). + // Example: 20,1,y,0x0804d843,main,C:/Users/xxxxx/vsplugin-ndk/samples/Square/Square/main.c,319,0 + ini = 3; + end = ev.IndexOf(';', 3); + _number = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + /* + if (ev[end + 1] == 'y') + _enabled = true; + else + _enabled = false; + */ + + ini = end + 3; + end = ev.IndexOf(';', ini); + _address = ev.Substring(ini, (end - ini)); + if (_address == "") + { + _functionName = "??"; + EventDispatcher._unknownCode = true; + _fileName = ""; + _line = 0; + _hits = 0; + return; + } + + ini = end + 1; + end = ev.IndexOf(';', ini); + _functionName = ev.Substring(ini, end - ini); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _fileName = ev.Substring(ini, end - ini); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _line = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + _hits = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + + break; + case '1': + // Breakpoint modified (asynchronous). + // Example: 21,1,y,0x0804d843,main,C:/Users/xxxxxx/vsplugin-ndk/samples/Square/Square/main.c,318,1 + ini = 3; + end = ev.IndexOf(';', 3); + _number = Convert.ToInt32(ev.Substring(ini, (end - ini))); ; + + /* + if (ev[end + 1] == 'y') + _enabled = true; + else + _enabled = false; + */ + + ini = end + 3; + end = ev.IndexOf(';', ini); + _address = ev.Substring(ini, (end - ini)); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _functionName = ev.Substring(ini, end - ini); + + // Need to set the flag for unknown code if necessary. + if (_functionName == "??") + { + EventDispatcher._unknownCode = true; + } + else + { + EventDispatcher._unknownCode = false; + } + + ini = end + 1; + end = ev.IndexOf(';', ini); + _fileName = ev.Substring(ini, end - ini); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _line = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + _hits = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + + // Update hit count on affected bound breakpoint. + _eventDispatcher.UpdateHitCount((uint)_number, (uint)_hits); + + break; + case '2': + // Breakpoint deleted asynchronously (a temporary breakpoint). Example: 22,2\r\n + _number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); + + break; + case '3': + // Breakpoint enabled. Example: 23 (enabled all) or 23,1 (enabled only breakpoint 1) + if (ev.Length > 2) + _number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); + else + _number = 0; // 0 means ALL breakpoints. + + break; + case '4': + // Breakpoint disabled. Example: 24 (disabled all) or 24,1 (disabled only breakpoint 1) + if (ev.Length > 2) + _number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); + else + _number = 0; // 0 means ALL breakpoints. + + break; + case '5': + // Breakpoint deleted. Example: 25 (deleted all) or 25,1 (deleted only breakpoint 1) + if (ev.Length > 2) + _number = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); + else + _number = 0; // 0 means ALL breakpoints. + + break; + case '6': + // Break after "n" hits (or ignore n hits). Example: 26;1;100 + ini = 3; + end = ev.IndexOf(';', 3); + _number = Convert.ToInt32(ev.Substring(3, (end - 3))); + + ini = end + 1; + _ignoreHits = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + + break; + case '7': + // Breakpoint hit. + // Example: 27,1,C:/Users/xxxxxx/vsplugin-ndk/samples/Square/Square/main.c,319;1\r\n + bool updatingCondBreak = _eventDispatcher.Engine._updatingConditionalBreakpoint.WaitOne(0); + if (updatingCondBreak) + { + + _eventDispatcher.Engine.ResetStackFrames(); + + ini = 3; + end = ev.IndexOf(';', ini); + _number = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _fileName = ev.Substring(ini, end - ini); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _line = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + _threadID = ev.Substring(ini, (ev.Length - ini)); + + _eventDispatcher.Engine.CleanEvaluatedThreads(); + + // Call the method/event that will stop SDM because a breakpoint was hit here. + if (_eventDispatcher.Engine._updateThreads) + { + _eventDispatcher.Engine.UpdateListOfThreads(); + } + _eventDispatcher.Engine.SelectThread(_threadID).SetCurrentLocation(_fileName, (uint)_line); + _eventDispatcher.Engine.SetAsCurrentThread(_threadID); + + // A breakpoint can be hit during a step + if (_eventDispatcher.Engine.State == AD7Engine.DebugEngineState.Step) + { + HandleProcessExecution.OnStepCompleted(_eventDispatcher, _fileName, (uint)_line); + } + else + { + _eventDispatcher.BreakpointHit((uint)_number, _threadID); + } + _eventDispatcher.Engine._updatingConditionalBreakpoint.Set(); + } + break; + case '8': + // Breakpoint condition set. Example: 28;1;expression + ini = 3; + end = ev.IndexOf(';', 3); + if (end != -1) + { + _number = Convert.ToInt32(ev.Substring(3, (end - 3))); + + ini = end + 1; + _condition = ev.Substring(ini, (ev.Length - ini)); + } + else + { + _number = Convert.ToInt32(ev.Substring(3)); + _condition = ""; + } + break; + case '9': // Error in testing breakpoint condition + break; + } + } + } +} diff --git a/src_vs2010/DebugEngine/Engine.Impl/HandleOutputs.cs b/src_vs2010/DebugEngine/Engine.Impl/HandleOutputs.cs new file mode 100644 index 00000000..f5b8a8c7 --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/HandleOutputs.cs @@ -0,0 +1,70 @@ +using System; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class manages events related to output messages. + /// + public sealed class HandleOutputs + { + /// + /// GDB textual output from the running target to be presented in the VS standard output window. + /// + private string _stdOut = ""; + + /// + /// Other GDB messages to be presented in the VS standard output window. + /// + private string _console = ""; + + /// + /// This object manages debug events in the engine. + /// + private EventDispatcher _eventDispatcher; + + /// + /// Constructor. + /// + /// This object manages debug events in the engine. + public HandleOutputs(EventDispatcher eventDispatcher) + { + if (eventDispatcher == null) + throw new ArgumentNullException("eventDispatcher"); + + _eventDispatcher = eventDispatcher; + } + + /// + /// This method manages events related to output messages by classifying each of them by sub-type. + /// + /// String that contains the event description. + public void Handle(string ev) + { + int ini; + int end; + switch (ev[1]) + { + case '0': // Display the m_console message in the VS output window. Example: 80,\"\"[New pid 15380494 tid 2]\\n\"\"!80 + ini = 4; + end = ev.IndexOf("\"!80", 4); + if (end == -1) + end = ev.Length; + _console = ev.Substring(ini, (end - ini)); + + // TODO: Call the method/event that will output this message in the VS output window. + + break; + case '1': // Display the m_stdOut message in the VS standard output window. Instruction should look like this: 81,\"\" ... "\"!81 + ini = 4; + end = ev.IndexOf("\"!81", 4); + if (end == -1) + end = ev.Length; + _stdOut = ev.Substring(ini, (end - ini)); + + // TODO: Call the method/event that will output this message in the VS standar output window. + + break; + } + } + } +} \ No newline at end of file diff --git a/src_vs2010/DebugEngine/Engine.Impl/HandleProcessExecution.cs b/src_vs2010/DebugEngine/Engine.Impl/HandleProcessExecution.cs new file mode 100644 index 00000000..a9e52670 --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/HandleProcessExecution.cs @@ -0,0 +1,576 @@ +using System; +using System.Threading; +using System.Windows.Forms; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio.Debugger.Interop; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class manages events related to execution control (processes, threads, programs). + /// + public sealed class HandleProcessExecution + { + /// + /// Thread ID. + /// + private int _threadId = -1; // when threadId is 0, it means all threads. + + /// + /// Process ID. + /// + private int _processId = -1; + + /// + /// Name of the signal that caused an interruption. + /// + private string _signalName = ""; + + /// + /// Meaning of the signal that caused an interruption. + /// + private string _signalMeaning = ""; + + /// + /// File name. + /// + private string _fileName = ""; + + /// + /// Line number. + /// + private int _line = -1; + + /// + /// Address. + /// + private int _address = -1; + + /// + /// Function name. + /// + private string _functionName = ""; + + /// + /// Error caused by a GDB command that failed. + /// + private string _error = ""; + + /// + /// This object manages debug events in the engine. + /// + private readonly EventDispatcher _eventDispatcher; + + /// + /// Boolean variable that indicates if GDB has to resume execution after handling what caused it to enter in break mode. + /// + public static bool NeedsResumeAfterInterrupt; + + /// + /// Used as a communication signal between the Event Dispatcher and the debug engine method responsible for stopping GDB + /// execution (IDebugEngine2.CauseBreak()). So, VS is able to wait for GDB's interruption before entering in break mode. + /// + public static ManualResetEvent m_mre = new ManualResetEvent(false); + + /// + /// Constructor. + /// + /// This object manages debug events in the engine. + public HandleProcessExecution(EventDispatcher eventDispatcher) + { + if (eventDispatcher == null) + throw new ArgumentNullException("eventDispatcher"); + + _eventDispatcher = eventDispatcher; + } + + /// + /// This method manages events related to execution control by classifying each of them by sub-type (e.g. thread created, program interrupted, etc.). + /// + /// String that contains the event description. + public void Handle(string ev) + { + int ini = 0; + int end = 0; + int numCommas = 0; + switch (ev[0]) + { + case '4': + switch (ev[1]) + { + case '0': + // Thread created. Example: 40,2,20537438 + EventDispatcher._GDBRunMode = true; + ini = 3; + end = ev.IndexOf(";", 3); + _threadId = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + try + { + _processId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + } + catch + { + _processId = 0; + } + + _eventDispatcher.Engine._updateThreads = true; + + break; + case '1': + // Process running. Example: 41,1 (when threadId is 0 means "all threads": example: 41,0) + EventDispatcher._GDBRunMode = true; + _threadId = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); + + break; + case '2': + // Program exited normally. Example: 42 + _eventDispatcher.EndDebugSession(0); + + break; + case '3': + // Program was exited with an exit code. Example: 43,1;1 (not sure if there is a threadID, but the last ";" exist) + // TODO: not tested yet + end = ev.IndexOf(";", 3); + uint exitCode = Convert.ToUInt32(ev.Substring(3, (end - 3))); + _eventDispatcher.EndDebugSession(exitCode); + + break; + case '4': + // Program interrupted. + // Examples: + // 44,ADDR,FUNC,THREAD-ID + // 44,ADDR,FUNC,FILENAME,LINE,THREAD-ID + + _eventDispatcher.Engine.ResetStackFrames(); + EventDispatcher._GDBRunMode = false; + numCommas = 0; + foreach (char c in ev) + { + if (c == ';') + numCommas++; + } + + ini = 3; + end = ev.IndexOf(';', ini); + _address = Convert.ToInt32(ev.Substring(ini, (end - ini)), 16); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _functionName = ev.Substring(ini, (end - ini)); + + if (_functionName == "??") + { + EventDispatcher._unknownCode = true; + } + else + { + EventDispatcher._unknownCode = false; + } + + switch (numCommas) + { + case 3: + // Thread ID + ini = end + 1; + try + { + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + } + catch (Exception ex) + { + _threadId = -1; + TraceLog.WriteException(ex, "Unable to parse ThreadID from: \"{0}\"", ev); + } + EventDispatcher._unknownCode = true; + break; + case 4: + // Filename and line number + ini = end + 1; + end = ev.IndexOf(';', ini); + _fileName = ev.Substring(ini, (end - ini)); + + ini = end + 1; + _line = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + break; + case 5: + // Filename, line number and thread ID + ini = end + 1; + end = ev.IndexOf(';', ini); + _fileName = ev.Substring(ini, (end - ini)); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _line = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + break; + } + + _eventDispatcher.Engine.CleanEvaluatedThreads(); + + + if (_eventDispatcher.Engine._updateThreads) + { + _eventDispatcher.Engine.UpdateListOfThreads(); + } + if (_threadId > 0) + { + var thread =_eventDispatcher.Engine.SelectThread(_threadId.ToString()); + + if (thread != null) + { + thread.SetCurrentLocation(_fileName, (uint) _line); + _eventDispatcher.Engine.SetAsCurrentThread(_threadId.ToString()); + } + } + + // Call the method/event that will let SDM know that the debugged program was interrupted. + OnInterrupt(_threadId); + + // Signal that interrupt is processed + m_mre.Set(); + + break; + + case '5': + // End-stepping-range. + _eventDispatcher.Engine.ResetStackFrames(); + EventDispatcher._GDBRunMode = false; + ini = 3; + end = ev.IndexOf(';', 3); + if (end == -1) + end = ev.Length; + string temp = ev.Substring(ini, (end - ini)); + + ini = end + 1; + + if (ev.Length > ini) + end = ev.IndexOf(';', ini); + else + end = -1; + + if (end == -1) + { + // Set sane default values for the missing file and line information + _fileName = ""; + _line = 1; + _threadId = Convert.ToInt32(temp); + EventDispatcher._unknownCode = true; + } + else + { + _fileName = temp; + _line = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + EventDispatcher._unknownCode = false; + } + + _eventDispatcher.Engine.CleanEvaluatedThreads(); + + + if (_eventDispatcher.Engine._updateThreads) + { + _eventDispatcher.Engine.UpdateListOfThreads(); + } + if (_threadId > 0) + { + if ((EventDispatcher._unknownCode == false) && (_fileName != "")) + _eventDispatcher.Engine.SelectThread(_threadId.ToString()).SetCurrentLocation(_fileName, (uint)_line); + _eventDispatcher.Engine.SetAsCurrentThread(_threadId.ToString()); + } + + OnStepCompleted(_eventDispatcher, _fileName, (uint)_line); + + break; + case '6': + // Function-finished. + _eventDispatcher.Engine.ResetStackFrames(); + EventDispatcher._GDBRunMode = false; + ini = 3; + end = ev.IndexOf(';', 3); + if (end == -1) + { + // Set sane default values for the missing file and line information + _fileName = ""; + _line = 1; + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + EventDispatcher._unknownCode = true; + } + else + { + _fileName = ev.Substring(ini, (end - ini)); + ini = end + 1; + end = ev.IndexOf(';', ini); + _line = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + EventDispatcher._unknownCode = false; + } + + _eventDispatcher.Engine.CleanEvaluatedThreads(); + + if (_eventDispatcher.Engine._updateThreads) + { + _eventDispatcher.Engine.UpdateListOfThreads(); + } + if (_threadId > 0) + { + if ((EventDispatcher._unknownCode == false) && (_fileName != "")) + _eventDispatcher.Engine.SelectThread(_threadId.ToString()).SetCurrentLocation(_fileName, (uint)_line); + _eventDispatcher.Engine.SetAsCurrentThread(_threadId.ToString()); + } + + OnStepCompleted(_eventDispatcher, _fileName, (uint)_line); + + break; + case '7': + // -exec-interrupt or signal-meaning="Killed". There's nothing to do in this case. + _eventDispatcher.Engine.ResetStackFrames(); + EventDispatcher._GDBRunMode = false; + + _eventDispatcher.Engine.CleanEvaluatedThreads(); + + _threadId = Convert.ToInt32(ev.Substring(3, (ev.Length - 3))); + + if (_eventDispatcher.Engine._updateThreads) + { + _eventDispatcher.Engine.UpdateListOfThreads(); + } + if (_threadId > 0) + { + if ((EventDispatcher._unknownCode == false) && (_fileName != "")) + _eventDispatcher.Engine.SelectThread(_threadId.ToString()).SetCurrentLocation(_fileName, (uint)_line); + _eventDispatcher.Engine.SetAsCurrentThread(_threadId.ToString()); + } + + if (_eventDispatcher.Engine.State != AD7Engine.DebugEngineState.Break) + { + OnInterrupt(_threadId); + } + // Signal that interrupt is processed + m_mre.Set(); + + break; + case '8': + // SIGKILL + _eventDispatcher.EndDebugSession(0); + break; + case '9': + // ERROR, ex: 49,Cannot find bounds of current function + _eventDispatcher.Engine.ResetStackFrames(); + _eventDispatcher.Engine.CleanEvaluatedThreads(); + + if (_eventDispatcher.Engine._updateThreads) + { + _eventDispatcher.Engine.UpdateListOfThreads(); + } + + if (ev.Length >= 3) + { + _error = ev.Substring(3, (ev.Length - 3)); + if (_error == "Cannot find bounds of current function") + { + // We don't have symbols for this function so further stepping won't be possible. Return from this function. + EventDispatcher._unknownCode = true; + _eventDispatcher.Engine.Step(_eventDispatcher.Engine.CurrentThread(), enum_STEPKIND.STEP_OUT, enum_STEPUNIT.STEP_LINE); + } + } + break; + } + break; + case '5': + switch (ev[1]) + { + case '0': + // Quit (expect signal SIGINT when the program is resumed) + _eventDispatcher.countSIGINT += 1; + if (_eventDispatcher.countSIGINT > 5) + { + _eventDispatcher.EndDebugSession(0); + MessageBoxHelper.Show("Lost communication with GDB. Please refer to documentation for more details.", "GDB failure", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + break; + case '1': + // Thread exited. Example: 51,2 + ini = 3; + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + + _eventDispatcher.Engine._updateThreads = true; + + break; + case '2': + // GDB Bugs, like "... 2374: internal-error: frame_cleanup_after_sniffer ...". Example: 52 + _eventDispatcher.EndDebugSession(0); + MessageBoxHelper.Show("This is a known issue that can happen when interrupting GDB's execution by hitting the \"break all\" or toggling a breakpoint in run mode. \n\n GDB CRASHED. Details: \"../../gdb/frame.c:2374: internal-error: frame_cleanup_after_sniffer: Assertion `frame->prologue_cache == NULL' failed.\nA problem internal to GDB has been detected,\nfurther debugging may prove unreliable.\" \r\n \nPlease close the app in the device/simulator if you want to debug it again.", "GDB failure", MessageBoxButtons.OK, MessageBoxIcon.Error); + + break; + case '3': + // Lost communication with device/simulator: ^error,msg="Remote communication error: No error." + MessageBoxHelper.Show("Lost communication with the device/simulator.", "Communication lost", MessageBoxButtons.OK, MessageBoxIcon.Error); + _eventDispatcher.EndDebugSession(0); + + break; + case '4': + // Program interrupted due to a segmentation fault. + // Examples: + // 54,ADDR,FUNC,THREAD-ID + // 54,ADDR,FUNC,FILENAME,LINE,THREAD-ID + + _eventDispatcher.Engine.ResetStackFrames(); + EventDispatcher._GDBRunMode = false; + numCommas = 0; + foreach (char c in ev) + { + if (c == ';') + numCommas++; + } + + ini = 3; + end = ev.IndexOf(';', ini); + _address = Convert.ToInt32(ev.Substring(ini, (end - ini)), 16); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _functionName = ev.Substring(ini, (end - ini)); + + if (_functionName == "??") + { + EventDispatcher._unknownCode = true; + } + else + { + EventDispatcher._unknownCode = false; + } + + switch (numCommas) + { + case 3: + // Thread ID + ini = end + 1; + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + EventDispatcher._unknownCode = true; + break; + case 5: + // Filename, line number and thread ID + ini = end + 1; + end = ev.IndexOf(';', ini); + _fileName = ev.Substring(ini, (end - ini)); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _line = Convert.ToInt32(ev.Substring(ini, (end - ini))); + + ini = end + 1; + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + break; + } + + MessageBoxHelper.Show("Segmentation Fault: If you continue debugging could take the environment to an unstable state.", "Segmentation Fault", MessageBoxButtons.OK, MessageBoxIcon.Warning); + + _eventDispatcher.Engine.CleanEvaluatedThreads(); + + if (_eventDispatcher.Engine._updateThreads) + { + _eventDispatcher.Engine.UpdateListOfThreads(); + } + if (_threadId > 0) + { + _eventDispatcher.Engine.SelectThread(_threadId.ToString()).SetCurrentLocation(_fileName, (uint)_line); + _eventDispatcher.Engine.SetAsCurrentThread(_threadId.ToString()); + } + + OnInterrupt(_threadId); + + break; + + case '5': + // Exited-signaled. Ex: 55;SIGSEGV;Segmentation fault + // or Aborted. Ex: 55;SIGABRT;Aborted + ini = 3; + end = ev.IndexOf(';', ini); + _signalName = ev.Substring(ini, (end - ini)); + + ini = end + 1; + end = ev.IndexOf(';', ini); + _signalMeaning = ev.Substring(ini, (end - ini)); + + ini = end + 1; + try + { + _threadId = Convert.ToInt32(ev.Substring(ini, (ev.Length - ini))); + } + catch + { + } + + if (_signalMeaning == "Segmentation fault") + { + MessageBoxHelper.Show("Segmentation Fault: Closing debugger.", "Segmentation Fault", MessageBoxButtons.OK, MessageBoxIcon.Error); + _eventDispatcher.EndDebugSession(0); + } + + if (_signalMeaning == "Aborted") + { + MessageBoxHelper.Show("Program aborted: Closing debugger.", "Program Aborted", MessageBoxButtons.OK, MessageBoxIcon.Error); + _eventDispatcher.EndDebugSession(0); + } + + break; + case '6': + // GDB Bugs, like "... 3550: internal-error: handle_inferior_event ...". Example: 56 + _eventDispatcher.EndDebugSession(0); + MessageBoxHelper.Show("This is a known issue that can happen while debugging multithreaded programs. \n\n GDB CRASHED. Details: \"../../gdb/infrun.c:3550: internal-error: handle_inferior_event: Assertion ptid_equal (singlestep_ptid, ecs->ptid)' failed.\nA problem internal to GDB has been detected,\nfurther debugging may prove unreliable.\" \r\n \nPlease close the app in the device/simulator if you want to debug it again.", "GDB failure", MessageBoxButtons.OK, MessageBoxIcon.Error); + + break; + case '7': // Not used + break; + case '8': // Not used + break; + case '9': // Not used + break; + } + break; + } + } + + /// + /// Update VS when a step action is completed in GDB. + /// + /// This object manages debug events in the engine. + /// File name. + /// Line number. + public static void OnStepCompleted(EventDispatcher eventDispatcher, string file, uint line) + { + if (eventDispatcher.Engine.State == AD7Engine.DebugEngineState.Step) + { + eventDispatcher.Engine.State = AD7Engine.DebugEngineState.Break; + AD7StepCompletedEvent.Send(eventDispatcher.Engine); + } + } + + /// + /// Update VS when the debugging process is interrupted in GDB. + /// + /// Thread ID. + private void OnInterrupt(int threadID) + { + if (_eventDispatcher.Engine.State == AD7Engine.DebugEngineState.Run) + { + _eventDispatcher.Engine.State = AD7Engine.DebugEngineState.Break; + + // Only send OnAsyncBreakComplete if break-all was requested by the user + if (!NeedsResumeAfterInterrupt) + { + _eventDispatcher.Engine.Callback.OnAsyncBreakComplete(_eventDispatcher.Engine.SelectThread(threadID.ToString())); + } + } + } + } +} diff --git a/src_vs2010/DebugEngine/Engine.Impl/VariableInfo.cs b/src_vs2010/DebugEngine/Engine.Impl/VariableInfo.cs new file mode 100644 index 00000000..61e9a0f1 --- /dev/null +++ b/src_vs2010/DebugEngine/Engine.Impl/VariableInfo.cs @@ -0,0 +1,580 @@ +using System; +using System.Collections; +using BlackBerry.NativeCore.Debugger; + +namespace BlackBerry.DebugEngine +{ + /// + /// This class contains all information about a variable / expression. + /// + public sealed class VariableInfo + { + /// + /// Variable's name or expression. + /// + public readonly string _name; + + /// + /// Variable's data type. + /// + public string _type; + + /// + /// Variable's value or the result of an expression. + /// + public string _value; + + /// + /// Variable's name to be used by GDB. + /// + public string _GDBName; + + /// + /// List of variable's children. + /// + public ArrayList _children; + + + /// + /// Evaluate an expression / Get the value of a variable. This method basically send a "-data-evaluate-expression" command to GDB + /// and evaluate the result. + /// + /// The expression/variable to be evaluated. + /// The result of the expression/ value of variable. + /// The GDB Name of the variable. + /// A boolean value indicating if the expression evaluation was successful or not. + public static bool EvaluateExpression(string name, out string result, string gdbName) + { + if (string.IsNullOrEmpty(name)) + { + result = string.Empty; + return false; + } + + if (name[name.Length - 1] == '.') + name = name.Remove(name.Length - 1); + + // Waits for the parsed response for the GDB/MI command that evaluates "name" as an expression. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Data-Manipulation.html) + result = GdbWrapper.SendCommand("-data-evaluate-expression \"" + name + "\"", 2); + if (string.IsNullOrEmpty(result) || result.Length < 2) + { + result = string.Empty; + return false; + } + + if (result.StartsWith("61")) // If result starts with 61, it means that there is an error. + { + if (gdbName != null) // Maybe that error was caused because GDB didn't accept the VS name. Use the GDBName if there is one. + { + // Gets the parsed response for the GDB/MI command that evaluates "GDBName" as an expression. + // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Data-Manipulation.html) + string result2 = GdbWrapper.SendCommand("-data-evaluate-expression \"" + gdbName + "\"", 2); + if (result2.StartsWith("60")) + result = result2; + } + } + + // If result starts with 61, it means that there is an error. So, expression is not valid. + bool valid = !result.StartsWith("61"); + + result = result.Substring(3); + result = result.Replace("\\\"", "\""); + + if (valid) + { + int endString = result.IndexOf("\\\\000"); + int ini, end = 0; + while (endString != -1) // remove garbage from strings + { + ini = result.IndexOf("\"", end); + while ((ini > 0) && (result[ini - 1] == '\\')) + ini = result.IndexOf("\"", ini + 1); + if (ini == -1) + break; + end = result.IndexOf("\"", ini + 1); + while ((end > 0) && (result[end - 1] == '\\')) + end = result.IndexOf("\"", end + 1); + if (end == -1) + break; + while ((endString != -1) && (endString < ini)) + endString = result.IndexOf("\\\\000", endString + 1); + if ((endString > ini) && (endString < end)) + { + result = result.Substring(0, endString) + result.Substring(end, (result.Length - end)); + end = endString; + endString = result.IndexOf("\\\\000", end); + } + end++; + }; + } + return valid; + } + + /// + /// Gets the information about a variable/expression. + /// + /// Variable name / expression. + /// The event dispatcher. + /// Current stack frame. + /// Return the VariableInfo object. + public static VariableInfo Get(string name, EventDispatcher eventDispatcher, AD7StackFrame frame) + { + VariableInfo vi = null; + string search = ""; + string separator = ""; + bool isArray = false; + bool isRoot = true; + + do + { + int dot = name.IndexOf('.'); + int squareBracket = name.IndexOf('['); + int pos = name.IndexOf("->", StringComparison.Ordinal); + if (dot == -1) + dot = name.Length; + if (squareBracket == -1) + squareBracket = name.Length; + if (pos == -1) + pos = name.Length; + int stop = dot < squareBracket ? dot : squareBracket; + stop = stop < pos ? stop : pos; + + search = search + separator + name.Substring(0, stop); + separator = ""; + + if (stop < name.Length) + { + separator = name.Substring(stop, 1); + if (separator == "-") + { + separator = "->"; + name = name.Substring(stop + 2, name.Length - (stop + 2)); + } + else if (separator == "[") + { + int aux = name.IndexOf("]"); + isArray = true; + separator = name.Substring(stop, (aux - stop) + 1); + name = name.Substring(aux + 1, name.Length - (aux + 1)); + } + else + name = name.Substring(stop + 1, name.Length - (stop + 1)); + } + else + name = ""; + + if (vi == null) + { + if (frame._locals != null) + { + foreach (VariableInfo var in frame._locals) + { + if (var._name == search) + { // if the "search" expression is a local variable, it doesn't need to create a VariableInfo object for that. + vi = var; + break; + } + } + } + + if (vi == null) + { + if (frame._arguments != null) + { + foreach (VariableInfo var in frame._arguments) + { // if the "search" expression is an argument, it doesn't need to create a VariableInfo object for that. + if (var._name == search) + { + vi = var; + break; + } + } + } + } + } + else + { + isRoot = false; + VariableInfo vi_child = null; + if (vi._children != null) + { + foreach (VariableInfo var in vi._children) + { + if (var._name == search) + { + vi_child = var; + break; + } + } + } + vi = vi_child; + } + } while ((vi != null) && ((isArray) || (name != ""))); + + + if (name != "") // variable not found probably because it is in an expression, so return to the original name to evaluate it. + search = search + separator + name; + + string result; + bool valid; + if (vi == null) + valid = EvaluateExpression(search, out result, null); + else + valid = EvaluateExpression(search, out result, vi._GDBName); + + if (vi != null) + { + if ((vi._value != result) || (!isRoot)) // if is not root means that it can be expanded... + { + vi._value = result; + if (vi._value == null || (vi._type.Contains("*") && (vi._value != "0x0"))) + { + // This is an array, struct, union, or pointer. + // Create a variable object so we can list this variable's children. + ArrayList GDBNames = new ArrayList(); + ArrayList VSNames = new ArrayList(); + bool hasVsNdK; + eventDispatcher.CreateVariable(vi._name, out hasVsNdK); + if (hasVsNdK) + { + GDBNames.Add("VsNdK_" + vi._name); + VSNames.Add(vi._name); + } + vi._children = new ArrayList(); + if (vi._type.Contains("struct")) + if (vi._type[vi._type.Length - 1] == '*') + vi.ListChildren(eventDispatcher, "*", GDBNames, VSNames, hasVsNdK, null); + else if (vi._type.Contains("[")) + vi.ListChildren(eventDispatcher, "struct[]", GDBNames, VSNames, hasVsNdK, null); + else + vi.ListChildren(eventDispatcher, "struct", GDBNames, VSNames, hasVsNdK, null); + else if (vi._type.Contains("[")) + vi.ListChildren(eventDispatcher, "[]", GDBNames, VSNames, hasVsNdK, null); + else if (vi._type.Contains("*")) + vi.ListChildren(eventDispatcher, "*", GDBNames, VSNames, hasVsNdK, null); + else + vi.ListChildren(eventDispatcher, "", GDBNames, VSNames, hasVsNdK, null); + eventDispatcher.DeleteVariable(vi._name, hasVsNdK); + } + } + } + else + { + if (!valid) + vi = new VariableInfo(search, "", result, null); + else + { + string aux_exp = search.Replace(" ", ""); + string datatype; + + // Sending 2 GDB commands to get the data type of "aux_exp" because it is not known, at this moment, if "aux_exp" + // is an expression, a primitive or a compound variable. + + // Gets the parsed response for the GDB command that returns the data type of "aux_exp". + // (http://sourceware.org/gdb/onlinedocs/gdb/Symbols.html) + string firstDatatype = GdbWrapper.SendCommand("whatis " + aux_exp, 3); + + // Gets the parsed response for the GDB command that returns a detailed description of the type. + // (http://sourceware.org/gdb/onlinedocs/gdb/Symbols.html) + string baseDatatype = GdbWrapper.SendCommand("ptype " + aux_exp, 4); + + if ((baseDatatype[baseDatatype.Length - 1] == '{') && (baseDatatype[baseDatatype.Length - 2] == ' ')) + baseDatatype = baseDatatype.Remove(baseDatatype.Length - 2); + if (baseDatatype.Length < firstDatatype.Length) + { + if (firstDatatype.Contains(baseDatatype)) + { + baseDatatype = firstDatatype; + } + } + if ((baseDatatype == firstDatatype) || ((baseDatatype.Contains("::")) && (!baseDatatype.Contains("union")))) + { + baseDatatype = ""; + datatype = firstDatatype; + } + else + { + datatype = baseDatatype; + } + if (datatype[datatype.Length - 1] == '*') + if (result == "0x0") + { + vi = new VariableInfo(search, firstDatatype, result, null); + } + else + { + vi = new VariableInfo(search, firstDatatype, baseDatatype, result, eventDispatcher, null, null); + } + else if ((datatype.Contains("struct")) || (datatype.Contains("["))) + { + vi = new VariableInfo(search, firstDatatype, baseDatatype, null, eventDispatcher, null, null); + } + else + { + vi = new VariableInfo(search, firstDatatype, result, null); + } + } + } + return vi; + } + + /// + /// Call the right VariableInfo constructor for locals and arguments. + /// + /// The name of the variable. + /// The data type of the variable. + /// The value of the variable. + /// The event dispatcher. + /// Return the VariableInfo created object. + public static VariableInfo Create(string name, string type, string value, EventDispatcher dispatcher) + { + VariableInfo newVar = new VariableInfo(name, type, "", value, dispatcher, null, null); + return newVar; + } + + /// + /// Constructor for Variable Info Object without inquiring for the variable's children. + /// + /// The name of the variable. + /// The data type of the variable. + /// The value of the variable. + /// The GDB Name of the variable. + public VariableInfo(string name, string type, string value, string gdbName) + { + _name = name; + _type = type; + _value = value; + _children = null; + _GDBName = gdbName; + } + + /// + /// Constructor for Variable Info Object inquiring for the variable's children + /// + /// The name of the variable. + /// The data type of the variable. + /// The base type of the variable. + /// The value of the variable. + /// The event dispatcher. + /// The names of the variables used by GDB. + /// The Names of the variables used by VS. + public VariableInfo(string name, string type, string baseType, string value, EventDispatcher dispatcher, ArrayList gdbNames, ArrayList vsNames) + { + // numChildren - The result of the createvar returns ERROR or a number from 0 to "n" where "n" is the number of children of the variable. + + _name = name; + _type = type; + _value = value; + _children = null; + _GDBName = null; + + if (baseType != "") + type = baseType; + + if (gdbNames == null) + { + gdbNames = new ArrayList(); + vsNames = new ArrayList(); + } + + if (value == null || (type.Contains("*") && (value != "0x0"))) + { + // This is an array, struct, union, or pointer. + // Create a variable object so we can list this variable's children. + + // Some VS variable names cannot be used by GDB. When that happens, it is added the prefix VsNdK_ to the GDB variable + // name and it is stored in the GDBNames array. At the same time, the VS name is stored in the VSNames array using the + // same index position. This bool variable just indicate if this prefix is used or not. + bool hasVsNdK; + string numChildren = dispatcher.CreateVariable(_name, out hasVsNdK); + + if (hasVsNdK) + { + _GDBName = "VsNdK_" + _name; + gdbNames.Add("VsNdK_" + _name); + vsNames.Add(_name); + } + + try // Catch non-numerical data + { + if (Convert.ToInt32(numChildren) > 0) // If the variable has children, evaluate them. + { + _children = new ArrayList(); + if (type.Contains("struct")) + if (type[type.Length - 1] == '*') + ListChildren(dispatcher, "*", gdbNames, vsNames, hasVsNdK, null); + else if (type.Contains("[")) + ListChildren(dispatcher, "struct[]", gdbNames, vsNames, hasVsNdK, null); + else + ListChildren(dispatcher, "struct", gdbNames, vsNames, hasVsNdK, null); + else if (type.Contains("[")) + ListChildren(dispatcher, "[]", gdbNames, vsNames, hasVsNdK, null); + else if (type.Contains("*")) + ListChildren(dispatcher, "*", gdbNames, vsNames, hasVsNdK, null); + else + ListChildren(dispatcher, "", gdbNames, vsNames, hasVsNdK, null); + } + } + catch (FormatException) + { + + } + + dispatcher.DeleteVariable(_name, hasVsNdK); + } + + if (value == null) + EvaluateExpression(name, out _value, null); + } + + /// + /// Gets the list of children for a given variable. + /// + /// The event dispatcher. + /// The variable's parent data type. "*" means it is a pointer; "struct[]" means it is an array of + /// structures; "struct" means it is a structure; and "[]" means it is an array. + /// The names of the variables used by GDB. + /// The Names of the variables used by VS. + /// Indicate if the variable name uses or not the prefix "VsNdK_". + /// The GDB Name of the variable. + public void ListChildren(EventDispatcher dispatcher, string parentType, ArrayList gdbNames, ArrayList vsNames, bool hasVsNdK, string gdbName) + { + string childListResponse; + if (gdbName == null) + { + if (hasVsNdK) + { + childListResponse = dispatcher.ListChildren(_GDBName); + } + else + { + childListResponse = dispatcher.ListChildren(_name); + if ((childListResponse == "ERROR") && (_GDBName != null)) + { + childListResponse = dispatcher.ListChildren(_GDBName); + } + } + } + else + childListResponse = dispatcher.ListChildren(gdbName); + + if (childListResponse != "ERROR") + { + childListResponse = (childListResponse.Substring(3)).Replace("#;;;", ""); + + string[] childList = childListResponse.Split('#'); + foreach (string childString in childList) + { + string name = null; + string type = null; + string value = null; + int numChildren = 0; + bool valid = true; + + string[] childProperties = childString.Split(';'); + + if (childProperties[0] == "") + continue; + + name = childProperties[0]; + + if (name.Contains("::")) // discard this GDB expression. + { + continue; + } + + gdbName = name; + + int end = name.Length; + if (name[end - 1] == '"') + end--; + if (((name.Length > 8) && (name.Substring(end - 8, 8) == ".private")) || + ((name.Length > 7) && (name.Substring(end - 7, 7) == ".public")) || + ((name.Length > 10) && (name.Substring(end - 10, 10) == ".protected")) || + ((name.Length > 9) && (name.Substring(end - 9, 9) == ".private.")) || + ((name.Length > 8) && (name.Substring(end - 8, 8) == ".public.")) || + ((name.Length > 11) && (name.Substring(end - 11, 11) == ".protected."))) + { + // GDB is using an intermediate representation for the variable. Inquire GDB again using this intermediate name. + int index = vsNames.IndexOf(_name); + if (index != -1) + gdbNames[index] = gdbName; + else + { + gdbNames.Add(gdbName); + vsNames.Add(_name); + } + ListChildren(dispatcher, parentType, gdbNames, vsNames, hasVsNdK, gdbName); + continue; + } + else + { + int dot = name.LastIndexOf("."); + if (dot != -1) + { + int index = gdbNames.IndexOf(name.Substring(0, dot)); + if (index != -1) + { + name = vsNames[index].ToString() + name.Substring(dot); + } + } + + name = name.Replace(".private", ""); + name = name.Replace(".public", ""); + name = name.Replace(".protected", ""); + name = name.Replace("..", "."); + + dot = name.LastIndexOf(".*"); + if (dot != -1) + { + name = "*(" + name.Remove(dot) + ")"; + } + + if (parentType == "*") + { + dot = name.LastIndexOf('.'); + if (dot != -1) + { + name = name.Substring(0, dot) + "->" + name.Substring(dot + 1, name.Length - (dot + 1)); + } + } + else if (parentType == "[]") + { + dot = name.LastIndexOf('.'); + name = name.Substring(0, dot) + "[" + name.Substring(dot + 1, name.Length - (dot + 1)); + name = name + "]"; + } + gdbNames.Add(gdbName); + vsNames.Add(name); + } + + if (childProperties[1] != "") + numChildren = Convert.ToInt32(childProperties[1]); + + value = childProperties[2]; + if ((value == "") || (value.Contains("{...}")) || + ((value.Length >= 2) && (value[0] == '[') && (value[value.Length - 1] == ']'))) + valid = EvaluateExpression(name, out value, gdbName); + + type = childProperties[3]; + + VariableInfo child = new VariableInfo(name, type, value, gdbName); + + if ((valid) && (numChildren > 0 && value != "0x0")) + { + child._children = new ArrayList(); + } + if (vsNames.Contains(name)) + { + int index = vsNames.IndexOf(name); + vsNames.RemoveAt(index); + gdbNames.RemoveAt(index); + } + _children.Add(child); // If VS knows that there are children, it will inquiries again if those children data + // were not filled. + } + } + } + } +} \ No newline at end of file diff --git a/src_vs2010/DebugEngine/Properties/AssemblyInfo.cs b/src_vs2010/DebugEngine/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..9a4dc6ae --- /dev/null +++ b/src_vs2010/DebugEngine/Properties/AssemblyInfo.cs @@ -0,0 +1,51 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +using BlackBerry.NativeCore; + +[assembly: AssemblyTitle("BlackBerry DebugEngine")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("BlackBerry")] +[assembly: AssemblyProduct("BlackBerry.DebugEngine")] +[assembly: AssemblyCopyright("Copyright © BlackBerry 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7925a96c-7e19-4796-87ef-41634e94a31a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion(ConfigDefaults.VersionString)] +[assembly: AssemblyFileVersion(ConfigDefaults.VersionString)] diff --git a/src_vs2010/GDBHost/BlackBerry.GDBHost.vcxproj b/src_vs2010/GDBHost/BlackBerry.GDBHost.vcxproj new file mode 100644 index 00000000..1af1ecdc --- /dev/null +++ b/src_vs2010/GDBHost/BlackBerry.GDBHost.vcxproj @@ -0,0 +1,105 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {9A560339-44DB-413F-868C-403962C2CF01} + Win32Proj + GDBWrapper + + + + Application + true + Unicode + false + + + Application + false + true + Unicode + false + + + + + + + + + + + + + true + $(ProjectDir)$(Configuration)\ + + + false + $(ProjectDir)$(Configuration)\ + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + false + + + xcopy "$(OutDir)BlackBerry.GDBHost.exe" "$(OutputPath)" /d /y + Copying Executable to output directory. + + + + + + + + + + + + + + Create + Create + + + + + + \ No newline at end of file diff --git a/src_vs2010/GDBHost/BlackBerry.GDBHost.vcxproj.filters b/src_vs2010/GDBHost/BlackBerry.GDBHost.vcxproj.filters new file mode 100644 index 00000000..21630635 --- /dev/null +++ b/src_vs2010/GDBHost/BlackBerry.GDBHost.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/GDBWrapper/stdafx.cpp b/src_vs2010/GDBHost/stdafx.cpp similarity index 100% rename from src/GDBWrapper/stdafx.cpp rename to src_vs2010/GDBHost/stdafx.cpp diff --git a/src_vs2010/GDBHost/stdafx.h b/src_vs2010/GDBHost/stdafx.h new file mode 100644 index 00000000..263bd874 --- /dev/null +++ b/src_vs2010/GDBHost/stdafx.h @@ -0,0 +1,27 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#include diff --git a/src/GDBWrapper/targetver.h b/src_vs2010/GDBHost/targetver.h similarity index 100% rename from src/GDBWrapper/targetver.h rename to src_vs2010/GDBHost/targetver.h diff --git a/src_vs2010/NativeCore/BlackBerry.NativeCore.csproj b/src_vs2010/NativeCore/BlackBerry.NativeCore.csproj new file mode 100644 index 00000000..803237e8 --- /dev/null +++ b/src_vs2010/NativeCore/BlackBerry.NativeCore.csproj @@ -0,0 +1,521 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {36D4495B-9A92-478F-BF95-AEA13804A7BA} + Library + Properties + BlackBerry.NativeCore + BlackBerry.NativeCore + v4.0 + 512 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2010;MAKE_CONFIG_DEFAULTS_PUBLIC + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2010;MAKE_CONFIG_DEFAULTS_PUBLIC + prompt + 4 + + + + + + + + + + + + + + + + + Components\TargetConnectionEventArgs.cs + + + Components\Targets.cs + + + Components\TargetStatus.cs + + + Components\TokenProcessor.cs + + + Components\UpdateManager.cs + + + Components\UpdateManagerCompletedEventArgs.cs + + + ConfigDefaults.cs + + + Debugger\GdbProcessor.cs + + + Debugger\GdbWrapper.cs + + + Debugger\IGdbSender.cs + + + Debugger\Instruction.cs + + + Debugger\InstructionCollection.cs + + + Debugger\Model\BreakpointInfo.cs + + + Debugger\Model\IResult.cs + + + Debugger\Model\ProcessInfo.cs + + + Debugger\Request.cs + + + Debugger\RequestGroup.cs + + + Debugger\RequestsFactory.cs + + + Debugger\Requests\BreakRequest.cs + + + Debugger\Requests\CliRequest.cs + + + Debugger\Requests\MiRequest.cs + + + Debugger\Requests\ProcessListRequest.cs + + + Debugger\Response.cs + + + Debugger\ResponseParsedEventArgs.cs + + + Debugger\ResponseReceivedEventArgs.cs + + + Debugger\ResponseType.cs + + + Diagnostics\BlackBerryTraceListener.cs + + + Diagnostics\QTraceLog.cs + + + Diagnostics\TimeTracker.cs + + + Diagnostics\TraceLog.cs + + + Helpers\BitHelper.cs + + + Helpers\DeviceHelper.cs + + + Helpers\GlobalHelper.cs + + + Helpers\NameValueCollectionHelper.cs + + + Helpers\PathHelper.cs + + + Model\ApiInfo.cs + + + Model\ApiInfoArray.cs + + + Model\ApiLevelAction.cs + + + Model\ApiLevelListTypes.cs + + + Model\ApiLevelTarget.cs + + + Model\ApiLevelTask.cs + + + Model\AuthorInfo.cs + + + Model\CertificateInfo.cs + + + Model\CskTokenInfo.cs + + + Model\DebugTokenInfo.cs + + + Model\DeveloperDefinition.cs + + + Model\DeviceDebugTokenInfo.cs + + + Model\DeviceDefinition.cs + + + Model\DeviceDefinitionType.cs + + + Model\DeviceFamilyType.cs + + + Model\DeviceInfo.cs + + + Model\DeviceTheme.cs + + + Model\GdbInfo.cs + + + Model\ImportProjectInfo.cs + + + Model\NdkDefinition.cs + + + Model\NdkInfo.cs + + + Model\PermissionInfo.cs + + + Model\RuntimeDefinition.cs + + + Model\RuntimeInfo.cs + + + Model\SimulatorInfo.cs + + + Model\Size.cs + + + NativeMethods.cs + + + Properties\AssemblyInfo.cs + + + QConn\HResult.cs + + + QConn\Model\CapturedLogsEventArgs.cs + + + QConn\Model\DataReaderBigEndian.cs + + + QConn\Model\DataReaderLittleEndian.cs + + + QConn\Model\DecryptedChallenge.cs + + + QConn\Model\EncryptionChallenge.cs + + + QConn\Model\Endianess.cs + + + QConn\Model\IDataReader.cs + + + QConn\Model\SystemInfoProcess.cs + + + QConn\Model\TargetFile.cs + + + QConn\Model\TargetFileDescriptor.cs + + + QConn\Model\TargetLogEntry.cs + + + QConn\Model\TargetProcess.cs + + + QConn\Model\TargetProcessSLog2Info.cs + + + QConn\Model\TargetSystemType.cs + + + QConn\Model\Token.cs + + + QConn\Model\TransferOperation.cs + + + QConn\Model\VisitorCompletionEventArgs.cs + + + QConn\Model\VisitorEventArgs.cs + + + QConn\Model\VisitorFailureEventArgs.cs + + + QConn\Model\VisitorProgressChangedEventArgs.cs + + + QConn\QConnAuthenticationEventArgs.cs + + + QConn\QConnClient.cs + + + QConn\QConnConnection.cs + + + QConn\QConnDoor.cs + + + QConn\QConnException.cs + + + QConn\QDataSource.cs + + + QConn\Request\SecureTargetAuthenticateChallengeRequest.cs + + + QConn\Request\SecureTargetAuthenticateRequest.cs + + + QConn\Request\SecureTargetChallengeRequest.cs + + + QConn\Request\SecureTargetCloseRequest.cs + + + QConn\Request\SecureTargetDecryptedChallengeRequest.cs + + + QConn\Request\SecureTargetEncryptedRequest.cs + + + QConn\Request\SecureTargetHelloRequest.cs + + + QConn\Request\SecureTargetKeepAliveRequest.cs + + + QConn\Request\SecureTargetRequest.cs + + + QConn\Request\SecureTargetSendSshPublicKeyRequest.cs + + + QConn\Request\SecureTargetStartServicesRequest.cs + + + QConn\Response\SecureTargetAuthenticateChallengeResponse.cs + + + QConn\Response\SecureTargetEncryptedChallengeResponse.cs + + + QConn\Response\SecureTargetFeedback.cs + + + QConn\Response\SecureTargetFeedbackMismatchedVersion.cs + + + QConn\Response\SecureTargetFeedbackNoPasswordRequired.cs + + + QConn\Response\SecureTargetFeedbackOK.cs + + + QConn\Response\SecureTargetFeedbackRejected.cs + + + QConn\Response\SecureTargetResponse.cs + + + QConn\Response\SecureTargetResult.cs + + + QConn\SecureTargetConnectionException.cs + + + QConn\Services\TargetService.cs + + + QConn\Services\TargetServiceConsoleLog.cs + + + QConn\Services\TargetServiceControl.cs + + + QConn\Services\TargetServiceFile.cs + + + QConn\Services\TargetServiceLauncher.cs + + + QConn\Services\TargetServiceSysInfo.cs + + + QConn\Visitors\BaseFileServiceEnumerator.cs + + + QConn\Visitors\BaseVisitorMonitor.cs + + + QConn\Visitors\BufferVisitor.cs + + + QConn\Visitors\IFileServiceEnumerator.cs + + + QConn\Visitors\IFileServiceVisitor.cs + + + QConn\Visitors\IFileServiceVisitorMonitor.cs + + + QConn\Visitors\LocalCopyVisitor.cs + + + QConn\Visitors\LocalEnumerator.cs + + + QConn\Visitors\LoggingVisitor.cs + + + QConn\Visitors\TargetCopyVisitor.cs + + + QConn\Visitors\TargetEnumerator.cs + + + QConn\Visitors\ZipPackageVisitor.cs + + + Services\IAttachDiscoveryService.cs + + + Services\IDeviceDiscoveryService.cs + + + Tools\ApiLevelListLoadRunner.cs + + + Tools\ApiLevelUpdateLogEventArgs.cs + + + Tools\ApiLevelUpdateRunner.cs + + + Tools\ApplicationRemoveRunner.cs + + + Tools\BBToolRunner.cs + + + Tools\DebugTokenCreateRunner.cs + + + Tools\DebugTokenInfoRunner.cs + + + Tools\DebugTokenUploadRunner.cs + + + Tools\DeviceConnectRunner.cs + + + Tools\DeviceInfoRunner.cs + + + Tools\EventDispatcher.cs + + + Tools\GdbHostRunner.cs + + + Tools\GdbRunner.cs + + + Tools\IEventDispatcher.cs + + + Tools\KeyToolGenRunner.cs + + + Tools\KeyToolInfoRunner.cs + + + Tools\KeyToolRegisterRunner.cs + + + Tools\KeyToolRemoveRunner.cs + + + Tools\SshCreateKeyRunner.cs + + + Tools\ToolRunner.cs + + + Tools\ToolRunnerEventArgs.cs + + + Tools\ToolRunnerStartupEventArgs.cs + + + + + Resources\Instructions.txt + + + + + + \ No newline at end of file diff --git a/src_vs2010/Package/BlackBerry.Package.csproj b/src_vs2010/Package/BlackBerry.Package.csproj new file mode 100644 index 00000000..ef0b2147 --- /dev/null +++ b/src_vs2010/Package/BlackBerry.Package.csproj @@ -0,0 +1,1235 @@ + + + + Debug + AnyCPU + 2.0 + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D} + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + BlackBerry.Package + BlackBerry.Package + false + Key.snk + v4.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2010 + prompt + 4 + true + AnyCPU + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2010 + prompt + 4 + true + true + AnyCPU + + + + + + + + + + + + + + false + + + + True + + + + ..\..\..\..\..\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.VisualStudio.XmlEditor\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.XmlEditor.dll + + + + + + + + + + + + + + + + + + + + {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2} + 8 + 0 + 0 + primary + False + False + + + {26AD1324-4B7C-44BC-84F8-B86AED45729F} + 10 + 0 + 0 + primary + False + False + + + {1A31287A-4D7D-413E-8E32-3B374931BD89} + 8 + 0 + 0 + primary + False + False + + + {2CE2370E-D744-4936-A090-3FFFE667B0E1} + 9 + 0 + 0 + primary + False + False + + + {1CBA492E-7263-47BB-87FE-639000619B15} + 8 + 0 + 0 + primary + False + False + + + + + BlackBerryPackage.cs + + + Components\BuildPlatformsManager.cs + + + Components\ErrorManager.cs + + + Components\LogManager.cs + + + Components\ProjectFolderTree.cs + + + Diagnostics\BlackBerryPaneTraceListener.cs + + + Diagnostics\PersistentTraceListener.cs + + + Dialogs\BinaryDiscoveryForm.cs + Form + + + Dialogs\BinaryDiscoveryForm.designer.cs + BinaryDiscoveryForm.cs + + + Dialogs\CachedAuthorForm.cs + Form + + + Dialogs\CachedAuthorForm.designer.cs + CachedAuthorForm.cs + + + Dialogs\FolderForm.cs + Form + + + Dialogs\FolderForm.designer.cs + FolderForm.cs + + + Dialogs\ImportProjectForm.cs + Form + + + Dialogs\ImportProjectForm.designer.cs + ImportProjectForm.cs + + + Editors\BarDescriptorEditorControl.xaml.cs + BarDescriptorEditorControl.xaml + + + Editors\BarDescriptorEditorFactory.cs + + + Editors\BarDescriptorEditorPane.cs + + + GuidList.cs + + + Helpers\AttributeHelper.cs + + + Helpers\CertHelper.cs + + + Helpers\CommandHelper.cs + + + Helpers\DialogHelper.cs + + + Helpers\DteHelper.cs + + + Helpers\IconHelper.cs + + + Helpers\MessageBoxHelper.cs + + + Helpers\ProjectHelper.cs + + + Languages\Qml\QmlColorizer.cs + + + Languages\Qml\QmlLanguageService.cs + + + Languages\Qml\QmlWindowManager.cs + + + Model\bar-descriptor.cs + + + Model\bar-descriptor.Extensions.cs + + + Model\Integration\ComboBoxItem.cs + + + Model\Integration\DynamicMenuCommand.cs + + + Model\Integration\WebBrowserTurbo.cs + Component + + + Model\Wizards\ContextParams.cs + + + Model\Wizards\NewProjectItemParams.cs + + + Model\Wizards\NewProjectParams.cs + + + Options\ApiLevelOptionControl.cs + UserControl + + + Options\ApiLevelOptionControl.designer.cs + ApiLevelOptionControl.cs + + + Options\ApiLevelOptionPage.cs + Component + + + Dialogs\AboutForm.cs + Form + + + Dialogs\AboutForm.designer.cs + AboutForm.cs + + + Dialogs\AddLocalNdkForm.cs + Form + + + Dialogs\AddLocalNdkForm.designer.cs + AddLocalNdkForm.cs + + + Dialogs\CertificateDetailsForm.cs + Form + + + Dialogs\CertificateDetailsForm.designer.cs + CertificateDetailsForm.cs + + + Dialogs\CskRequestForm.cs + Form + + + Dialogs\CskRequestForm.designer.cs + CskRequestForm.cs + + + Dialogs\DebugTokenDeploymentForm.cs + Form + + + Dialogs\DebugTokenDeploymentForm.designer.cs + DebugTokenDeploymentForm.cs + + + Dialogs\DeviceForm.cs + Form + + + Dialogs\DeviceForm.designer.cs + DeviceForm.cs + + + Dialogs\InstallConfirmationForm.cs + Form + + + Dialogs\InstallConfirmationForm.designer.cs + InstallConfirmationForm.cs + + + Dialogs\InstallForm.cs + Form + + + Dialogs\InstallForm.designer.cs + InstallForm.cs + + + Dialogs\ListItemControl.cs + UserControl + + + Dialogs\ListItemControl.designer.cs + ListItemControl.cs + + + Dialogs\MissingNdkInstalledForm.cs + Form + + + Dialogs\MissingNdkInstalledForm.designer.cs + MissingNdkInstalledForm.cs + + + Dialogs\PasswordForm.cs + Form + + + Dialogs\PasswordForm.designer.cs + PasswordForm.cs + + + Dialogs\PinListForm.cs + Form + + + Dialogs\PinListForm.designer.cs + PinListForm.cs + + + Dialogs\RegistrationForm.cs + Form + + + Dialogs\RegistrationForm.designer.cs + RegistrationForm.cs + + + Dialogs\UpdateManagerStatusForm.cs + Form + + + Dialogs\UpdateManagerStatusForm.designer.cs + UpdateManagerStatusForm.cs + + + Options\BackupOptionControl.cs + UserControl + + + Options\BackupOptionControl.designer.cs + BackupOptionControl.cs + + + Options\BackupOptionPage.cs + Component + + + Options\GeneralOptionControl.cs + UserControl + + + Options\GeneralOptionControl.designer.cs + GeneralOptionControl.cs + + + Options\GeneralOptionPage.cs + Component + + + Options\LogsOptionControl.cs + UserControl + + + Options\LogsOptionControl.designer.cs + LogsOptionControl.cs + + + Options\LogsOptionPage.cs + Component + + + Options\SigningOptionControl.cs + UserControl + + + Options\SigningOptionControl.designer.cs + SigningOptionControl.cs + + + Options\SigningOptionPage.cs + Component + + + Options\TargetsOptionControl.cs + UserControl + + + Options\TargetsOptionControl.designer.cs + TargetsOptionControl.cs + + + Options\TargetsOptionPage.cs + Component + + + PackageCommands.cs + + + Registration\DebugEngineRegistrationAttribute.cs + + + Registration\ProvideProjects.cs + + + Registration\ProvideWizardEngineAttribute.cs + + + Registration\XmlEditorDesignerViewRegistrationAttribute.cs + + + StandardCommands.cs + + + ToolWindows\TargetNavigatorControl.xaml.cs + TargetNavigatorControl.xaml + + + ToolWindows\TargetNavigatorPane.cs + + + ViewModels\ApiLevelOptionViewModel.cs + + + ViewModels\BackupOptionViewModel.cs + + + ViewModels\BarEditorViewModel.cs + + + ViewModels\Common\BinaryToStringConverter.cs + + + ViewModels\Common\ContentTemplateSelector.cs + + + ViewModels\Common\CountToVisibilityConverter.cs + + + ViewModels\Common\NullToVisibilityConverter.cs + + + ViewModels\ImportProjectViewModel.cs + + + ViewModels\PackageViewModel.cs + + + ViewModels\SigningOptionViewModel.cs + + + ViewModels\TargetNavigatorViewModel.cs + + + ViewModels\TargetNavigator\BaseViewItem.cs + + + ViewModels\TargetNavigator\DownloadUploadProgress.cs + + + ViewModels\TargetNavigator\FileSystemViewItem.cs + + + ViewModels\TargetNavigator\FileToParentViewItem.cs + + + ViewModels\TargetNavigator\FileViewItem.cs + + + ViewModels\TargetNavigator\MessageViewItem.cs + + + ViewModels\TargetNavigator\ProcessListViewItem.cs + + + ViewModels\TargetNavigator\ProcessViewItem.cs + + + ViewModels\TargetNavigator\ProgressViewItem.cs + + + ViewModels\TargetNavigator\TargetViewItem.cs + + + ViewModels\TargetsChangedEventArgs.cs + + + ViewModels\TargetsOptionViewModel.cs + + + Wizards\BaseWizardEngine.cs + + + Wizards\PuppetMasterWizardEngine.cs + + + Dialogs\CachedAuthorForm.resx + CachedAuthorForm.cs + + + Dialogs\ImportProjectForm.resx + ImportProjectForm.cs + + + Options\BackupOptionControl.resx + BackupOptionControl.cs + + + + Resources\License.txt + true + Always + + + Resources\ReleaseNotes.txt + true + + + Resources\StartGuide.txt + true + + + Templates\VCWizards\BlackBerry\Shared\applicationui.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\applicationui.hpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\applicationui.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\applicationui.hpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\applicationuibase.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\applicationuibase.hpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\bar-descriptor.xml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\cardui.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\cardui.hpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\main.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\applicationui.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\applicationui.hpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\bar-descriptor.xml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\main-service.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\service.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\service.hpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\ListView\data.xml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\QtPlayBook\bar-descriptor.xml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\QtPlayBook\main.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\QtPlayBook\README.txt + true + + + Templates\VCWizards\BlackBerry\Shared\bar-descriptor-cascades.xml + true + + + Templates\VCWizards\BlackBerry\Shared\bar-descriptor.xml + true + + + Templates\VCWizards\BlackBerry\Shared\main-cascades.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\main-empty.c + true + + + Templates\VCWizards\BlackBerry\Shared\main-opengl1.c + true + + + Templates\VCWizards\BlackBerry\Shared\main-opengl2.c + true + + + Templates\VCWizards\BlackBerry\Shared\main-screen.c + true + + + Templates\VCWizards\BlackBerry\Shared\precompiled-cascades.h + true + + + Templates\VCWizards\BlackBerry\Shared\precompiled-empty.h + true + + + Templates\VCWizards\BlackBerry\Shared\qclass.cpp + true + + + Templates\VCWizards\BlackBerry\Shared\qclass.hpp + true + + + Templates\VCWizards\BlackBerry\Shared\qcontrol.qml + true + + + Templates\VCWizards\BlackBerry\Shared\qdialog.qml + true + + + Templates\VCWizards\BlackBerry\Shared\qpage.qml + true + + + Templates\VCWizards\BlackBerry\Shared\qpane.qml + true + + + Templates\VCWizards\BlackBerry\Shared\qsheet.qml + true + + + Templates\ProjectItems\BlackBerry\Cascades\qcontrol.vsz + true + + + Templates\ProjectItems\BlackBerry\Cascades\qdialog.vsz + true + + + Templates\ProjectItems\BlackBerry\Cascades\qpage.vsz + true + + + Templates\ProjectItems\BlackBerry\Cascades\qpane.vsz + true + + + Templates\ProjectItems\BlackBerry\Cascades\qsheet.vsz + true + + + Templates\Projects\BlackBerry\Cascades\items.vsdir + true + + + Templates\Projects\BlackBerry\cascadesproj.vsz + true + + + Templates\Projects\BlackBerry\libsharedproj.vsz + true + + + Templates\Projects\BlackBerry\libstaticproj.vsz + true + + + Templates\Projects\BlackBerry\openglproj1.vsz + true + + + Templates\Projects\BlackBerry\openglproj2.vsz + true + + + Templates\Projects\BlackBerry\screenproj.vsz + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\main-helloworld.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Translations\makefile-cascades + true + + + Templates\VCWizards\BlackBerry\Shared\Translations\qmake-default.pro + true + + + Templates\VCWizards\BlackBerry\Shared\makefile-cascades + true + + + Templates\VCWizards\BlackBerry\Shared\qmake-config.pri + true + + + Templates\VCWizards\BlackBerry\Shared\qmake-default.pro + true + + + Templates\Projects\BlackBerry\Cascades\cascadesproj_card.vsz + true + + + Templates\Projects\BlackBerry\Cascades\cascadesproj_listview.vsz + true + + + Templates\Projects\BlackBerry\Cascades\cascadesproj_navigationpane.vsz + true + + + Templates\Projects\BlackBerry\Cascades\cascadesproj_tabs.vsz + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\main-tabs.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\card.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\main.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Card\qmake.pro + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\ListView\ItemPage.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\ListView\main.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\ListView\qmake.pro + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\NavigationPane\DetailsPage.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\NavigationPane\main.qml + true + + + Templates\Projects\BlackBerry\Cascades\cascadesproj_headless.vsz + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\main.qml + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\qmake-service.pro + true + + + Templates\VCWizards\BlackBerry\Shared\Assets\Headless\qmake.pro + true + + + Templates\ProjectItems\BlackBerry\bbutil.vsz + true + + + Templates\VCWizards\BlackBerry\Shared\qtab.qml + true + + + Templates\ProjectItems\BlackBerry\Cascades\qtab.vsz + true + + + Templates\ProjectItems\BlackBerry\makefile.vsz + true + + + Templates\VCWizards\BlackBerry\Shared\makefile-empty + true + + + Templates\Projects\BlackBerry\Qt\items.vsdir + true + + + Templates\Projects\BlackBerry\Qt\qtproj_playbook.vsz + true + + + + + + Templates\VCWizards\BlackBerry\Shared\Utils\bbutil.c + true + + + Templates\VCWizards\BlackBerry\Shared\Utils\bbutil.h + true + + + true + + + true + + + true + + + true + + + true + + + Menus.ctmenu + Designer + + + + Dialogs\BinaryDiscoveryForm.resx + BinaryDiscoveryForm.cs + + + Dialogs\FolderForm.resx + FolderForm.cs + + + Options\ApiLevelOptionControl.resx + ApiLevelOptionControl.cs + + + Dialogs\AboutForm.resx + AboutForm.cs + + + Dialogs\AddLocalNdkForm.resx + AddLocalNdkForm.cs + + + Dialogs\CertificateDetailsForm.resx + CertificateDetailsForm.cs + + + Dialogs\CskRequestForm.resx + CskRequestForm.cs + + + Dialogs\DebugTokenDeploymentForm.resx + DebugTokenDeploymentForm.cs + + + Dialogs\DeviceForm.resx + DeviceForm.cs + + + Dialogs\InstallConfirmationForm.resx + InstallConfirmationForm.cs + + + Dialogs\InstallForm.resx + InstallForm.cs + + + Dialogs\ListItemControl.resx + ListItemControl.cs + + + Dialogs\MissingNdkInstalledForm.resx + MissingNdkInstalledForm.cs + + + Dialogs\PasswordForm.resx + PasswordForm.cs + + + Dialogs\PinListForm.resx + PinListForm.cs + + + Dialogs\RegistrationForm.resx + RegistrationForm.cs + + + Dialogs\UpdateManagerStatusForm.resx + UpdateManagerStatusForm.cs + + + Options\GeneralOptionControl.resx + GeneralOptionControl.cs + + + Options\LogsOptionControl.resx + LogsOptionControl.cs + + + Options\SigningOptionControl.resx + SigningOptionControl.cs + + + Options\TargetsOptionControl.resx + TargetsOptionControl.cs + + + Resources\Logo.png + + + Resources\Package.Bitmaps.vsct + + + Resources\Package.Menu.vsct + + + Resources\Navigator\folder_closed.png + + + Resources\Navigator\folder_opened.png + + + Resources\Navigator\process.png + + + Resources\Navigator\target.png + + + Resources\Navigator\target_disconnected.png + + + Resources\Navigator\thread.png + + + Resources\Permissions\BlackBerryMessager.bmp + + + Resources\Permissions\Calendar.bmp + + + Resources\Permissions\Camera.bmp + + + Resources\Permissions\CaptureScreen.bmp + + + Resources\Permissions\Contacts.bmp + + + Resources\Permissions\DeviceIdentifyingInfo.bmp + + + Resources\Permissions\EmailPINMessages.bmp + + + Resources\Permissions\Gamepad.bmp + + + Resources\Permissions\GPSLocation.bmp + + + Resources\Permissions\Internet.bmp + + + Resources\Permissions\Location.bmp + + + Resources\Permissions\Mircrophone.bmp + + + Resources\Permissions\MyContactInfo.bmp + + + Resources\Permissions\Notebooks.bmp + + + Resources\Permissions\Phone.bmp + + + Resources\Permissions\PhoneControl.bmp + + + Resources\Permissions\PostNotifications.bmp + + + Resources\Permissions\Push.bmp + + + Resources\Permissions\RunBackgrounded.bmp + + + Resources\Permissions\SharedFiles.bmp + + + Resources\Permissions\TextMessages.bmp + + + Templates\Projects\BlackBerry.vsdir + true + + + Templates\Projects\BlackBerry\emptyproj.vsz + true + + + Templates\Projects\BlackBerry\items.vsdir + true + + + Templates\Projects\BlackBerry\OpenGL\items.vsdir + true + + + Templates\ProjectItems\BlackBerry.vsdir + true + + + Templates\ProjectItems\BlackBerry\bar-descriptor.vsz + true + + + Templates\ProjectItems\BlackBerry\items.vsdir + true + + + Templates\ProjectItems\BlackBerry\Cascades\items.vsdir + true + + + Templates\ProjectItems\BlackBerry\Cascades\qclass.vsz + true + + + Always + true + + + True + True + Strings.resx + + + + + + + Resources\Template.Strings.resx + + + ResXFileCodeGenerator + Strings.Designer.cs + Designer + + + true + Package + Designer + + + + + Designer + Always + + + + + + + + + + + + + + + + Editors\BarDescriptorEditorControl.xaml + MSBuild:Compile + Designer + + + ToolWindows\TargetNavigatorControl.xaml + MSBuild:Compile + Designer + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {59A7B188-E307-4495-A3AF-4ED76B086A87} + BlackBerry.DebugEngine + + + {9A560339-44DB-413F-868C-403962C2CF01} + BlackBerry.GDBHost + false + BuiltProjectOutputGroup%3bBuiltProjectOutputGroupDependencies%3bGetCopyToOutputDirectoryItems%3bSatelliteDllsProjectOutputGroup%3b + DebugSymbolsProjectOutputGroup%3b + + + {36D4495B-9A92-478F-BF95-AEA13804A7BA} + BlackBerry.NativeCore + + + + + true + + + + + \ No newline at end of file diff --git a/src_vs2010/Package/GlobalSuppressions.cs b/src_vs2010/Package/GlobalSuppressions.cs new file mode 100644 index 00000000..d73697ea --- /dev/null +++ b/src_vs2010/Package/GlobalSuppressions.cs @@ -0,0 +1,25 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. Project-level +// suppressions either have no target or are given a specific target +// and scoped to a namespace, type, member, etc. +// +// To add a suppression to this file, right-click the message in the +// Error List, point to "Suppress Message(s)", and click "In Project +// Suppression File". You do not need to add suppressions to this +// file manually. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")] diff --git a/src/VSNDK.Package/Key.snk b/src_vs2010/Package/Key.snk similarity index 100% rename from src/VSNDK.Package/Key.snk rename to src_vs2010/Package/Key.snk diff --git a/src_vs2010/Package/Properties/AssemblyInfo.cs b/src_vs2010/Package/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..a10364c6 --- /dev/null +++ b/src_vs2010/Package/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using BlackBerry.NativeCore; +using BlackBerry.Package; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("BlackBerry Native SDK Plugin for Visual Studio")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("BlackBerry")] +[assembly: AssemblyProduct("BlackBerry.Package")] +[assembly: AssemblyCopyright("Copyright © BlackBerry 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: NeutralResourcesLanguage("en-US")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion(ConfigDefaults.VersionString)] +[assembly: AssemblyFileVersion(ConfigDefaults.VersionString)] + +#if DEBUG +[assembly: InternalsVisibleTo("IntegrationTests")] +[assembly: InternalsVisibleTo("UnitTests")] +#endif diff --git a/src_vs2010/Package/Resources/File.ico b/src_vs2010/Package/Resources/File.ico new file mode 100644 index 00000000..375d2cbc Binary files /dev/null and b/src_vs2010/Package/Resources/File.ico differ diff --git a/src/VSNDK.Package/Resources/Images_24bit.bmp b/src_vs2010/Package/Resources/Images_24bit.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Images_24bit.bmp rename to src_vs2010/Package/Resources/Images_24bit.bmp diff --git a/src/VSNDK.Package/Resources/Images_32bit.bmp b/src_vs2010/Package/Resources/Images_32bit.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Images_32bit.bmp rename to src_vs2010/Package/Resources/Images_32bit.bmp diff --git a/src_vs2010/Package/Resources/Package.ico b/src_vs2010/Package/Resources/Package.ico new file mode 100644 index 00000000..c5dd0a3f Binary files /dev/null and b/src_vs2010/Package/Resources/Package.ico differ diff --git a/src_vs2010/Package/Resources/Package.resx b/src_vs2010/Package/Resources/Package.resx new file mode 100644 index 00000000..d83477a7 --- /dev/null +++ b/src_vs2010/Package/Resources/Package.resx @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + BlackBerry Native SDK Plugin for Visual Studio + + + Package providing Native SDK support inside Visual Studio for PlayBook and BlackBerry 10 devices + + + + Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + [Read Only] + + + File has been changed outside the environment. Reload the new file? + + + BarDescriptor Editor + Name of the editor to show for the Keybindings + + + BarDescriptor Editor Files + + + BarDescriptor Editor + + + bar-descriptor + + + BarDescriptor Editor File (xml) + + + Images_24bit.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + File.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + BlackBerry + Name of the section in Tools -> Options + + + General + + + Logs + + + API Levels + + + Targets + + + Signing + + + Backup + + \ No newline at end of file diff --git a/src_vs2010/Package/Resources/Package.vsct b/src_vs2010/Package/Resources/Package.vsct new file mode 100644 index 00000000..0e43b0e0 --- /dev/null +++ b/src_vs2010/Package/Resources/Package.vsct @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + B&lackBerry + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2010/Package/Resources/Strings.Designer.cs b/src_vs2010/Package/Resources/Strings.Designer.cs new file mode 100644 index 00000000..60571e6c --- /dev/null +++ b/src_vs2010/Package/Resources/Strings.Designer.cs @@ -0,0 +1,225 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18444 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace BlackBerry.Package.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BlackBerry.Package.Resources.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to You have to specify the Author name. + /// + internal static string AuthorMissing { + get { + return ResourceManager.GetString("AuthorMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is important that you back up your signing keys. If you should lose your signing keys, or forget your password, you will be required to re-register with BlackBerry. After re-registering, new versions of your applications will appear as new applications, and will not have access to shared data from previous versions. Exporting your signing keys will also allow you to import them to multiple computers allow you to sign from any of them.. + /// + internal static string BackupRestoreInfo { + get { + return ResourceManager.GetString("BackupRestoreInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Can not create tool window.. + /// + internal static string CanNotCreateWindow { + get { + return ResourceManager.GetString("CanNotCreateWindow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have to specify a confirm password. + /// + internal static string CSJConfirmPasswordMissing { + get { + return ResourceManager.GetString("CSJConfirmPasswordMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have to specify a BlackBerry ID token password and it must be at least 6 characters long. + /// + internal static string CSJPasswordMissing { + get { + return ResourceManager.GetString("CSJPasswordMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have to provide the Pin. + /// + internal static string CSJPinMissing { + get { + return ResourceManager.GetString("CSJPinMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to bar-descriptor Designer. + /// + internal static string ErrorMessageBoxTitle { + get { + return ResourceManager.GetString("ErrorMessageBoxTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Errors. + /// + internal static string Errors { + get { + return ResourceManager.GetString("Errors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Info. + /// + internal static string Info { + get { + return ResourceManager.GetString("Info", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The vstemplate file you are attempting to load is missing TemplateData. + /// + internal static string InvalidVsTemplateData { + get { + return ResourceManager.GetString("InvalidVsTemplateData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Check if the Natvie SDK is installed.. + /// + internal static string NativSDKNotInstalled { + get { + return ResourceManager.GetString("NativSDKNotInstalled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Passwords do not match.. + /// + internal static string PasswordNotmatch { + get { + return ResourceManager.GetString("PasswordNotmatch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to RDK CSJ file is required!. + /// + internal static string RDKCSJFileMissing { + get { + return ResourceManager.GetString("RDKCSJFileMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reformat. + /// + internal static string ReformatBuffer { + get { + return ResourceManager.GetString("ReformatBuffer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the "Author Name" and the password that was used to create the BlackBerry ID token.. + /// + internal static string RegistrationInfo { + get { + return ResourceManager.GetString("RegistrationInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Synchronize XML file with view. + /// + internal static string SynchronizeBuffer { + get { + return ResourceManager.GetString("SynchronizeBuffer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Signing. + /// + internal static string ToolWindowTitle { + get { + return ResourceManager.GetString("ToolWindowTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you want to unregister and remove the BlackBerry ID Token file?. + /// + internal static string UnRegistrationInfo { + get { + return ResourceManager.GetString("UnRegistrationInfo", resourceCulture); + } + } + } +} diff --git a/src_vs2010/Package/Resources/Strings.resx b/src_vs2010/Package/Resources/Strings.resx new file mode 100644 index 00000000..e0800492 --- /dev/null +++ b/src_vs2010/Package/Resources/Strings.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Can not create tool window. + + + You have to specify a confirm password + + + You have to specify a BlackBerry ID token password and it must be at least 6 characters long + + + You have to provide the Pin + + + You have to specify the Author name + + + Errors + + + Info + + + Check if the Natvie SDK is installed. + + + The Passwords do not match. + + + RDK CSJ file is required! + + + Signing + + + It is important that you back up your signing keys. If you should lose your signing keys, or forget your password, you will be required to re-register with BlackBerry. After re-registering, new versions of your applications will appear as new applications, and will not have access to shared data from previous versions. Exporting your signing keys will also allow you to import them to multiple computers allow you to sign from any of them. + + + Enter the "Author Name" and the password that was used to create the BlackBerry ID token. + + + Do you want to unregister and remove the BlackBerry ID Token file? + + + bar-descriptor Designer + + + The vstemplate file you are attempting to load is missing TemplateData + + + Reformat + + + Synchronize XML file with view + + \ No newline at end of file diff --git a/src_vs2010/Package/Resources/Template.Icons.resx b/src_vs2010/Package/Resources/Template.Icons.resx new file mode 100644 index 00000000..8fcbfb78 --- /dev/null +++ b/src_vs2010/Package/Resources/Template.Icons.resx @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + TemplateIcons\EmptyProj.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + templateicons\cascadesproj.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + templateicons\newitem.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + templateicons\newqitem.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/src_vs2010/Package/Resources/TemplateIcons/CascadesProj.ico b/src_vs2010/Package/Resources/TemplateIcons/CascadesProj.ico new file mode 100644 index 00000000..477e4523 Binary files /dev/null and b/src_vs2010/Package/Resources/TemplateIcons/CascadesProj.ico differ diff --git a/src_vs2010/Package/Resources/TemplateIcons/EmptyProj.ico b/src_vs2010/Package/Resources/TemplateIcons/EmptyProj.ico new file mode 100644 index 00000000..c273dab6 Binary files /dev/null and b/src_vs2010/Package/Resources/TemplateIcons/EmptyProj.ico differ diff --git a/src_vs2010/Package/Resources/TemplateIcons/NewItem.ico b/src_vs2010/Package/Resources/TemplateIcons/NewItem.ico new file mode 100644 index 00000000..f6b06c36 Binary files /dev/null and b/src_vs2010/Package/Resources/TemplateIcons/NewItem.ico differ diff --git a/src_vs2010/Package/Resources/TemplateIcons/NewQItem.ico b/src_vs2010/Package/Resources/TemplateIcons/NewQItem.ico new file mode 100644 index 00000000..7f2e362e Binary files /dev/null and b/src_vs2010/Package/Resources/TemplateIcons/NewQItem.ico differ diff --git a/src/VSNDK.Package/Resources/info.png b/src_vs2010/Package/Resources/info.png similarity index 100% rename from src/VSNDK.Package/Resources/info.png rename to src_vs2010/Package/Resources/info.png diff --git a/src_vs2010/Package/Templates/VCWizards/BlackBerry/cascades-default.vcxproj b/src_vs2010/Package/Templates/VCWizards/BlackBerry/cascades-default.vcxproj new file mode 100644 index 00000000..db3c7afc --- /dev/null +++ b/src_vs2010/Package/Templates/VCWizards/BlackBerry/cascades-default.vcxproj @@ -0,0 +1,54 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + Cascades + armle-v7 + Device-Debug + + + qcc + Cascades + armle-v7 + Device-Release + + + + + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + diff --git a/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-default.vcxproj b/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-default.vcxproj new file mode 100644 index 00000000..9c0dffbf --- /dev/null +++ b/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-default.vcxproj @@ -0,0 +1,53 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + + + qcc + armle-v7 + + + + + + + + + + $(TargetCPU)-$(Configuration)\ + + _DEBUG;%(PreprocessorDefinitions) + + + + $(TargetCPU)-$(Configuration)\ + + + + + + + + + + + diff --git a/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-libshared-default.vcxproj b/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-libshared-default.vcxproj new file mode 100644 index 00000000..05247cd5 --- /dev/null +++ b/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-libshared-default.vcxproj @@ -0,0 +1,55 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + DynamicLibrary + + + qcc + armle-v7 + DynamicLibrary + + + + + + + + + + $(TargetCPU)-$(Configuration)\ + + _DEBUG;%(PreprocessorDefinitions) + + + + $(TargetCPU)-$(Configuration)\ + + + + + + + + + + + diff --git a/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-libstatic-default.vcxproj b/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-libstatic-default.vcxproj new file mode 100644 index 00000000..dde9f09c --- /dev/null +++ b/src_vs2010/Package/Templates/VCWizards/BlackBerry/native-libstatic-default.vcxproj @@ -0,0 +1,55 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + StaticLibrary + + + qcc + armle-v7 + StaticLibrary + + + + + + + + + + $(TargetCPU)-$(Configuration)\ + + _DEBUG;%(PreprocessorDefinitions) + + + + $(TargetCPU)-$(Configuration)\ + + + + + + + + + + + diff --git a/src_vs2010/Package/Templates/VCWizards/BlackBerry/opengl-default.vcxproj b/src_vs2010/Package/Templates/VCWizards/BlackBerry/opengl-default.vcxproj new file mode 100644 index 00000000..9c0dffbf --- /dev/null +++ b/src_vs2010/Package/Templates/VCWizards/BlackBerry/opengl-default.vcxproj @@ -0,0 +1,53 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + + + qcc + armle-v7 + + + + + + + + + + $(TargetCPU)-$(Configuration)\ + + _DEBUG;%(PreprocessorDefinitions) + + + + $(TargetCPU)-$(Configuration)\ + + + + + + + + + + + diff --git a/src/VSNDK.Package/Templates/VCWizards/BlackBerry/BarDescriptor/Templates/1033/bar-descriptor.cs b/src_vs2010/Package/Templates/bar-descriptor.cs similarity index 100% rename from src/VSNDK.Package/Templates/VCWizards/BlackBerry/BarDescriptor/Templates/1033/bar-descriptor.cs rename to src_vs2010/Package/Templates/bar-descriptor.cs diff --git a/src_vs2010/Package/source.extension.vsixmanifest b/src_vs2010/Package/source.extension.vsixmanifest new file mode 100644 index 00000000..a02e1bab --- /dev/null +++ b/src_vs2010/Package/source.extension.vsixmanifest @@ -0,0 +1,31 @@ + + + + BlackBerry Native Plugin for Visual Studio 2010 + CodeTitans + 3.0.0 + Package providing Native SDK support inside Visual Studio for BlackBerry 10 devices + 1033 + http://github.com/phofman/vs-plugin/wiki + Resources/License.txt + http://github.com/phofman/vs-plugin/wiki + Resources/TemplateIcons/EmptyProj.ico + false + + + Ultimate + Premium + Pro + + + + + + + Visual Studio MPF + + + + |%CurrentProject%;PkgdefProjectOutputGroup| + + diff --git a/src_vs2010/UnitTests/UnitTests.csproj b/src_vs2010/UnitTests/UnitTests.csproj new file mode 100644 index 00000000..ae642f2a --- /dev/null +++ b/src_vs2010/UnitTests/UnitTests.csproj @@ -0,0 +1,117 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D} + Library + Properties + UnitTests + UnitTests + v4.0 + 512 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2010 + prompt + 4 + AnyCPU + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2010 + prompt + 4 + AnyCPU + + + + + ..\..\ext\NUnit\nunit.framework.dll + + + + + + + + + + + + + + + CollectionHelperTests.cs + + + DebuggerProcessorTests.cs + + + DebuggerTests.cs + + + Defaults.cs + + + DiagnosticTests.cs + + + ImportProjectTests.cs + + + MakeAllAndFormatOutputMessagesTestClass.cs + + + ParserTests.cs + + + ProjectHelperTests.cs + + + QConnTests.cs + + + ResponseParsingTests.cs + + + TokenProcessorTests.cs + + + ToolRunnerTests.cs + + + Properties\AssemblyInfo.cs + + + + + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C} + BlackBerry.BuildTasks + + + {36D4495B-9A92-478F-BF95-AEA13804A7BA} + BlackBerry.NativeCore + + + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D} + BlackBerry.Package + + + + + \ No newline at end of file diff --git a/src_vs2012/BlackBerry.NativePlugin.sln b/src_vs2012/BlackBerry.NativePlugin.sln new file mode 100644 index 00000000..00e7a1aa --- /dev/null +++ b/src_vs2012/BlackBerry.NativePlugin.sln @@ -0,0 +1,90 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.BuildTasks", "BuildTasks\BlackBerry.BuildTasks.csproj", "{328CAD98-F4E5-444A-B5DF-AD102C67BA3C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.Package", "Package\BlackBerry.Package.csproj", "{3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.DebugEngine", "DebugEngine\BlackBerry.DebugEngine.csproj", "{59A7B188-E307-4495-A3AF-4ED76B086A87}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{EA581F35-1EE6-4C7B-89FF-C3C7D886869D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlackBerry.NativeCore", "NativeCore\BlackBerry.NativeCore.csproj", "{FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackBerry.GDBHost", "GDBHost\BlackBerry.GDBHost.vcxproj", "{9A560339-44DB-413F-868C-403962C2CF01}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Debug|Win32.ActiveCfg = Debug|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Any CPU.Build.0 = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C}.Release|Win32.ActiveCfg = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Any CPU.Build.0 = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D}.Release|Win32.ActiveCfg = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Debug|Win32.ActiveCfg = Debug|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Any CPU.Build.0 = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {59A7B188-E307-4495-A3AF-4ED76B086A87}.Release|Win32.ActiveCfg = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Any CPU.Build.0 = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {EA581F35-1EE6-4C7B-89FF-C3C7D886869D}.Release|Win32.ActiveCfg = Release|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Debug|Win32.ActiveCfg = Debug|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Release|Any CPU.Build.0 = Release|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F}.Release|Win32.ActiveCfg = Release|Any CPU + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Win32.ActiveCfg = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Debug|Win32.Build.0 = Debug|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Any CPU.ActiveCfg = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Mixed Platforms.Build.0 = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Win32.ActiveCfg = Release|Win32 + {9A560339-44DB-413F-868C-403962C2CF01}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src_vs2012/BuildTasks/AsyncExec.cs b/src_vs2012/BuildTasks/AsyncExec.cs new file mode 100644 index 00000000..c47ba1b2 --- /dev/null +++ b/src_vs2012/BuildTasks/AsyncExec.cs @@ -0,0 +1,100 @@ +//* Copyright 2010-2011 BlackBerry Limited. +//* +//* 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. + +using System.Diagnostics; +using System.IO; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Helpers; +using Microsoft.Build.Tasks; + +namespace BlackBerry.BuildTasks +{ + // This task overrides Exec in order to run commands such as blackberry-connect asynchronously. + public sealed class AsyncExec : Exec + { + private int _processId; + + /// + /// Execute given command asynchronously. + /// + /// Path of executable to be run. + /// Response file commands + /// Command Line Arguments + protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) + { + string comm = "/Q /C " + Command + " -password " + GlobalHelper.Decrypt(Password); + + Process process = new Process(); + process.StartInfo = GetProcessStartInfo(pathToTool, comm); + process.Start(); + _processId = process.Id; + return 0; + } + + /// + /// Helper function to create the ProcessStartInfo object for the running process. + /// + /// Path of executable to be run. + /// Command Line Arguments + private ProcessStartInfo GetProcessStartInfo(string executable, string arguments) + { + if (arguments.Length > 0x7d00) + { + Log.LogWarningWithCodeFromResources("ToolTask.CommandTooLong", new object[] { GetType().Name }); + } + + var startInfo = new ProcessStartInfo(executable, arguments); + startInfo.WindowStyle = ProcessWindowStyle.Hidden; + startInfo.CreateNoWindow = true; + startInfo.UseShellExecute = false; + + string workingDirectory = GetWorkingDirectory(); + if (workingDirectory != null) + { + startInfo.WorkingDirectory = workingDirectory; + } + + var env = startInfo.EnvironmentVariables; + env["PATH"] = string.Concat(Path.Combine(ConfigDefaults.JavaHome, "bin"), ";", env["PATH"]); + + if (EnvironmentVariables != null) + { + foreach (var item in EnvironmentVariables) + { + int separatorIndex = item.IndexOf('='); + if (separatorIndex >= 0) + { + var name = item.Substring(0, separatorIndex).Trim(); + var value = item.Substring(separatorIndex + 1).Trim(); + + if (!string.IsNullOrEmpty(name)) + { + env[name] = value; + } + } + } + } + return startInfo; + } + + /// + /// Getter/Setter for Password Property + /// + public string Password + { + set; + get; + } + } +} diff --git a/src_vs2012/BuildTasks/BBDeploy.cs b/src_vs2012/BuildTasks/BBDeploy.cs new file mode 100644 index 00000000..0afb727a --- /dev/null +++ b/src_vs2012/BuildTasks/BBDeploy.cs @@ -0,0 +1,571 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.IO; +using BlackBerry.BuildTasks.Properties; +using Microsoft.Build.CPPTasks; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks +{ + public sealed class BBDeploy : BBTask + { + #region Member Variable Declaration + + private const string RunInfoFileName = "vsndk-runinfo.flag"; + private const string LogInfo_Lanuching = "Info: Launching "; + private const string LogInfo_ProcessID = "result::"; + private const string LogInfo_ProcessIDRunning = "result::running,"; + + private const string GET_FILE = "GetFile"; + private const string GET_FILE_SAVE_AS = "GetFileSaveAs"; + private const string PUT_FILE = "PutFile"; + private const string PUT_FILE_SAVE_AS = "PutFileSaveAs"; + private const string DEVICE = "Device"; + private const string PASSWORD = "Password"; + private const string PACKAGE_ID = "PackageId"; + private const string PACKAGE_NAME = "PackageName"; + private const string LAUNCH_APP = "LaunchApp"; + private const string INSTALL_APP = "InstallApp"; + private const string LIST_INSTALLED_APPS = "ListInstalledApps"; + private const string DEBUG_NATIVE = "DebugNative"; + private const string PACKAGE = "Package"; + + private string _localManifest; + private string _flagFile; + + private StreamWriter _localLogWriter; + + private string _packageName; // actual_dname of installed package + private uint _processID; // ID of the launched process + + #endregion + + /// + /// BBDeploy default constructor + /// + public BBDeploy() + : base(Resources.ResourceManager) + { + DefineSwitchOrder(INSTALL_APP, LAUNCH_APP, LIST_INSTALLED_APPS, DEBUG_NATIVE, DEVICE, PASSWORD, PACKAGE, PACKAGE_ID, PACKAGE_NAME, GET_FILE, GET_FILE_SAVE_AS, PUT_FILE, PUT_FILE_SAVE_AS); + } + + #region Overrides + + /// + /// Helper function to return Response File Switch + /// + /// Path to response file. + /// Return response file switch + protected override string GetResponseFileSwitch(string responseFilePath) + { + return string.Empty; + } + + /// + /// Helper function to generte the command line argument string. + /// + /// command line argument string + protected override string GenerateCommandLineCommands() + { + return GenerateResponseFileCommands(); + } + + /// + /// Creates a temporary response (.rsp) file and runs the executable file. + /// + /// + /// The returned exit code of the executable file. If the task logged errors, but the executable returned an exit code of 0, this method returns -1. + /// + /// The path to the executable file.The command line arguments to place in the .rsp file.The command line arguments to pass directly to the executable file. + protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) + { + if (ListInstalledApps) + { + _localLogWriter = File.CreateText("installedApps.txt"); + _localLogWriter.WriteLine("Info: Generating list of applications from the device ({0})", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + } + + // delete the run-info file: + if (File.Exists(RunInfoFileName)) + { + File.Delete(RunInfoFileName); + } + + _packageName = null; + _processID = 0; + + var result = base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); + + if (_localLogWriter != null) + { + _localLogWriter.Dispose(); + _localLogWriter = null; + } + + // create run-info file, if proper info was extracted from logs: + if (!string.IsNullOrEmpty(_packageName) && _processID != 0) + { + File.WriteAllText(RunInfoFileName, string.Concat("dname=", _packageName, Environment.NewLine, "pid=", _processID, Environment.NewLine)); + } + + return result; + } + + /// + /// Parses a single line of text to identify any errors or warnings in canonical format. + /// + /// A single line of text for the method to parse.A value of that indicates the importance level with which to log the message. + protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) + { + // dump all printouts of this tool into dedicated logger: + if (_localLogWriter != null) + { + _localLogWriter.WriteLine(singleLine); + LogToolError(singleLine); + return; + } + + // preprocess the 'install' part returned by the deployment tool + // (since we install whole .bar file or only selected files, when optimized deploy is on, + // we can't trust the 'BAR build' part of it): + if (string.IsNullOrEmpty(_packageName) && singleLine.StartsWith(LogInfo_Lanuching)) + { + int dots = CountAtEnd(singleLine, '.'); + _packageName = singleLine.Substring(LogInfo_Lanuching.Length, singleLine.Length - LogInfo_Lanuching.Length - dots); + } + + // expect PID, after the package name: + if (!string.IsNullOrEmpty(_packageName) && _processID == 0 && singleLine.StartsWith(LogInfo_ProcessID)) + { + uint.TryParse(singleLine.Substring(LogInfo_ProcessID.Length), out _processID); + } + if (!string.IsNullOrEmpty(_packageName) && _processID == 0 && singleLine.StartsWith(LogInfo_ProcessIDRunning)) + { + uint.TryParse(singleLine.Substring(LogInfo_ProcessIDRunning.Length), out _processID); + } + + base.LogEventsFromTextOutput(singleLine, messageImportance); + } + + /// + /// Counts occurrences of specified char at the end given text. + /// + private static int CountAtEnd(string text, char c) + { + if (string.IsNullOrEmpty(text)) + return 0; + + int i = text.Length - 1; + int result = 0; + + while (i > 0 && text[i] == c) + { + result++; + i--; + } + + return result; + } + + /// + /// Getter for the CommandTLogName property + /// + protected override string CommandTLogName + { + get { return "BBDeploy.command.1.tlog"; } + } + + /// + /// Getter for the ReadTLogNames property + /// + protected override string[] ReadTLogNames + { + get { return new[] { "BBDeploy.read.1.tlog", "BBDeploy.*.read.1.tlog" }; } + } + + /// + /// Getter for the WriteTLogNames property + /// + protected override string[] WriteTLogNames + { + get { return new[] { "BBDeploy.write.1.tlog", "BBDeploy.*.write.1.tlog" }; } + } + + /// + /// Getter for the TrackedInputFiles property + /// + protected override ITaskItem[] TrackedInputFiles + { + get + { + // I don't know what this method does but we need to return something other than 'null' or the task doesn't run, + // and adding something like "localManifest.mf" to the list of items causes other problems. + ITaskItem[] items = new ITaskItem[1]; + return items; + } + } + + /// + /// Getter for the ToolName property + /// + protected override string ToolName + { + get { return ToolExe; } + } + + /// + /// Returns the full path to the tool. + /// + protected override string GenerateFullPathToTool() + { + return ToolName; + } + + #endregion + + #region Properties + + /// + /// Getter/Setter for the GetFile property + /// Retrieve specified file from default application directory + /// + public string GetFile + { + get { return GetSwitchAsString(GET_FILE); } + set + { + // Value passed in is the file to get, relative to our app's directory. + // We determine the app's directory from the PackageName and PackageId. + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = GET_FILE, + DisplayName = "GetFile", + Description = "Get the given file from the application's directory.", + SwitchValue = "-getFile ", + Value = string.Concat("../../../../apps/", PackageName, ".", PackageId, "/", value) + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the GetFileSaveAs property + /// Retrieve specified file from location. + /// + public string GetFileSaveAs + { + get { return GetSwitchAsString(GET_FILE_SAVE_AS); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = GET_FILE_SAVE_AS, + DisplayName = "GetFileSaveAs", + Description = "Save a file retrieved using GetFile to the given location.", + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the PutFile property + /// Save given file to default application directory. + /// + public string PutFile + { + get { return GetSwitchAsString(PUT_FILE); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PUT_FILE, + DisplayName = "PutFile", + Description = "Put the given file into the application's directory.", + SwitchValue = "-putFile ", + Value = value + //Value = value.Replace(".exe", ""); + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the PutFileSaveAs property + /// Save given file to specified location + /// + public string PutFileSaveAs + { + get { return GetSwitchAsString(PUT_FILE_SAVE_AS); } + set + { + // We determine the app's directory from the PackageName and PackageId. + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PUT_FILE_SAVE_AS, + DisplayName = "PutFileSaveAs", + Description = "Save a file retrieved using PutFile to the given location.", + Value = string.Concat("../../../../apps/", PackageName, ".", PackageId + "/", value) + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the InstallApp property - Switch to cause deploy to install a given application + /// + public bool InstallApp + { + get { return GetSwitchAsBool(INSTALL_APP); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + Name = INSTALL_APP, + DisplayName = "Install App", + Description = "The -installApp option installs an app from a given package.", + SwitchValue = "-installApp", + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the LaunchApp Property - Switch to launch given application. + /// + public bool LaunchApp + { + get { return GetSwitchAsBool(LAUNCH_APP); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + Name = LAUNCH_APP, + DisplayName = "Launch App", + Description = "The -launchApp option allows an app to be launched with or without being installed.", + SwitchValue = "-launchApp ", + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for ListInstalledApps Property. + /// Switch for command to retrieve the list of installed apps. + /// + public bool ListInstalledApps + { + get { return GetSwitchAsBool(LIST_INSTALLED_APPS); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + Name = LIST_INSTALLED_APPS, + DisplayName = "List Installed Apps", + Description = "The -listInstalledApps option does just that.", + SwitchValue = "-listInstalledApps ", + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Setter for FlagFile property + /// + public string FlagFile + { + set + { + _flagFile = value; + } + } + + /// + /// Getter/Setter for DebugNative property + /// Switch to cause task to install application in debug configuration. + /// + public bool DebugNative + { + get { return GetSwitchAsBool(DEBUG_NATIVE); } + + set + { + if (File.Exists(_flagFile)) + { + value = true; + } + + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + Name = DEBUG_NATIVE, + DisplayName = "Launch for debugging", + Description = "The -debugNative option launches the app in suspended, ready-to-debug state.", + SwitchValue = "-debugNative ", + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for Device property. + /// Device property designates the IP of the target device. + /// + public string Device + { + get { return GetSwitchAsString(DEVICE); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = DEVICE, + DisplayName = "Device IP", + Description = "The -device option specifies the target device's IP address.", + SwitchValue = "-device ", + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for Password property. + /// Password property specifies the target device password. + /// + public string Password + { + get { return GetSwitchAsString(PASSWORD); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PASSWORD, + DisplayName = "Device Password", + Description = "The -password option specifies the target device's password.", + SwitchValue = "-password ", + Value = DecryptPassword(value) + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for Package property. + /// Package property specified package to be installed/launched on task execution. + /// + public string Package + { + get { return GetSwitchAsString(PACKAGE); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PACKAGE, + DisplayName = "Package", + Description = "The -package option specifies a .bar package.", + SwitchValue = "-package ", + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for PackageId property + /// + [Output] + public string PackageId + { + get { return GetSwitchAsString(PACKAGE_ID); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PACKAGE_ID, + DisplayName = "Package ID", + Description = "The -package-id option specifies the application's package id.", + SwitchValue = "-package-id ", + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for PackageName property + /// + [Output] + public string PackageName + { + get { return GetSwitchAsString(PACKAGE_NAME); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PACKAGE_NAME, + DisplayName = "Package Name", + Description = "The -package-name option specifies the application's package name.", + SwitchValue = "-package-name ", + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for LocalManifestFile property + /// We need the local manifest in order to determine PackageId and PackageName. + /// + public string LocalManifestFile + { + get { return _localManifest; } + set + { + _localManifest = value; + + string[] lines = File.ReadAllLines(_localManifest); + + for (int i = 0; i < lines.Length; i++) + { + if (lines[i].StartsWith("Package-Name: ")) + { + string name = lines[i].Substring(14); + PackageName = name; + } + else if (lines[i].StartsWith("Package-Id: ")) + { + string id = lines[i].Substring(12); + PackageId = id; + } + } + } + } + + /// + /// Getter/Setter for the TargetManifestFile + /// + [Output] + public string TargetManifestFile + { + get { return null; } + } + + #endregion + } +} diff --git a/src_vs2012/BuildTasks/BBNativePackager.cs b/src_vs2012/BuildTasks/BBNativePackager.cs new file mode 100644 index 00000000..0da65add --- /dev/null +++ b/src_vs2012/BuildTasks/BBNativePackager.cs @@ -0,0 +1,662 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using BlackBerry.BarDescriptor.Model; +using BlackBerry.BuildTasks.BarDescriptor; +using BlackBerry.BuildTasks.Properties; +using Microsoft.Build.CPPTasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace BlackBerry.BuildTasks +{ + public sealed class BBNativePackager : BBTask + { + #region Member Variable and Constant Declarations + + private QnxRootType _descriptor; + private string _projectDirectory; + private string _appName; + private string _barDescriptorPath = ""; + + private const string OUTPUT_FILE = "OutputFiles"; + private const string APP_DESCRIPTOR = "ApplicationDescriptorXml"; + private const string TARGET_FORMAT = "TargetFormat"; + private const string BUILD_ID = "BuildId"; + private const string BUILD_ID_FILE = "BuildIdFile"; + private const string DEV_MODE = "DevMode"; + private const string CONFIGURATION = "Configuration"; + private const string PACKAGE_MANIFEST_ONLY = "PackageManifestOnly"; + private const string DEBUG_TOKEN = "DebugToken"; + private const string SOURCES = "Sources"; + private const string GET_TARGET_FILE_MAP = "GetTargetFileMap"; + private const string WORKSPACE_LOC = "${workspace_loc:/"; + + private StreamWriter _localLogWriter; + + #endregion + + /// + /// BBNativePackager default constructor + /// + public BBNativePackager() + : base(Resources.ResourceManager) + { + DefineSwitchOrder(TARGET_FORMAT, BUILD_ID, BUILD_ID_FILE, DEV_MODE, CONFIGURATION, GET_TARGET_FILE_MAP, PACKAGE_MANIFEST_ONLY, OUTPUT_FILE, APP_DESCRIPTOR); + } + + #region Overrides + + /// + /// Return the response file switch. + /// Note: Don't use response file for msbuild because it is removed before qcc to run GCC compiler + /// + /// Response File Path + /// Response File Switch + protected override string GetResponseFileSwitch(string responseFilePath) + { + return string.Empty; + } + + /// + /// Return the Command Line String. + /// Note: pass the response file to command line commands + /// + /// Command Line String + protected override string GenerateCommandLineCommands() + { + return GenerateResponseFileCommands(); + } + + /// + /// Return the Response File Command String + /// + protected override string GenerateResponseFileCommands() + { + StringBuilder resultCommand = new StringBuilder(base.GenerateResponseFileCommands()); + PackagerCmdBuilder packagerBuilder = new PackagerCmdBuilder(); + + AppendResources(packagerBuilder); + resultCommand.Append(' ').Append(packagerBuilder); + + return resultCommand.ToString(); + } + + /// + /// Creates a temporary response (.rsp) file and runs the executable file. + /// + /// + /// The returned exit code of the executable file. If the task logged errors, but the executable returned an exit code of 0, this method returns -1. + /// + /// The path to the executable file.The command line arguments to place in the .rsp file.The command line arguments to pass directly to the executable file. + protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) + { + // Output the .bar file's manifest to a file so we can parse it. + if (PackageManifestOnly) + { + _localLogWriter = File.CreateText("localManifest.mf"); + _localLogWriter.WriteLine("Info: Generating local manifest ({0})", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + } + else if (GetTargetFileMap) + { + _localLogWriter = File.CreateText("targetFileMap.txt"); + _localLogWriter.WriteLine("Info: Generating target map-file ({0})", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + } + + var result = base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); + + if (_localLogWriter != null) + { + _localLogWriter.Dispose(); + _localLogWriter = null; + } + + return result; + } + + /// + /// Parses a single line of text to identify any errors or warnings in canonical format. + /// + /// A single line of text for the method to parse.A value of that indicates the importance level with which to log the message. + protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) + { + // dump all printouts of this tool into dedicated logger: + if (_localLogWriter != null) + { + _localLogWriter.WriteLine(singleLine); + LogToolError(singleLine); + return; + } + + base.LogEventsFromTextOutput(singleLine, messageImportance); + } + + /// + /// Helper function to read the assets from the bar-descriptor.xml file and + /// generate the command line listing the resources to be packaged into the bar file. + /// + /// Command Line Builder object + private void AppendResources(CommandLineBuilder commandBuilder) + { + // is it a regular application? + if (string.Compare(AppType, "Regular", StringComparison.OrdinalIgnoreCase) == 0 || string.IsNullOrEmpty(MakefileTargetName)) + { + IEnumerable sources = GetAssetsFile(); + foreach (ITaskItem item in sources) + { + string target = item.GetMetadata("target"); + if (item.ItemSpec == target) + { + commandBuilder.AppendFileNameIfNotNull(item); + } + else + { + commandBuilder.AppendSwitchIfNotNull("-e ", item); + commandBuilder.AppendFileNameIfNotNull(target); + } + } + } + else + { + if (string.Compare(AppType, "Cascades", StringComparison.OrdinalIgnoreCase) == 0) + { + // or Cascades application, where we can use directly the configuration with specified name from bar-descriptor file? + commandBuilder.AppendTextUnquoted("-configuration \"" + MakefileTargetName + "\""); + + /* + ActiveToolSwitches.Remove(CONFIGURATION); + + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Configuration Name", + Description = "Name of the configuration from bar-descriptor.xml to use during BAR build", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-configuration ", + Name = CONFIGURATION, + Value = MakefileTargetName + }; + ActiveToolSwitches.Add(CONFIGURATION, switch2); + AddActiveSwitchToolValue(switch2); + */ + } + else + { + // custom makefile: + var expectedTargetName = string.Concat(Platform, "-", Configuration); + commandBuilder.AppendTextUnquoted("-configuration \"" + expectedTargetName + "\""); + } + } + } + + /// + /// Return the assets from the bar-descriptor.xml + /// + private IEnumerable GetAssetsFile() + { + //make sure the _descriptor is loaded + if (_descriptor == null) + { + _descriptor = Parser.Load(Path.Combine(ProjectDir, ApplicationDescriptorXml)); + } + AssetType[] globalAssets = _descriptor.asset; + AssetType[] configAssets = null; + + // You can call a configuration whatever you like, but these are the ones Momentics uses for its various + // platform + configuration combinations. Usually this is the same as the output directory, but asset paths + // don't have anything to do with the configuration name. I've based the config names on the platform + // + configuration combination, not the output directory. + var configs = _descriptor.configuration; + var expectedConfigName = string.Concat(Platform, "-", Configuration); + + foreach (var config in configs) + { + if (config.name == expectedConfigName) + { + configAssets = config.asset; + break; + } + if (expectedConfigName == "Simulator-Debug" && (config.name == "Simulator" || config.name == expectedConfigName)) + { + configAssets = config.asset; + break; + } + } + + var items = new List(); + + AppendAssets(items, globalAssets); + AppendAssets(items, configAssets); + + return items.ToArray(); + } + + private void AppendAssets(ICollection result, IEnumerable assets) + { + if (result == null) + throw new ArgumentNullException("result"); + + if (assets != null) + { + foreach (var asset in assets) + { + string path = asset.path; + path = path.Replace("}", string.Empty).Replace(WORKSPACE_LOC, ProjectDir); + string target = asset.Value; + + if (!string.IsNullOrEmpty(target)) + { + var item = new TaskItem(path); + item.SetMetadata("target", target); + result.Add(item); + } + else + { + Log.LogWarning("Asset \"{0}\" has no value set. Ignoring.", path); + } + } + } + } + + /// + /// Getter for the CommandTLogName property + /// + protected override string CommandTLogName + { + get { return "BBNativePackager.command.1.tlog"; } + } + + /// + /// Getter for the ReadTLogNames property. + /// + protected override string[] ReadTLogNames + { + get { return new[] { "BBNativePackager.read.1.tlog", "BBNativePackager.*.read.1.tlog" }; } + } + + /// + /// Getter for the WriteTLogNames property + /// + protected override string[] WriteTLogNames + { + get { return new[] { "BBNativePackager.write.1.tlog", "BBNativePackager.*.write.1.tlog" }; } + } + + /// + /// Getter for the ToolName property + /// + protected override string ToolName + { + get { return ToolExe; } + } + + #endregion + + #region Properties + + /// + /// Getter/Setter for Device property + /// + [Output] + public string Device { get; set; } + + /// + /// Getter/Setter for Password property + /// + [Output] + public string Password { get; set;} + + /// + /// Getter/Setter for BarDeploy property + /// + [Output] + public string BarDeploy { get; set; } + + /// + /// Getter/Setter for OutputFile property + /// + [Required] + [Output] + public string OutputFile + { + get + { + if (IsPropertySet(OUTPUT_FILE) && IsExplicitlySetToFalse(PACKAGE_MANIFEST_ONLY)) + { + return ActiveToolSwitches[OUTPUT_FILE].Value; + } + return null; + } + set + { + String switchValue = ""; + if (IsPropertySet(OUTPUT_FILE) && IsExplicitlySetToFalse(PACKAGE_MANIFEST_ONLY)) + { + switchValue = "-package "; + } + + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.File) + { + Name = OUTPUT_FILE, + DisplayName = "Output bar file name, for example, out.bar", + Description = "The -package option specifies the bar file name.", + ArgumentRelationList = new ArrayList(), + SwitchValue = switchValue, + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for ProjectDir property + /// + [Required] + public string ProjectDir + { + get { return _projectDirectory; } + set + { + _projectDirectory = value; + _descriptor = Parser.Load(Path.Combine(ProjectDir, ApplicationDescriptorXml)); + } + } + + /// + /// Getter/Setter for AppName property + /// + [Required] + public string AppName + { + get { return _appName; } + set + { + _appName = value; + + if (string.IsNullOrEmpty(_barDescriptorPath)) + { + // Default location of bar-descriptor file, if not specified in the Properties Configurations. + _barDescriptorPath = "BlackBerry-" + _appName + "\\bar-descriptor.xml"; + if (!File.Exists(_barDescriptorPath)) + { + // Just to support the default locations of bar-descriptor from previous versions of the plug-in. + _barDescriptorPath = _appName + "_barDescriptor\\bar-descriptor.xml"; + if (!File.Exists(_barDescriptorPath)) + { + _barDescriptorPath = "bar-descriptor.xml"; + } + } + } + + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.File) + { + Name = APP_DESCRIPTOR, + DisplayName = "Application descriptor file name, for example, bar-descriptor.xml", + Description = "Application descriptor file name, for example, bar-descriptor.xml, it must follows the out.bar file", + ArgumentRelationList = new ArrayList(), + Value = _barDescriptorPath + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for SolutionDir property + /// + [Required] + public string SolutionDir { get; set; } + + [Required] + public string ApplicationDescriptorXml + { + get { return GetSwitchAsString(APP_DESCRIPTOR); } + set { _barDescriptorPath = value; } + } + + /// + /// Getter/Setter for TargetFormat property + /// + public string TargetFormat + { + get { return GetSwitchAsString(TARGET_FORMAT); } + set + { + string[][] switchMap = + { + new[] { "bar", "-target bar" }, + new[] { "bar-debug", "-target bar-debug" } + }; + + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = TARGET_FORMAT, + DisplayName = "Target format", + Description = "Select the build target format (-target bar -target bar-debug)", + ArgumentRelationList = new ArrayList(), + SwitchValue = ReadSwitchMap(TARGET_FORMAT, switchMap, value), + Value = value, +#if PLATFORM_VS2010 + MultiValues = true +#else + MultipleValues = true +#endif + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for BuildID property + /// + public int BuildID + { + get { return GetSwitchAsInt32(BUILD_ID); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Integer) + { + Name = BUILD_ID, + DisplayName = "Build Id", + Description = "Set the build id (the fourth segment of the version). Must be a numbers from 0 to 65535", + ArgumentRelationList = new ArrayList(), + IsValid = ValidateInteger(BUILD_ID, 0, 65535, value), + SwitchValue = "-buildId ", + Number = value, + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for BuildIDFile property + /// + public string BuildIDFile + { + get { return GetSwitchAsString(BUILD_ID_FILE); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.File) + { + Name = BUILD_ID_FILE, + DisplayName = "Build ID File", + Description = "set the build ID from an existing file", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-buildIdFile ", + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for DevMode property + /// + public bool DevMode + { + get { return GetSwitchAsBool(DEV_MODE); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + Name = DEV_MODE, + DisplayName = "Development mode", + Description = "Package in development mode (-devMode)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-devMode", + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for PackageManifestOnly property + /// + public bool PackageManifestOnly + { + get { return GetSwitchAsBool(PACKAGE_MANIFEST_ONLY); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Package manifest only.", + Description = "Package only the manifest file ( -packageManifest)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-packageManifest -listManifest ", + Name = PACKAGE_MANIFEST_ONLY, + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for GetTargetFileMap property + /// + public bool GetTargetFileMap + { + get { return GetSwitchAsBool(GET_TARGET_FILE_MAP); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + Name = GET_TARGET_FILE_MAP, + DisplayName = "Get target file map", + Description = "Get the mapping between local and target files with the -targetFileMap option.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-targetFileMap ", + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for DebugToken property + /// + public string DebugToken + { + get { return GetSwitchAsString(DEBUG_TOKEN); } + set + { + ActiveToolSwitches.Remove(DEBUG_TOKEN); + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Directory) + { + Name = DEBUG_TOKEN, + DisplayName = "Debug Token", + Description = "Use debug token to generate author and author id ( -debugToken only usable with -devMode)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-debugToken ", + Value = value + }; + toolSwitch.Parents.AddLast(DEV_MODE); + SetSwitch(toolSwitch); + } + } + + /// + /// Getter for the TrackedInputFiles + /// + protected override ITaskItem[] TrackedInputFiles + { + get { return Sources; } + } + + /// + /// Getter/Seter for the Sources property + /// + [Required] + public ITaskItem[] Sources + { + get { return GetSwitchAsItemArray(SOURCES); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.ITaskItemArray) + { + Name = SOURCES, + Separator = " ", + Required = true, + ArgumentRelationList = new ArrayList(), + TaskItemArray = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the Configuration property + /// + [Required] + public string Configuration + { + get; + set; + } + + /// + /// Getter/Setter for the Platform property + /// + [Required] + public string Platform + { + get; + set; + } + + /// + /// Gets or sets the type of application, which is currently built. + /// + [Required] + public string AppType + { + get; + set; + } + + /// + /// Gets or set the name of makefile's target issuing the build. + /// + public string MakefileTargetName + { + get; + set; + } + + #endregion + } +} diff --git a/src_vs2012/BuildTasks/BBSigner.cs b/src_vs2012/BuildTasks/BBSigner.cs new file mode 100644 index 00000000..316643bf --- /dev/null +++ b/src_vs2012/BuildTasks/BBSigner.cs @@ -0,0 +1,256 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.Collections; +using BlackBerry.BuildTasks.Properties; +using Microsoft.Build.CPPTasks; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks +{ + /// + /// MSBuild Task responsible for the signing of the BlackBerry Bar files + /// for deploy to a secure device not in development mode. + /// + public sealed class BBSigner : BBTask + { + #region Member Variables and Constants Declaration + + private const string REGISTER = "Register"; + private const string KEYSTOREPASSWORD = "KeyStorePassword"; + private const string CSJPIN = "CSJPin"; + private const string CSJFILES = "Signing_AND_DEBUGTOKEN_CSJFiles"; + private const string SOURCES = "Sources"; + private const string OUTPUT_FILE = "OutputFiles"; + + #endregion + + /// + /// BBSigner default constructor + /// + public BBSigner() + : base(Resources.ResourceManager) + { + DefineSwitchOrder("AlwaysAppend", REGISTER, CSJPIN, KEYSTOREPASSWORD, CSJFILES, OUTPUT_FILE); + } + + #region Overrides + + /// + /// Return the GetResposeFile Switch + /// Note: don't use response file for msbuild because it is removed before qcc to run GCC compiler + /// + protected override string GetResponseFileSwitch(string responseFilePath) + { + return string.Empty; + } + + /// + /// Return the command line argument string + /// Note: pass the response file to command line commands + /// + /// + protected override string GenerateCommandLineCommands() + { + return GenerateResponseFileCommands(); + } + + /// + /// Return the Response File Commands string. + /// + protected override string GenerateResponseFileCommands() + { + if (!Register) + { + RemoveFromSwithOrder(REGISTER, CSJPIN, CSJFILES); + } + else + { + RemoveFromSwithOrder(OUTPUT_FILE); + } + return base.GenerateResponseFileCommands(); + } + + /// + /// Getter for the CommandTLogName property + /// + protected override string CommandTLogName + { + get { return "BBSigner.command.1.tlog"; } + } + + /// + /// Getter for the ReadTLogNames property + /// + protected override string[] ReadTLogNames + { + get { return new[] { "BBSigner.read.1.tlog", "BBSigner.*.read.1.tlog" }; } + } + + protected override string[] WriteTLogNames + { + get { return new[] { "BBSigner.write.1.tlog", "BBSigner.*.write.1.tlog" }; } + } + + /// + /// Getter for the ToolName property + /// + protected override string ToolName + { + get { return ToolExe; } + } + + /// + /// Getter for the TrackedInputFiles property + /// + protected override ITaskItem[] TrackedInputFiles + { + get { return Sources; } + } + + #endregion + + #region Properties + + /// + /// Getter/Setter for the Register property + /// + [Required] + public bool Register + { + get { return GetSwitchAsBool(REGISTER); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Boolean) + { + Name = REGISTER, + DisplayName = "Register", + Description = "Register the computer with CSJ file to sign application( -register)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-register", + BooleanValue = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the Sources property + /// + [Required] + public ITaskItem[] Sources + { + get { return GetSwitchAsItemArray(SOURCES); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.ITaskItemArray) + { + Name = SOURCES, + Separator = " ", + Required = true, + ArgumentRelationList = new ArrayList(), + TaskItemArray = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the CSJFiles property + /// + public ITaskItem[] CSJFiles + { + get { return GetSwitchAsItemArray(CSJFILES); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.ITaskItemArray) + { + Name = CSJFILES, + Separator = " ", + Required = true, + ArgumentRelationList = new ArrayList(), + TaskItemArray = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the KeyStorePassword property + /// + public string KeyStorePassword + { + get { return GetSwitchAsString(KEYSTOREPASSWORD); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.File) + { + Name = KEYSTOREPASSWORD, + DisplayName = "Keystore password", + Description = "The -storepass option specifies the password.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-storepass ", + Value = DecryptPassword(value) + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the CSJPin property + /// + public string CSJPin + { + get { return GetSwitchAsString(CSJPIN); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.File) + { + Name = CSJPIN, + DisplayName = "Keystore password", + Description = "The -csjpin option specifies the password.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-csjpin ", + Value = value + }; + SetSwitch(toolSwitch); + } + } + + /// + /// Getter/Setter for the OutputFile property + /// + [Required] + [Output] + public string OutputFile + { + get { return GetSwitchAsString(OUTPUT_FILE); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.File) + { + Name = OUTPUT_FILE, + DisplayName = "Output bar file name to be signed", + Description = "Specifies the bar file name to be signed", + ArgumentRelationList = new ArrayList(), + Value = value + }; + SetSwitch(toolSwitch); + } + } + + #endregion + } +} + \ No newline at end of file diff --git a/src_vs2012/BuildTasks/BBTask.cs b/src_vs2012/BuildTasks/BBTask.cs new file mode 100644 index 00000000..75e3d43a --- /dev/null +++ b/src_vs2012/BuildTasks/BBTask.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections; +using System.IO; +using System.Resources; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Helpers; +using Microsoft.Build.CPPTasks; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks +{ + /// + /// Base class for all BlackBerry-related MSBuild tasks. + /// + public abstract class BBTask : TrackedVCToolTask + { + private readonly ArrayList _switchOrderList; + + private const string TRACKER_LOG_DIRECTORY = "TrackerLogDirectory"; + + /// + /// Init constructor. + /// + internal BBTask(ResourceManager taskResources) + : base(taskResources) + { + var newPath = string.Concat("PATH=", Path.Combine(ConfigDefaults.JavaHome, "bin"), ";", Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Process)); + EnvironmentVariables = new[] { newPath }; + + _switchOrderList = new ArrayList(); + } + + #region Properties + + /// + /// Gets or sets the directory for logs. + /// + public string TrackerLogDirectory + { + get { return GetSwitchAsString(TRACKER_LOG_DIRECTORY); } + set + { + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.Directory) + { + Name = TRACKER_LOG_DIRECTORY, + DisplayName = "Tracker Log Directory", + Description = "Tracker Log Directory.", + Value = EnsureTrailingSlash(value) + }; + SetSwitch(toolSwitch); + } + } + + #endregion + + /// + /// Decrypts a given string. + /// + protected string DecryptPassword(string value) + { + return GlobalHelper.Decrypt(value); + } + + /// + /// Defines the order of switches appearing in generated command-line. + /// + protected void DefineSwitchOrder(params string[] switchNames) + { + if (switchNames != null) + { + _switchOrderList.Clear(); + foreach (var name in switchNames) + { + _switchOrderList.Add(name); + } + + _switchOrderList.Add(TRACKER_LOG_DIRECTORY); + } + } + + /// + /// Removes specified switches from the order list to appear in generated command-line. + /// + protected void RemoveFromSwithOrder(params string[] switchNames) + { + if (switchNames != null) + { + foreach (var name in switchNames) + { + _switchOrderList.Remove(name); + } + } + } + + /// + /// Getter for the SwitchOrderList property + /// + protected override ArrayList SwitchOrderList + { + get { return _switchOrderList; } + } + + /// + /// Getter for the TrackerIntermediateDirectory property + /// + protected override string TrackerIntermediateDirectory + { + get + { + if (TrackerLogDirectory != null) + { + return TrackerLogDirectory; + } + return string.Empty; + } + } + + /// + /// Sets the values for generated command-line switch. + /// + protected void SetSwitch(ToolSwitch toolSwitch) + { + if (toolSwitch == null) + throw new ArgumentNullException("toolSwitch"); + if (string.IsNullOrEmpty(toolSwitch.Name)) + throw new ArgumentOutOfRangeException("toolSwitch"); + + // remove the switch, in case it was already defined: + ActiveToolSwitches.Remove(toolSwitch.Name); + RemoveSwitchToolBasedOnValue(toolSwitch.Name); + + // and add new value: + ActiveToolSwitches.Add(toolSwitch.Name, toolSwitch); + AddActiveSwitchToolValue(toolSwitch); + } + + /// + /// Gets the string value of existing tool-switch or null. + /// + protected string GetSwitchAsString(string name) + { + if (IsPropertySet(name)) + { + return ActiveToolSwitches[name].Value; + } + + return null; + } + + /// + /// Gets the numeric value of existing tool-switch or 0. + /// + protected int GetSwitchAsInt32(string name) + { + if (IsPropertySet(name)) + { + return ActiveToolSwitches[name].Number; + } + + return 0; + } + + /// + /// Gets the bool value of existing tool-switch or false. + /// + protected bool GetSwitchAsBool(string name) + { + return IsPropertySet(name) && ActiveToolSwitches[name].BooleanValue; + } + + /// + /// Gets the array value of existing tool-switch or null. + /// + protected ITaskItem[] GetSwitchAsItemArray(string name) + { + if (IsPropertySet(name)) + { + return ActiveToolSwitches[name].TaskItemArray; + } + return null; + } + + /// + /// Reports specified error returned from BlackBerry tool (by removing leading 'Error: ' prefix). + /// + protected bool LogToolError(string text) + { + if (string.IsNullOrEmpty(text)) + return false; + + string message = null; + bool skipPrinting = false; + + if (text.StartsWith("Error: ", StringComparison.OrdinalIgnoreCase)) + { + message = text.Substring(7).Trim(); + skipPrinting = true; + } + else + { + if (text.StartsWith("[ERROR] ", StringComparison.OrdinalIgnoreCase)) + { + message = text.Substring(8).Trim(); + skipPrinting = true; + } + else + { + if (text.StartsWith("result::failure ", StringComparison.OrdinalIgnoreCase)) + { + // skip the error-id, if specified before message: + int i = text.Length > 16 && char.IsDigit(text[16]) ? text.IndexOf(' ', 16) : 15; + if (i > 0) + { + message = text.Substring(i + 1); + } + } + } + } + + if (!string.IsNullOrWhiteSpace(message)) + { + // add a dedicated error for the tool failure: + BuildEngine.LogErrorEvent(new BuildErrorEventArgs(null, null, GetType().Name, 0, 0, 0, 0, message, null, GetType().Name)); + return skipPrinting; + } + + return false; + } + + /// + /// Parses a single line of text to identify any errors or warnings in canonical format. + /// + /// A single line of text for the method to parse.A value of that indicates the importance level with which to log the message. + protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) + { + // is it a failure result? + // then add a dedicated error-task for it: + if (LogToolError(singleLine)) + { + return; + } + + base.LogEventsFromTextOutput(singleLine, messageImportance); + } + } +} diff --git a/src_vs2012/BuildTasks/BarDescriptor/Parser.cs b/src_vs2012/BuildTasks/BarDescriptor/Parser.cs new file mode 100644 index 00000000..5524169d --- /dev/null +++ b/src_vs2012/BuildTasks/BarDescriptor/Parser.cs @@ -0,0 +1,53 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Diagnostics; +using System.IO; +using System.Xml; +using System.Xml.Serialization; +using BlackBerry.BarDescriptor.Model; + +namespace BlackBerry.BuildTasks.BarDescriptor +{ + static class Parser + { + /// + /// Helper function to to deserialize the bar-descriptor.xml file for read. + /// + /// Path to the bar-descriptor.xml file + /// BarDescriptor.qnx object containing the deserialized data from the bar-descriptor. + public static QnxRootType Load(string filename) + { + if (!string.IsNullOrEmpty(filename)) + { + try + { + using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) + { + XmlTextReader reader = new XmlTextReader(fs); + XmlSerializer serializer = new XmlSerializer(typeof(QnxRootType)); + return serializer.Deserialize(reader) as QnxRootType; + } + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + throw; + } + } + return null; + } + } +} diff --git a/src_vs2012/BuildTasks/BlackBerry.BuildTasks.csproj b/src_vs2012/BuildTasks/BlackBerry.BuildTasks.csproj new file mode 100644 index 00000000..6cc44bdf --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry.BuildTasks.csproj @@ -0,0 +1,233 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {328CAD98-F4E5-444A-B5DF-AD102C67BA3C} + Library + Properties + BlackBerry.BuildTasks + BlackBerry.BuildTasks + v4.5 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2012 + prompt + 4 + false + AnyCPU + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2012 + prompt + 4 + false + AnyCPU + + + + + False + ..\..\..\..\..\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.Build.CPPTasks.Common.v110\v4.0_4.0.0.0__b03f5f7f11d50a3a\Microsoft.Build.CPPTasks.Common.v110.dll + + + + + + + + + + + + + Properties\AssemblyInfo.cs + + + ConfigDefaults.cs + + + Helpers\GlobalHelper.cs + + + NativeMethods.cs + + + BarDescriptor\Schema\bar-descriptor.cs + + + BarDescriptor\Schema\bar-descriptor.Extensions.cs + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + Code + + + + + + + + + True + True + ConfigPriTemplate.tt + + + + True + True + MakefileTemplate.tt + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + Designer + + + Always + Designer + + + TextTemplatingFilePreprocessor + ConfigPriTemplate.cs + + + TextTemplatingFilePreprocessor + MakefileTemplate.cs + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Common.props b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Common.props new file mode 100644 index 00000000..fc71e978 --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Common.props @@ -0,0 +1,185 @@ + + + + + + + armle-v7 + Regular + Unicode + + + + + QCC;__QCC__;__QNX__;QNX_DEVICE=1;QNX_FAMILY=device + QCC;__QCC__;__QNX__;QNX_DEVICE=2;QNX_TABLET=1;QNX_FAMILY=tablet + false + + + QCC;__QCC__;__QNX__;QNX_SIMULATOR=1;QNX_FAMILY=device-simulator + QCC;__QCC__;__QNX__;QNX_SIMULATOR=2;QNX_TABLET=1;QNX_FAMILY=tablet-simulator + false + + + + + true + false + + + + + true + .a + lib + + + + true + + + + + + true + .so + true + lib + + + + $(IntermediateOutputPath) + Device-$(Configuration)\ + Device-$(Configuration)\ + $(IntDir) + + gcc_ntoarmv7le + Device + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@device_IP) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@device_password) + armle-v7 + arm + .le-v7 + + + + $(IntermediateOutputPath) + Simulator-$(Configuration)\ + Simulator-$(Configuration)\ + $(IntDir) + + gcc_ntox86 + Simulator + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@simulator_IP) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@simulator_password) + x86 + x86 + + + + + + $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) + $(TargetPath.TrimEnd('\')) + $([System.IO.Path]::GetFileName('$(TargetPath)')) + $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) + $(LibPrefix)$(ProjectName) + + + + + + $(IntDir)%(FileName).o + $(QccDefines) + WIN32;_WINDOWS + NormalWarnings + false + false + + true + + false + false + Default + true + + + + + + + O2 + true + + + + + + + O2 + false + + + + + + + $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) + $(TargetPath) + + + false + false + true + false + true + Default + + + + + + + $(OutDir)$(LibPrefix)$(TargetName)$(TargetExt) + false + + + + + + + $(IntDir) + true + $(OutDir)$(TargetName).bar + true + false + false + bar-debug + bar + true + false + None + Install + false + 1 + bar-descriptor.xml + + + + + BlackBerryDebugEngine + + + + diff --git a/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets new file mode 100644 index 00000000..1050d103 --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.Packager.targets @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + true + + + + true + + + + true + + + + + $(BuildLinkTargets); + + $(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets) + + + + + + + + + + + + + + + + + + $([System.IO.Path]::Combine($(ProjectDir),$(OutDir)$(LibPrefix)$(TargetName)$(TargetExt))) + $([System.IO.Path]::GetFileName('$(TargetPath)')) + $([System.IO.Path]::GetDirectoryName('$(TargetPath)')) + $(LibPrefix)$(ProjectName) + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + true + $(IsAppInstalled) + false + + + + + + + + + + + + + + + + + + + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@CSKPass) + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props new file mode 100644 index 00000000..2780b946 --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.default.props @@ -0,0 +1,28 @@ + + + + + BlackBerry + qcc + qcc + Regular + all + armle-v7 + Unicode + + + <_PlatformToolsetShortNameFor_qcc Condition="'$(_PlatformToolsetShortNameFor_qcc)' == ''">BlackBerry + + <_PlatformToolsetFriendlyNameFor_qcc Condition="'$(_PlatformToolsetFriendlyNameFor_qcc)' == ''">BlackBerry QNX Compiler (qcc) + + diff --git a/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.props b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.props new file mode 100644 index 00000000..0cf4147f --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.props @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets new file mode 100644 index 00000000..af138eff --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/Microsoft.Cpp.BlackBerry.targets @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + CompileAsC + CompileAsCpp + false + + + + + + + $(DefaultToolArchitecture) + + + + + + + + false + + + + + $(DefaultToolArchitecture) + + + + + + + + + + + false + false + true + $(DefaultToolArchitecture) + true + + + + + + CompileAsC + CompileAsCpp + + + + + + + + + + + + + $(CleanDependsOn); + MakeClean; + + + + + + + + + + + + + PlatformPrepareForBuild;$(PrepareForBuildDependsOn) + PlatformPrepareForBuild;$(PrepareForBuildDependsOn) + + + + \ No newline at end of file diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/ndkProjectItemsSchema.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/ProjectItemsSchema.xml similarity index 100% rename from src/VSNDK.Tasks/BlackBerry/Rules/ndkProjectItemsSchema.xml rename to src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/ProjectItemsSchema.xml diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/cl.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/cl.xml new file mode 100644 index 00000000..6ebc828e --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/cl.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/debugger_general.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/debugger_general.xml new file mode 100644 index 00000000..9135f4fd --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/debugger_general.xml @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/src/VSNDK.Tasks/BlackBerry/Rules/ndk_directories.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/directories.xml similarity index 100% rename from src/VSNDK.Tasks/BlackBerry/Rules/ndk_directories.xml rename to src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/directories.xml diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/general.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/general.xml new file mode 100644 index 00000000..af3c8535 --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/general.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/lib.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/lib.xml new file mode 100644 index 00000000..36115ecb --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/lib.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/link.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/link.xml new file mode 100644 index 00000000..f3ca56e5 --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/link.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/packager.xml b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/packager.xml new file mode 100644 index 00000000..5fef944d --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/1033/packager.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props new file mode 100644 index 00000000..b84e0c4d --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.props @@ -0,0 +1,83 @@ + + + + + + + + + + <_NoWinAPIFamilyApp Condition="'$(_NoWinAPIFamilyApp)' == ''">true + true + true + false + false + + false + true + + + + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@NDKTargetPath) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@NDKHostPath) + $(Registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@NDKFamilyType) + $([System.IO.File]::ReadAllText("$(QNX_HOST)\etc\qcc\gcc\default").Substring(4,5)) + $(QNX_HOST)\etc\qcc\gcc + $(from_file) + $(LocalAppData) + + + $(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion@CurrentVersion) + $(HomeDrive)$(HomePath)\Local Settings\Application Data + + $(AppDataPath)\Research In Motion + $(SSHKeyDir)\bbt_id_rsa.pub + $(SSHKeyDir)\bbt_id_rsa + + + + + + + qcc2.0 + $(QNX_HOST)\usr\bin + $(QNX_TARGET)\$(CPUVARDIR)\lib + qcc.exe + qcc.exe + qcc.exe + $(registry:HKEY_CURRENT_USER\SOFTWARE\BlackBerry\VSPlugin@QNXToolsPath) + $(QNX_HOST)\usr\bin + $(MSBuildProgramFiles32)\MSBuild\BlackBerry\QnxTools\bin + $(QnxToolsPath)\blackberry-signer.bat + $(QnxToolsPath) + $(QnxToolsPath)\blackberry-nativepackager.bat + $(QnxToolsPath) + $(QnxToolsPath)\blackberry-deploy.bat + $(QnxToolsPath)\blackberry-connect.bat + ssh.exe + $(QccToolsPath) + $(QccToolsPath)\ssh-keygen.exe + + + + $(QNX_HOST)\usr\bin;$(PATH); + $(QNX_TARGET)\usr\include;$(QNX_TARGET)\usr\include\freetype2;$(QNX_TARGET)\usr\include\qt4\QtCore;$(QNX_TARGET)\usr\include\qt4\QtDeclarative;$(QNX_TARGET)\usr\include\qt4;$(QNX_TARGET)\..\target-override\usr\include;$(QNX_TARGET)\usr\include\cpp;$(QNX_TARGET)\usr\include\cpp\c;$(ProjectDir)\arm\o.le-v7-g\.moc;$(ProjectDir)\arm\o.le-v7\.moc;$(ProjectDir)\x86\o-g\.moc + $(QccLibPath);$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\lib;$(QNX_TARGET)\..\target-override\$(CPUVARDIR)\usr\lib; + + $(ExecutablePath) + + + + diff --git a/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.targets b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.targets new file mode 100644 index 00000000..ffcf5d45 --- /dev/null +++ b/src_vs2012/BuildTasks/BlackBerry/PlatformToolsets/qcc/Microsoft.Cpp.BlackBerry.qcc.targets @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2012/BuildTasks/CheckIfInstalled.cs b/src_vs2012/BuildTasks/CheckIfInstalled.cs new file mode 100644 index 00000000..aca53844 --- /dev/null +++ b/src_vs2012/BuildTasks/CheckIfInstalled.cs @@ -0,0 +1,99 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace BlackBerry.BuildTasks +{ + /// + /// MSBuild Task to check if the application was previously installed. + /// + public sealed class CheckIfInstalled : Task + { + #region Member Variables and Constants + + private string _listFile; + private string _appName; + private bool _isAppInstalled; + + #endregion + + /// + /// Execute the MSBuild task + /// + /// True on successful execution + public override bool Execute() + { + try + { + _isAppInstalled = false; + + string[] installedApps = File.ReadAllLines(_listFile); + foreach (string app in installedApps) + { + if (app.Contains(_appName)) + { + _isAppInstalled = true; + break; + } + } + + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Setter for the ListFile property + /// + [Required] + public string ListFile + { + set + { + _listFile = value; + } + } + + /// + /// Setter for the AppName property + /// + [Required] + public string AppName + { + set + { + _appName = value; + } + } + + /// + /// Getter for the IsAppInstalled property + /// + [Output] + public bool IsAppInstalled + { + get + { + return _isAppInstalled; + } + } + } +} diff --git a/src_vs2012/BuildTasks/DiffManifests.cs b/src_vs2012/BuildTasks/DiffManifests.cs new file mode 100644 index 00000000..accdd770 --- /dev/null +++ b/src_vs2012/BuildTasks/DiffManifests.cs @@ -0,0 +1,237 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace BlackBerry.BuildTasks +{ + /// + /// MSBuild task to compare the manifest file from the bar file being uploaded against the one already installed on the device. + /// + public sealed class DiffManifests : Task + { + #region Member Variables and Constants + + private string _localManifestFile; + private string _targetManifestFile; + private string _targetFileMap; + private ArrayList _modifiedFiles; + private ArrayList _deletedFiles; + private int _modifiedFilesCount; + private int _deletedFilesCount; + + #endregion + + /// + /// Execute the MSBuild Task. + /// + public override bool Execute() + { + _modifiedFiles = new ArrayList(); + _deletedFiles = new ArrayList(); + + // Parse local manifest to retrieve list of files and their hashes. + string[] localManifest = File.ReadAllLines(_localManifestFile); + Dictionary localFiles = new Dictionary(); + for (int i = 0; i < localManifest.Length; i++) + { + if (localManifest[i].StartsWith("Archive-Asset-Name: ")) + { + string assetName = localManifest[i].Substring(20); + i++; + if (localManifest[i].StartsWith("Archive-Asset-SHA-512-Digest: ")) + { + string assetHash = localManifest[i].Substring(30); + localFiles.Add(assetName, assetHash); + } + else + { + return false; + } + } + } + + // Do the same for the target manifest. + string[] targetManifest = File.ReadAllLines(_targetManifestFile); + Dictionary targetFiles = new Dictionary(); + for (int i = 0; i < targetManifest.Length; i++) + { + if (targetManifest[i].StartsWith("Archive-Asset-Name: ")) + { + string assetName = targetManifest[i].Substring(20); + i++; + if (targetManifest[i].StartsWith("Archive-Asset-SHA-512-Digest: ")) + { + string assetHash = targetManifest[i].Substring(30); + targetFiles.Add(assetName, assetHash); + } + else + { + return false; + } + } + } + + // Compare hashes and populate the lists of modified and deleted files. + string[] targetFileMap = File.ReadAllLines(_targetFileMap); + foreach (KeyValuePair file in localFiles) + { + // For some reason this MANIFEST.bbr file appears in the manifest, even though + // it doesn't actually exist anywhere...? It doesn't seem to correspond to + // MANIFEST.MF either. + if (file.Key == "META-INF/MANIFEST.bbr") + { + continue; + } + + // If the target manifest doesn't contain the same key/value pair, + // that means the local file has been either added or modified. + if (!targetFiles.Contains(file)) + { + TaskItem item = new TaskItem(file.Key); + item.SetMetadata("SourcePath", GetSourcePath(file.Key, targetFileMap)); + _modifiedFiles.Add(item); + } + } + + IDictionaryEnumerator targetEnum = targetFiles.GetEnumerator(); + while (targetEnum.MoveNext()) + { + // If the local manifest doesn't contain the same key, + // that means the target file has been deleted from the project. + if (!localFiles.ContainsKey((string)targetEnum.Key)) + { + TaskItem item = new TaskItem((string)targetEnum.Key); + _deletedFiles.Add(item); + } + } + + // For some reason the manifest file doesn't show up in the target file map + // or the manifest itself, so we add it manually here and always upload it. + TaskItem manifestItem = new TaskItem("META-INF/MANIFEST.MF"); + manifestItem.SetMetadata("SourcePath", "localManifest.mf"); + _modifiedFiles.Add(manifestItem); + + return true; + } + + /// + /// Helper function to parse the target file map to add the source path of each modified file as metadata. + /// + /// Path to the source file + /// Target file map + private string GetSourcePath(string sourcePath, string[] targetFileMap) + { + foreach (string line in targetFileMap) + { + if (line.Contains(sourcePath)) + { + int startIndex = line.IndexOf('='); + return line.Substring(startIndex + 1); + } + } + + return ""; + } + + /// + /// Getter for the ModifiedFiles property. + /// + [Output] + public ITaskItem[] ModifiedFiles + { + get + { + ITaskItem[] items = (ITaskItem[])_modifiedFiles.ToArray(typeof(ITaskItem)); + _modifiedFilesCount = items.Length; + return items; + } + } + + /// + /// Getter for the ModifiedFilesCount property + /// + [Output] + public int ModifiedFilesCount + { + get { return _modifiedFilesCount; } + set { _modifiedFilesCount = value; } + } + + /// + /// Getter for the DeletedFiles property + /// + [Output] + public ITaskItem[] DeletedFiles + { + get + { + ITaskItem[] items = (ITaskItem[])_deletedFiles.ToArray(typeof(ITaskItem)); + _deletedFilesCount = items.Length; + return items; + } + } + + /// + /// Getter/Setter for the DeletedFilesCount property + /// + [Output] + public int DeletedFilesCount + { + get { return _deletedFilesCount; } + set { _deletedFilesCount = value; } + } + + /// + /// Setter for the LocalManifestFile property + /// + [Required] + public string LocalManifestFile + { + set + { + _localManifestFile = value; + } + } + + /// + /// Setter for the TargetManifestFile property + /// + [Required] + public string TargetManifestFile + { + set + { + _targetManifestFile = value; + } + } + + /// + /// Setter for the targetFileMap property + /// + [Required] + public string TargetFileMap + { + set + { + _targetFileMap = value; + } + } + } +} diff --git a/src_vs2012/BuildTasks/GenerateMakefile.cs b/src_vs2012/BuildTasks/GenerateMakefile.cs new file mode 100644 index 00000000..97182870 --- /dev/null +++ b/src_vs2012/BuildTasks/GenerateMakefile.cs @@ -0,0 +1,446 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using BlackBerry.BuildTasks.Helpers; +using BlackBerry.BuildTasks.Templates; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace BlackBerry.BuildTasks +{ + /// + /// MSBuild Task for generating a make file for packaging the bar file. + /// + public sealed class GenerateMakefile : Task + { + #region Member Variables and Constants + + private string _projectDirectory; + private string _intDir; + private string _outDir; + + #endregion + + #region Properties + + /// + /// Gets or sets items supposed to compile. + /// + public ITaskItem[] CompileItems + { + set; + get; + } + + public ITaskItem[] IncludeItems + { + get; + set; + } + + /// + /// Getter/Setter for LinkItems + /// + public ITaskItem[] LinkItems + { + set; + get; + } + + /// + /// Getter/Setter for ProjectDir property + /// + public string ProjectDir + { + set { _projectDirectory = value != null ? value.Replace('\\', '/') : string.Empty; } + get { return _projectDirectory; } + } + + /// + /// Getter/Setter for IntDir property + /// + public string IntDir + { + set { _intDir = value != null ? value.Replace('\\', '/') : string.Empty; } + get { return _intDir; } + } + + /// + /// Getter/Setter for OutDir property + /// + public string OutDir + { + set { _outDir = value != null ? value.Replace('\\', '/') : string.Empty; } + get { return _outDir; } + } + + /// + /// Getter/Setter for AdditionalIncludeDirectories property + /// + public string[] AdditionalIncludeDirectories + { + set; + get; + } + + /// + /// Getter/Setter for AdditionLibraryDirectories + /// + public string[] AdditionalLibraryDirectories + { + set; + get; + } + + /// + /// Getter/Setter for ExcludeDirectories + /// + public string[] ExcludeDirectories + { + set; + get; + } + + /// + /// Getter/Setter for TargetName property + /// + public string TargetName + { + set; + get; + } + + /// + /// Getter/Setter for TargetExtension property + /// + public string TargetExtension + { + set; + get; + } + + public string SolutionName + { + get; + set; + } + + /// + /// Getter/Setter for ConfigurationType property + /// + public string ConfigurationType + { + set; + get; + } + + public string ConfigurationAppType + { + get; + set; + } + + public string TargetCompiler + { + get; + set; + } + + public string TargetArch + { + get; + set; + } + + /// + /// Getter/Setter for CompilerVersion property + /// + public string TargetCompilerVersion + { + set; + get; + } + + /// + /// Getter/Setter for Platform property + /// + public string Platform + { + set; + get; + } + + #endregion + + /// + /// Execute MSBuild Task + /// + public override bool Execute() + { + // are we asked not to generate makefile as developer supplied custom one: + if (ConfigurationAppType == "Custom") + { + NotifyMessage(new BuildMessageEventArgs("Skipped makefile creation", null, "GenerateMakefile", MessageImportance.High)); + return true; + } + + if (ConfigurationAppType == "Regular") + { + GenerateRegularMakefile(); + return true; + } + + if (ConfigurationAppType == "Cascades") + { + GenerateConfigPri(); + return true; + } + + return false; + } + + private void GenerateConfigPri() + { + // generate list of items to compile: + ITaskItem[] toCompile; + ITaskItem[] toCompileAsC; + ITaskItem[] toCompileAsCpp; + ITaskItem additionalInfo; + var linkInfo = LinkItems != null && LinkItems.Length > 0 ? LinkItems[0] : null; + + SplitCompileItems(CompileItems, ExcludeDirectories, out toCompile, out toCompileAsC, out toCompileAsCpp); + additionalInfo = toCompile != null && toCompile.Length > 0 ? toCompile[0] : null; + + using (var outputFile = new StreamWriter(ProjectDir + "config.pri")) + { + ITaskItem excludedHeader; + ITaskItem excludedItem; + + var template = new ConfigPriTemplate(); + template.SolutionName = SolutionName; + template.CompileItems = toCompile; + template.CompileDirs = ExtractDirectories(template.CompileItems); + template.IncludeItems = FilterByExtension(IncludeItems, new[] { ".h", ".hpp", ".hxx", ".h++", ".hh" }, new[] { "precompiled.h", "precompiled.hpp", "stdafx.h", "src\\precompiled.h", "src\\precompiled.hpp", "src\\stdafx.h" }, out excludedHeader); + template.IncludeDirs = ExtractDirectories(template.IncludeItems); + template.PrecompiledHeaderName = excludedHeader != null ? excludedHeader.ItemSpec : null; + template.QmlItems = FilterByExtension(IncludeItems, new[] {".qml", ".js", ".qs"}, null, out excludedItem); + template.QmlDirs = ExtractDirectories(template.QmlItems); + template.LinkItem = linkInfo; + template.AdditionalIncludeDirs = TemplateHelper.GetRootedDirs(ProjectDir, TemplateHelper.MergeArrays(AdditionalIncludeDirectories, additionalInfo != null ? additionalInfo.GetMetadata("AdditionalIncludeDirectories").Split(';') : null)); + template.AdditionalLibraryDirs = TemplateHelper.GetRootedDirs(ProjectDir, TemplateHelper.MergeArrays(AdditionalLibraryDirectories, linkInfo != null ? linkInfo.GetMetadata("AdditionalLibraryDirectories").Split(';') : null)); + template.PreprocessorDefinitions = additionalInfo != null ? additionalInfo.GetMetadata("PreprocessorDefinitions").Split(';') : null; + template.UndefinePreprocessorDefinitions = additionalInfo != null ? additionalInfo.GetMetadata("UndefinePreprocessorDefinitions").Split(';') : null; + + outputFile.Write(template.TransformText()); + } + } + + private void GenerateRegularMakefile() + { + // generate list of items to compile: + ITaskItem[] toCompile; + ITaskItem[] toCompileAsC; + ITaskItem[] toCompileAsCpp; + SplitCompileItems(CompileItems, ExcludeDirectories, out toCompile, out toCompileAsC, out toCompileAsCpp); + + using (var outputFile = new StreamWriter(IntDir + "makefile")) + { + var template = new MakefileTemplate(); + template.ConfigurationType = ConfigurationType; + template.SolutionName = SolutionName; + template.OutDir = Path.IsPathRooted(OutDir) ? OutDir : ProjectDir + OutDir; + template.ProjectDir = ProjectDir; + template.TargetFile = TargetName + (TargetExtension != ".exe" ? TargetExtension : string.Empty); + template.TargetBarFile = ConfigurationType == "Application" ? TargetName + ".bar" : string.Empty; + template.TargetCompiler = TargetCompiler; + template.TargetCompilerVersion = TargetCompilerVersion; + template.CompilerFlags = string.Concat("-V\"", TargetCompilerVersion, + string.IsNullOrEmpty(TargetCompilerVersion) || string.IsNullOrEmpty(TargetCompiler) ? string.Empty : ",", + TargetCompiler, "\""); + template.CompileItems = toCompile; + template.CompileItemsAsC = toCompileAsC; + template.CompileItemsAsCpp = toCompileAsCpp; + template.LinkItem = LinkItems != null && LinkItems.Length > 0 ? LinkItems[0] : null; + template.AdditionalIncludeDirectories = TemplateHelper.GetRootedDirs(ProjectDir, AdditionalIncludeDirectories); + template.AdditionalLibraryDirectories = TemplateHelper.GetRootedDirs(ProjectDir, AdditionalLibraryDirectories); + + outputFile.Write(template.TransformText()); + } + } + + private static void SplitCompileItems(ITaskItem[] compileItems, string[] excludedDirectories, out ITaskItem[] toCompile, out ITaskItem[] toCompileAsC, out ITaskItem[] toCompileAsCpp) + { + if (compileItems == null) + throw new ArgumentNullException("compileItems"); + + var listCompile = new List(); + var listCompileAsC = new List(); + var listCompileAsCpp = new List(); + + excludedDirectories = TemplateHelper.NormalizePaths(excludedDirectories); + foreach (var item in compileItems) + { + var fullPath = TemplateHelper.GetFullPath(item); + + // skip the ones, that are explicitly excluded: + if (!IsExcludedPath(excludedDirectories, fullPath)) + { + listCompile.Add(item); + + // and devide into C vs C++ sets: + if (IsCompileAsC(item)) + listCompileAsC.Add(item); + else + listCompileAsCpp.Add(item); + } + } + + toCompile = listCompile.ToArray(); + toCompileAsC = listCompileAsC.ToArray(); + toCompileAsCpp = listCompileAsCpp.ToArray(); + } + + private static bool IsCompileAsC(ITaskItem item) + { + return item.GetMetadata("CompileAs") == "CompileAsC"; + } + + private static ITaskItem[] FilterByExtension(IEnumerable items, string[] extensions, string[] excludedItemSpecs, out ITaskItem excludedItem) + { + var result = new List(); + + excludedItem = null; + if (items != null) + { + if (extensions != null && extensions.Length > 0) + { + foreach (var item in items) + { + var itemExtension = item.GetMetadata("Extension"); + for (int i = 0; i < extensions.Length; i++) + { + // is the extension matching? + if (string.Compare(itemExtension, extensions[i], StringComparison.OrdinalIgnoreCase) == 0) + { + // is the file excluded? + var index = IndexOf(excludedItemSpecs, item); + if (index >= 0) + { + if (excludedItem == null) + { + excludedItem = item; + } + } + else + { + result.Add(item); + } + break; + } + } + } + } + else + { + result.AddRange(items); + } + } + + return result.ToArray(); + } + + /// + /// Finds index of the matching by ItemSpec item. + /// + private static int IndexOf(string[] itemSpecs, ITaskItem item) + { + if (item == null || itemSpecs == null || itemSpecs.Length == 0) + return -1; + + for(int i = 0; i < itemSpecs.Length; i++) + { + if (string.Compare(itemSpecs[i], item.ItemSpec, StringComparison.OrdinalIgnoreCase) == 0) + { + return i; + } + } + + return -1; + } + + private static string[] ExtractDirectories(IEnumerable items) + { + var result = new List(); + + if (items != null) + { + foreach (var item in items) + { + var path = Path.GetDirectoryName(item.ItemSpec); + if (!result.Contains(path)) + { + result.Add(path); + } + } + } + + return result.ToArray(); + } + + /// + /// Check to see if path is in the excluded list. + /// + private static bool IsExcludedPath(IEnumerable excludedDirectories, string path) + { + if (string.IsNullOrEmpty(path)) + return false; + + if (excludedDirectories != null) + { + var fullPath = TemplateHelper.NormalizePath(path); + + foreach (string excludedDir in excludedDirectories) + { + if (fullPath.StartsWith(excludedDir, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + } + return false; + } + + private void NotifyMessage(BuildMessageEventArgs e) + { + if (e != null) + { + try + { + if (BuildEngine != null) + { + BuildEngine.LogMessageEvent(e); + } + } + catch (Exception ex) + { + Trace.WriteLine(ex.Message, "BlackBerry.Build.Log"); + } + } + } + } +} diff --git a/src_vs2012/BuildTasks/GetAppInfo.cs b/src_vs2012/BuildTasks/GetAppInfo.cs new file mode 100644 index 00000000..f8d6b7e3 --- /dev/null +++ b/src_vs2012/BuildTasks/GetAppInfo.cs @@ -0,0 +1,119 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.IO; +using System.Xml; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace BlackBerry.BuildTasks +{ + /// + /// MSBuid Task to retrieve the application info + /// + public sealed class GetAppInfo : Task + { + #region Member Variables and Constants + private string _projectDir; + private string _appName; + private string _barDescriptorPath = ""; + private string _appId; + #endregion + + /// + /// Execute the MSBuild Task + /// + public override bool Execute() + { + string rootedOutDir = (Path.IsPathRooted(_barDescriptorPath)) ? _barDescriptorPath : _projectDir + _barDescriptorPath; + XmlReader reader = XmlReader.Create(rootedOutDir); + reader.ReadToFollowing("id"); + _appId = reader.ReadElementContentAsString(); + + return true; + } + + /// + /// Getter/Setter for the ApplicationDescriptorXml property + /// + public string ApplicationDescriptorXml + { + set + { + _barDescriptorPath = value; + } + get + { + return _barDescriptorPath; + } + } + + /// + /// Getter/Setter for the ProjectDir property + /// + public string ProjectDir + { + set + { + _projectDir = value; + } + get + { + return _projectDir; + } + } + + /// + /// Getter/Setter for the AppName property + /// + public string AppName + { + set + { + _appName = value; + + if (_barDescriptorPath == "") + { + // Default location of bar-descriptor file, if not specified in the Properties Configurations. + _barDescriptorPath = "BlackBerry-" + _appName + "\\bar-descriptor.xml"; + if (!File.Exists(_barDescriptorPath)) + { + // Just to support the default locations of bar-descriptor from previous versions of the plug-in. + _barDescriptorPath = _appName + "_barDescriptor\\bar-descriptor.xml"; + if (!File.Exists(_barDescriptorPath)) + { + _barDescriptorPath = "bar-descriptor.xml"; + } + } + } + } + get + { + return _appName; + } + } + + /// + /// Getter/Setter for the AppId property + /// + [Output] + public string AppId + { + get + { + return _appId; + } + } + } +} diff --git a/src_vs2012/BuildTasks/Helpers/ProcessSetupHelper.cs b/src_vs2012/BuildTasks/Helpers/ProcessSetupHelper.cs new file mode 100644 index 00000000..9b36a87a --- /dev/null +++ b/src_vs2012/BuildTasks/Helpers/ProcessSetupHelper.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; + +namespace BlackBerry.BuildTasks.Helpers +{ + /// + /// Helper class for configuring processes to start. + /// + static class ProcessSetupHelper + { + /// + /// Adds basic set of BlackBerry-build-system specific variables. + /// + public static void Update(StringDictionary environment, string qnxHost, string qnxTarget) + { + if (environment == null) + throw new ArgumentNullException("environment"); + + // set some BlackBerry default environment variables: + // (idea taken from any bbndk-env_xxx.bat script) + if (string.IsNullOrEmpty(qnxHost)) + qnxHost = Environment.GetEnvironmentVariable("QNX_HOST"); + if (string.IsNullOrEmpty(qnxTarget)) + qnxTarget = Environment.GetEnvironmentVariable("QNX_TARGET"); + + if (qnxHost != null) + { + environment["QNX_HOST"] = qnxHost.Replace('\\', '/'); + environment["PATH"] = string.Concat(Path.Combine(qnxHost, "usr", "bin"), ";", environment["PATH"]); + } + if (qnxTarget != null) + { + qnxTarget = qnxTarget.Replace('\\', '/'); + environment["QNX_TARGET"] = qnxTarget; + environment["MAKEFLAGS"] = "-I" + qnxTarget + "/usr/include"; + } + } + + /// + /// Adds basic set of BlackBerry-build-system specific variables. + /// + public static string[] Update(string[] environment, string qnxHost, string qnxTarget) + { + var result = new List(); + + // set some BlackBerry default environment variables: + // (idea taken from any bbndk-env_xxx.bat script) + + string path = null; + + if (environment != null) + { + foreach (var env in environment) + { + if (env.StartsWith("PATH=", StringComparison.OrdinalIgnoreCase)) + { + path = env.Substring(5); + continue; + } + + if (env.StartsWith("QNX_HOST=", StringComparison.OrdinalIgnoreCase)) + { + qnxHost = env.Substring(9); + continue; + } + + if (env.StartsWith("QNX_TARGET=", StringComparison.OrdinalIgnoreCase)) + { + qnxTarget = env.Substring(11); + continue; + } + + if (env.StartsWith("MAKEFLAGS=", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + result.Add(env); + } + } + + if (string.IsNullOrEmpty(qnxHost)) + qnxHost = Environment.GetEnvironmentVariable("QNX_HOST"); + if (string.IsNullOrEmpty(qnxTarget)) + qnxTarget = Environment.GetEnvironmentVariable("QNX_TARGET"); + + if (!string.IsNullOrEmpty(qnxHost)) + { + result.Add("QNX_HOST=" + qnxHost.Replace('\\', '/')); + + if (string.IsNullOrEmpty(path)) + path = Environment.GetEnvironmentVariable("PATH"); + path = string.Concat(Path.Combine(qnxHost, "usr", "bin"), ";", path); + } + + if (!string.IsNullOrEmpty(qnxTarget)) + { + qnxTarget = qnxTarget.Replace('\\', '/'); + result.Add("QNX_TARGET=" + qnxTarget); + result.Add("MAKEFLAGS=-I" + qnxTarget + "/usr/include"); + } + + if (!string.IsNullOrEmpty(path)) + { + result.Add("PATH=" + path); + } + + return result.ToArray(); + } + } +} diff --git a/src_vs2012/BuildTasks/Helpers/TemplateHelper.cs b/src_vs2012/BuildTasks/Helpers/TemplateHelper.cs new file mode 100644 index 00000000..d906c519 --- /dev/null +++ b/src_vs2012/BuildTasks/Helpers/TemplateHelper.cs @@ -0,0 +1,393 @@ +using System; +using System.Collections.Generic; +using System.IO; +using BlackBerry.NativeCore; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks.Helpers +{ + /// + /// Helper methods for template-generator. + /// + static class TemplateHelper + { + /// + /// Interface implemented by template-generator to let the helper class perform more complex actions. + /// + public interface IWriter + { + void Write(string text); + void WriteLine(string text); + } + + /// + /// Checks, if path should be escaped. + /// + public static bool ShouldEscape(string text) + { + return !string.IsNullOrEmpty(text) && text.IndexOf(' ') > 0; + } + + public static string Normalize(string path) + { + return string.IsNullOrEmpty(path) ? null : path.Replace('\\', '/'); + } + + /// + /// Gets the list of rooted directories. All relative ones are expanded using specified project's location. + /// + public static string[] GetRootedDirs(string projectDir, string[] items) + { + if (string.IsNullOrEmpty(projectDir)) + { + if (items == null) + return new string[0]; + return items; + } + + if (items == null) + return new string[0]; + + var result = new string[items.Length]; + + // prepend ProjectDir to relative paths: + for (int i = 0; i < items.Length; i++) + { + if (!string.IsNullOrEmpty(items[i]) && !items[i].StartsWith("\\\\") && items[i].IndexOf(':') < 0) + result[i] = Normalize(projectDir + items[i]); + else + result[i] = Normalize(items[i]); + } + + return result; + } + + /// + /// Writes a collection of space-separated items, where each has given prefix. + /// + public static void WriteCollection(IWriter output, IEnumerable items, string prefix, string separator) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (items != null) + { + foreach (var item in items) + { + if (!string.IsNullOrWhiteSpace(item)) + { + output.Write(prefix); + + if (ShouldEscape(item)) + { + output.Write("\""); + output.Write(item); + output.Write("\""); + } + else + { + output.Write(item); + } + + if (!string.IsNullOrEmpty(separator)) + { + output.Write(separator); + } + } + } + } + } + + /// + /// Normalizes the paths, so they are correctly processed by makefile. + /// + public static string[] NormalizePaths(ICollection collection) + { + if (collection == null) + return null; + + var result = new List(); + + foreach (var item in collection) + { + if (!string.IsNullOrEmpty(item)) + { + result.Add(NormalizePath(item)); + } + } + + return result.ToArray(); + } + + /// + /// Normalizes the single path. + /// + public static string NormalizePath(string path) + { + return Normalize(Path.GetFullPath(path)); + } + + /// + /// Gets the full path to the item. + /// + public static string GetFullPath(ITaskItem item) + { + return Normalize(item.GetMetadata("FullPath")); + } + + /// + /// Gets the short name of the file. + /// + public static string GetFullPath8Dot3(ITaskItem item) + { + var path = item.GetMetadata("FullPath"); + return Normalize(NativeMethods.GetShortPathName(path)); + } + + /// + /// Writes a collection of specified ITaskItems, using their 8.3-style full paths, where each item has specified prefix and suffix. + /// + public static void Write8Dot3Collection(IWriter output, ITaskItem[] items, string prefix, string suffix) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (items != null && items.Length > 0) + { + int lastIndex = items.Length - 1; + + // print items: + for (int i = 0; i < lastIndex; i++) + { + output.Write(prefix); + output.Write(GetFullPath8Dot3(items[i])); + output.Write(suffix); + output.WriteLine(" \\"); + } + + // print last item without 'move to next line char': + output.Write(prefix); + output.Write(GetFullPath8Dot3(items[lastIndex])); + output.WriteLine(suffix); + } + } + + /// + /// Writes a collection of specified ITaskItem names, where each item has specified prefix and suffix. + /// + public static void WriteNameCollection(IWriter output, ITaskItem[] items, string prefix, string suffix) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (items != null && items.Length > 0) + { + int lastIndex = items.Length - 1; + + // print items: + for (int i = 0; i < lastIndex; i++) + { + output.Write(prefix); + output.Write(items[i].GetMetadata("Filename")); + output.Write(suffix); + output.WriteLine(" \\"); + } + + // print last item without suffix: + output.Write(prefix); + output.Write(items[lastIndex].GetMetadata("Filename")); + output.WriteLine(suffix); + } + } + + private static bool IsDirSeparator(char c) + { + return c == '\\' || c == '/'; + } + + /// + /// Writes path made of segments into the output. Segment can be several folder names. + /// + public static void WritePath(IWriter output, params string[] segments) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (segments != null) + { + bool trailing = false; + foreach (var s in segments) + { + if (string.IsNullOrEmpty(s)) + { + continue; + } + + if (trailing) + { + if (IsDirSeparator(s[0])) + { + output.Write(s.Substring(1)); + if (s.Length > 1) + trailing = IsDirSeparator(s[s.Length - 1]); + continue; + } + } + output.Write(s); + trailing = IsDirSeparator(s[s.Length - 1]); + } + } + } + + /// + /// Writes a collection of relative paths from specified task-items. Each can have prefix and suffix. + /// + public static void WriteRelativePaths(IWriter output, ITaskItem[] items, string prefix, string suffix) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (items != null && items.Length > 0) + { + int lastIndex = items.Length - 1; + + // print items: + for (int i = 0; i < lastIndex; i++) + { + WritePath(output, prefix, Normalize(items[i].ItemSpec), suffix); + output.WriteLine(" \\"); + } + + // print last item without 'move to next line char': + WritePath(output, prefix, Normalize(items[lastIndex].ItemSpec), suffix); + output.WriteLine(string.Empty); + } + } + + public static void WriteRelativePaths(IWriter output, string[] items, string prefix, string suffix) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (items != null && items.Length > 0) + { + int lastIndex = items.Length - 1; + + // print items: + for (int i = 0; i < lastIndex; i++) + { + WritePath(output, prefix, Normalize(items[i]), suffix); + output.WriteLine(" \\"); + } + + // print last item without 'move to next line char': + WritePath(output, prefix, Normalize(items[lastIndex]), suffix); + output.WriteLine(string.Empty); + } + } + + public static void WriteRelativePathsTuple(IWriter output, string[] items1, string[] items2, string prefix, string suffix) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (items1 != null && items1.Length > 0) + { + if (items2 == null || items2.Length == 0) + { + WriteRelativePaths(output, items1, prefix, suffix); + return; + } + + int lastIndex1 = items1.Length - 1; + int lastIndex2 = items2.Length - 1; + + // print items: + for (int i = 0; i <= lastIndex1; i++) + { + for (int j = 0; j <= lastIndex2; j++) + { + WritePath(output, prefix, Normalize(items1[i]), "/", items2[j], suffix); + + if (i != lastIndex1 || j != lastIndex2) + { + output.WriteLine(" \\"); + } + else + { + output.WriteLine(string.Empty); + } + } + } + } + } + + public static bool HasDependencyLibrariesReferences(ITaskItem linkItem) + { + return linkItem != null && !string.IsNullOrEmpty(linkItem.GetMetadata("AdditionalDependencies")); + } + + public static void WriteDependencyLibrariesReferences(IWriter output, ITaskItem linkItem) + { + if (output == null) + throw new ArgumentNullException("output"); + + if (linkItem != null) + { + // Visual Studio doesn't have separate lists for static vs. dynamic dependencies. + // To differentiate between the two, include the extension in the list - `.a for static, `.so for dynamic. + // If no extension is included in the name it will be treated as the same type + // as the last declared type, and the default type is static. This is the way qcc would work + // if you were using it from the command line with the "-Bstatic" and "-Bdynamic" flags. + + var libs = linkItem.GetMetadata("AdditionalDependencies").Split(';'); + for (int i = 0; i < libs.Length; i++) + { + if (libs[i].EndsWith(".so")) + { + output.Write("-Bdynamic -l"); + output.Write(libs[i].Substring(0, libs[i].Length - 3)); + } + else if (libs[i].EndsWith(".a")) + { + output.Write("-Bstatic -l"); + output.Write(libs[i].Substring(0, libs[i].Length - 2)); + } + else + { + if (!string.IsNullOrEmpty(libs[i])) + { + output.Write("-l"); + output.Write(libs[i]); + } + } + + output.Write(" "); + } + } + } + + /// + /// Merges arrays into one. + /// + public static string[] MergeArrays(string[] a1, string[] a2) + { + if (a1 == null || a1.Length == 0) + return a2; + if (a2 == null || a2.Length == 0) + return a1; + + var result = new string[a1.Length + a2.Length]; + for (int i = 0; i < a1.Length; i++) + { + result[i] = a1[i]; + } + for (int i = 0, j = a1.Length; i < a2.Length; i++, j++) + { + result[j] = a2[i]; + } + + return result; + } + } +} diff --git a/src_vs2012/BuildTasks/MakeAllAndFormatOutputMessages.cs b/src_vs2012/BuildTasks/MakeAllAndFormatOutputMessages.cs new file mode 100644 index 00000000..24538c57 --- /dev/null +++ b/src_vs2012/BuildTasks/MakeAllAndFormatOutputMessages.cs @@ -0,0 +1,589 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using BlackBerry.BuildTasks.Helpers; +using BlackBerry.NativeCore; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks +{ + /// + /// Cancelable MSBuild Task for Running the Make file for the build. + /// + public sealed class MakeAllAndFormatOutputMessages : ICancelableTask + { + /// + /// Type of parsed messages from makefile's (qcc's) output/error streams. + /// + public enum MessageType + { + Nothing, + Message, + Warning, + Error + } + + #region Member Variables and Constants + + private string _projectDir; + private string _outDir; + + private Process _process; + + private string _processorCount; + private int _errorCount; + + private static readonly Regex UndefinedReferenceLineRegex = new Regex(@"(\(\s*\d+\s*\)|:\s*\d+\s*:)"); + private bool _isCascadesProject; + private string _makefileSourceReferencePath; + + #endregion + + /// + /// Getter/Setter for the BuildEngine property + /// + public IBuildEngine BuildEngine + { + get; + set; + } + + /// + /// Getter/Setter for the HostObject property + /// + public ITaskHost HostObject + { + get; + set; + } + + /// + /// Getter/Setter for CompileItems property + /// + public ITaskItem[] CompileItems + { + set; + get; + } + + public string ConfigurationType + { + get; + set; + } + + public string ConfigurationAppType + { + get; + set; + } + + public string QnxHost + { + get; + set; + } + + public string QnxTarget + { + get; + set; + } + + public string MakefileTargetName + { + get; + set; + } + + /// + /// Getter/Setter for the number of processors property. + /// + public string ProcessorCount + { + get + { + if (_processorCount != null) + return _processorCount; + + _processorCount = Environment.ProcessorCount.ToString(); + return _processorCount; + } + set { _processorCount = value; } + } + + private bool IsMultiProcessorsBuild() + { + foreach (ITaskItem compileItem in CompileItems) + { + bool result; + + // Get the metadata we need from this compile item. + return bool.TryParse(compileItem.GetMetadata("MultiProcess"), out result) && result; + } + + return false; + } + + [Required] + public string ProjectDir + { + set { _projectDir = value.Replace('\\', '/'); } + get { return _projectDir; } + } + + [Required] + public string OutDir + { + set { _outDir = value.Replace('\\', '/'); } + get { return _outDir; } + } + + [Required] + public string ToolsPath + { + get; + set; + } + + /// + /// Perform Task Execution + /// + /// Return true on successful task completion + public bool Execute() + { + _isCascadesProject = ConfigurationAppType == "Cascades"; + _errorCount = 0; + + try + { + var makeArgs = string.Concat(IsMultiProcessorsBuild() ? " -j" + ProcessorCount : string.Empty, + !string.IsNullOrEmpty(MakefileTargetName) ? " " : string.Empty, MakefileTargetName); + var args = string.Concat("/c \"", ToolsPath, "\\make\"", makeArgs); + + NotifyMessage(string.Concat("Building: make", makeArgs)); + + ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe", args); + + // set some BlackBerry default environment variables: + // (taken from any bbndk-env_xxx.bat script) + ProcessSetupHelper.Update(startInfo.EnvironmentVariables, QnxHost, QnxTarget); + + // Set UseShellExecute to false for redirection. + startInfo.UseShellExecute = false; + + // The following commands are needed to redirect the standard and error outputs. + // These streams are read asynchronously using an event handler. + startInfo.RedirectStandardOutput = true; + startInfo.RedirectStandardError = true; + + // Setting the working directory, if we use makefiles generated by the VSNDK plugin + // they all are placed inside the output dir, however the ones for Cascades Application + // and custom is supposed to be located next to the project: + if (ConfigurationAppType == "Cascades" || ConfigurationAppType == "Custom") + { + startInfo.WorkingDirectory = ProjectDir; + _makefileSourceReferencePath = ProjectDir.Replace('/', '\\'); + } + else + { + string rootedOutDir = Path.IsPathRooted(OutDir) ? OutDir : ProjectDir + OutDir; + startInfo.WorkingDirectory = rootedOutDir; + _makefileSourceReferencePath = null; // NOTE: the 'Regular' type of builds contains full-paths already, so no need to process them + } + + // Do not create the black window. + startInfo.CreateNoWindow = true; + + // Create a process and assign its ProcessStartInfo + _process = new Process(); + _process.StartInfo = startInfo; + + // Set ours events handlers to asynchronously read the standard and error outputs. + _process.OutputDataReceived += StandardOutputHandler; + _process.ErrorDataReceived += ErrorOutputHandler; + + // Start the process + _process.Start(); + + // Start the asynchronous read of the standard and error output stream. + _process.BeginOutputReadLine(); + _process.BeginErrorReadLine(); + + do + { + Application.DoEvents(); + + // Wait until finished + // This code is correct, don't remove it. WaitForExit freezes the IDE while waiting for the end of the build process. + // With this loop and the time out, the IDE won't be frozen enabling the build process to be cancelled. + } + while (!_process.WaitForExit(100)); + _process = null; + } + catch (Exception ex) + { + _process = null; + Console.WriteLine("Failed to execute make all. Reason: " + ex.Message); + return false; + } + + // build succeeded, when no errors printed: + return _errorCount == 0; + } + + /// + /// Parses the standard output and presents its content to upper layer. + /// + public static MessageType ProcessStandardOutput(string text, out string message) + { + if (!string.IsNullOrEmpty(text)) + { + message = text; + return MessageType.Message; + } + + message = null; + return MessageType.Nothing; + } + + public static MessageType ProcessErrorOutput(string text, out string message, out string fileName, out int line, out int column) + { + if (!string.IsNullOrEmpty(text)) + { + // send build output to the Output Window and to the ErrorList window: + int separatorStart = text.IndexOf(": error:"); + if (separatorStart > 0) + { + fileName = ExtractFileName(text, separatorStart, out line, out column); + message = text.Substring(separatorStart + 9); + return MessageType.Error; + } + + separatorStart = text.IndexOf(": fatal error:"); + if (separatorStart > 0) + { + fileName = ExtractFileName(text, separatorStart, out line, out column); + message = text.Substring(separatorStart + 15); + return MessageType.Error; + } + + separatorStart = text.IndexOf(": warning:"); + if (separatorStart > 0) + { + fileName = ExtractFileName(text, separatorStart, out line, out column); + message = text.Substring(separatorStart + 11); + return MessageType.Warning; + } + + separatorStart = text.IndexOf(": note:"); + if (separatorStart > 0) + { + fileName = ExtractFileName(text, separatorStart, out line, out column); + message = text.Substring(separatorStart + 7); + return MessageType.Warning; + } + + if (text.Contains("undefined reference")) + { + return ProcessUndefinedReference(text, out message, out fileName, out line, out column); + } + + fileName = null; + line = 0; + column = 0; + message = text; + return MessageType.Message; + } + + fileName = null; + line = 0; + column = 0; + message = null; + return MessageType.Nothing; + } + + /// + /// Extracts file name from specified text with additional info if available. + /// + public static string ExtractFileName(string text, out int line, out int column) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException("text"); + + return ExtractFileName(text, text.Length, out line, out column); + } + + /// + /// Extracts file name from specified text with additional info if available. + /// + private static string ExtractFileName(string text, int length, out int line, out int column) + { + var extendedInfoStartAt = text.IndexOf('(', 0, length); + char separator; + + // check if line and column are specified in brackets: + if (extendedInfoStartAt < 0) + { + extendedInfoStartAt = length > 2 ? text.IndexOf(':', 2, length - 2) : -1; // since 2 as it might be a drive letter separator inside path + + // check if using ':line:column' format: + if (extendedInfoStartAt < 0) + { + line = 0; + column = 0; + return PostProcessPath(text.Substring(0, length)); + } + + ////////////////////////////// + // Format: :line:column + separator = ':'; + } + else + { + ////////////////////////////// + // Format: (line,column) + separator = ','; + } + + var fileName = text.Substring(0, extendedInfoStartAt); + var separatorAt = text.IndexOf(separator, extendedInfoStartAt + 1, length - extendedInfoStartAt - 1); + var extendedInfoEndAt = text.IndexOf(')', extendedInfoStartAt + 1, length - extendedInfoStartAt - 1); + + // there is only line provided: + if (separatorAt < 0) + { + var lineText = extendedInfoEndAt < 0 + ? text.Substring(extendedInfoStartAt + 1, length - extendedInfoStartAt - 1) + : text.Substring(extendedInfoStartAt + 1, extendedInfoEndAt - extendedInfoStartAt - 1); + + int.TryParse(lineText, out line); + column = 1; + } + else + { + var lineText = text.Substring(extendedInfoStartAt + 1, separatorAt - extendedInfoStartAt - 1); + var columnText = extendedInfoEndAt < 0 + ? text.Substring(separatorAt + 1, length - separatorAt - 1) + : text.Substring(separatorAt + 1, extendedInfoEndAt - separatorAt - 1); + + int.TryParse(lineText, out line); + int.TryParse(columnText, out column); + } + + return PostProcessPath(fileName); + } + + private static string PostProcessPath(string fileName) + { + if (string.IsNullOrEmpty(fileName)) + return string.Empty; + + return NativeMethods.GetLongPathName(fileName.Trim()); + } + + private static MessageType ProcessUndefinedReference(string text, out string message, out string fileName, out int line, out int column) + { + var match = UndefinedReferenceLineRegex.Match(text); + + if (match.Success) + { + var lineText = match.Value.Substring(1, match.Value.Length - 2).Trim(); + int.TryParse(lineText, out line); + + fileName = PostProcessPath(text.Substring(0, match.Index).TrimEnd(':', ' ', '\t')); + message = text.Substring(match.Index + match.Length + 1).Trim(); + } + else + { + line = 0; + + int separatorStartAt = text.IndexOf(':'); + if (separatorStartAt < 0) + { + fileName = null; + message = text.Trim(); + } + else + { + fileName = PostProcessPath(text.Substring(0, separatorStartAt)); + + int separatorEndAt = text.IndexOf(':', separatorStartAt + 1); + message = text.Substring((separatorEndAt < 0 ? separatorStartAt : separatorEndAt) + 1).Trim(); + } + } + column = 1; + + return MessageType.Error; + } + + /// + /// Standard Output Event Handler + /// + /// Sending Process + /// Output Text + private void StandardOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) + { + string message; + + if (ProcessStandardOutput(outLine.Data, out message) != MessageType.Nothing) + { + NotifyMessage(message); + } + } + + /// + /// Error Output Event Handler + /// + /// Sending process + /// Error Message + private void ErrorOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) + { + string fileName; + int line; + int column; + string message; + + var type = ProcessErrorOutput(outLine.Data, out message, out fileName, out line, out column); + if (type != MessageType.Nothing) + { + switch (type) + { + case MessageType.Message: + NotifyMessage(message); + break; + case MessageType.Warning: + NotifyWarning(message, fileName, line, column); + break; + case MessageType.Error: + //NotifyMessage(outLine.Data); + NotifyError(message, fileName, line, column); + _errorCount++; + break; + } + } + } + + #region Notifications + + private void NotifyMessage(string message) + { + if (!string.IsNullOrEmpty(message) && BuildEngine != null) + { + try + { + BuildEngine.LogMessageEvent(new BuildMessageEventArgs(message, string.Empty, string.Empty, MessageImportance.High)); + } + catch (Exception ex) + { + Trace.WriteLine(ex.Message, "BlackBerry.Build.Log"); + } + } + } + + private void NotifyWarning(string message, string fileName, int line, int column) + { + if (!string.IsNullOrEmpty(message) && BuildEngine != null) + { + try + { +#if PLATFORM_VS2010 + // PH: somehow in VS2010 the column count starts from 0, not 1 as the whole code assumes: + column--; +#endif + BuildEngine.LogWarningEvent(new BuildWarningEventArgs(string.Empty, string.Empty, GetProjectAwareFileName(fileName), line, column, 0, 0, message, string.Empty, string.Empty)); + } + catch (Exception ex) + { + Trace.WriteLine(ex.Message, "BlackBerry.Build.Warning"); + } + } + } + + private void NotifyError(string message, string fileName, int line, int column) + { + if (!string.IsNullOrEmpty(message) && BuildEngine != null) + { + try + { +#if PLATFORM_VS2010 + // PH: somehow in VS2010 the column count starts from 0, not 1 as the whole code assumes: + column--; +#endif + BuildEngine.LogErrorEvent(new BuildErrorEventArgs(string.Empty, string.Empty, GetProjectAwareFileName(fileName), line, column, 0, 0, message, string.Empty, string.Empty)); + } + catch (Exception ex) + { + Trace.WriteLine(ex.Message, "BlackBerry.Build.Error"); + } + } + } + + #endregion + + /// + /// Returns full path to the file within the project. + /// + private string GetProjectAwareFileName(string fileName) + { + if (string.IsNullOrEmpty(fileName)) + return string.Empty; + + // is it a 'Regular' project with full-paths already: + if (string.IsNullOrEmpty(_makefileSourceReferencePath)) + return fileName; + + if (fileName.StartsWith(_makefileSourceReferencePath)) + return fileName.Replace('/', '\\'); + + if (_isCascadesProject) + return Path.Combine(_makefileSourceReferencePath, DropFirstDirectory(fileName.Replace('/', '\\'))); + + // for 'Custom' project type: + return Path.Combine(_makefileSourceReferencePath, fileName.Replace('/', '\\')); + } + + private static string DropFirstDirectory(string path) + { + int at = path.IndexOf('\\'); + if (at < 0) + return path; + + return path.Substring(at + 1); + } + + /// + /// Perform Cancel Code + /// + public void Cancel() + { + try + { + if (_process != null) + { + _process.Kill(); + } + } + catch (Exception ex) + { + NotifyMessage(ex.Message); + } + } + } +} diff --git a/src_vs2012/BuildTasks/PackagerCmdBuilder.cs b/src_vs2012/BuildTasks/PackagerCmdBuilder.cs new file mode 100644 index 00000000..4c231bd7 --- /dev/null +++ b/src_vs2012/BuildTasks/PackagerCmdBuilder.cs @@ -0,0 +1,37 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using Microsoft.Build.Utilities; + +namespace BlackBerry.BuildTasks +{ + sealed class PackagerCmdBuilder : CommandLineBuilder + { + /// + /// Default constructor + /// + public PackagerCmdBuilder() + : base(true) + { + } + + /// + /// Override of IsQuotingRequired function. Always return true. + /// + protected override bool IsQuotingRequired(string parameter) + { + return true; + } + } +} diff --git a/src_vs2012/BuildTasks/Properties/Resources.Designer.cs b/src_vs2012/BuildTasks/Properties/Resources.Designer.cs new file mode 100644 index 00000000..aa4d5141 --- /dev/null +++ b/src_vs2012/BuildTasks/Properties/Resources.Designer.cs @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace BlackBerry.BuildTasks.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BlackBerry.BuildTasks.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to # This file is automatically generated by vs-ndk. + ///# Do not modify this file -- YOUR CHANGES WILL BE ERASED! + ///# + ///# This file must *NOT* be checked in Version Control Systems, + ///# as it contains information specific to your local configuration. + /// + ///# location of the SDK. This is only used by Ant + ///# For customization when using a Version Control System, please read the + ///# header note. + ///sdk.dir={SDKDIR}. + /// + internal static string localproperties_ant_file { + get { + return ResourceManager.GetString("localproperties_ant_file", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tracking command:. + /// + internal static string Native_TrackingCommandMessage { + get { + return ResourceManager.GetString("Native_TrackingCommandMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MSB8016: Can not turn on Unicode output for "{0}". Some Unicode characters will be improperly displayed.. + /// + internal static string TrackedVCToolTask_CreateUnicodeOutputPipeFailed { + get { + return ResourceManager.GetString("TrackedVCToolTask.CreateUnicodeOutputPipeFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Forcing rebuild of all source files due to a change in the command line since the last build.. + /// + internal static string TrackedVCToolTask_RebuildingAllSourcesCommandLineChanged { + get { + return ResourceManager.GetString("TrackedVCToolTask.RebuildingAllSourcesCommandLineChanged", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MSB8014: Forcing a rebuild of all sources due to an error with the tracking logs. {0}. + /// + internal static string TrackedVCToolTask_RebuildingDueToInvalidTLog { + get { + return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLog", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MSB8015: Forcing a rebuild of all source files due to the contents of "{0}" being invalid.. + /// + internal static string TrackedVCToolTask_RebuildingDueToInvalidTLogContents { + get { + return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLogContents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Forcing rebuild of all source files due to missing command tlog "{0}".. + /// + internal static string TrackedVCToolTask_RebuildingNoCommandTLog { + get { + return ResourceManager.GetString("TrackedVCToolTask.RebuildingNoCommandTLog", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Forcing rebuild of source file "{0}" due to a change in the command line since the last build.. + /// + internal static string TrackedVCToolTask_RebuildingSourceCommandLineChanged { + get { + return ResourceManager.GetString("TrackedVCToolTask.RebuildingSourceCommandLineChanged", resourceCulture); + } + } + } +} diff --git a/src/VSNDK.Tasks/Properties/Resources.resx b/src_vs2012/BuildTasks/Properties/Resources.resx similarity index 100% rename from src/VSNDK.Tasks/Properties/Resources.resx rename to src_vs2012/BuildTasks/Properties/Resources.resx diff --git a/src_vs2012/BuildTasks/QccCompiler.cs b/src_vs2012/BuildTasks/QccCompiler.cs new file mode 100644 index 00000000..8d464141 --- /dev/null +++ b/src_vs2012/BuildTasks/QccCompiler.cs @@ -0,0 +1,521 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.Collections.Generic; +using BlackBerry.BuildTasks.Properties; +using Microsoft.Build.CPPTasks; +using Microsoft.Build.Framework; +using System.Collections; + +namespace BlackBerry.BuildTasks +{ + public sealed class QccCompiler : QccTask + { + #region Fields + + // Fields + private ITaskItem[] _preprocessOutput; + + //constant fields + private const string ADDITIONAL_INCLUDEDIRECTORIES = "AdditionalIncludeDirectories"; + private const string PREPROCESSOR_DEFINITIONS = "PreprocessorDefinitions"; + private const string UNDEFINE_PREPROCESSOR_DEFINITION = "UndefinePreprocessorDefinition"; + private const string PREPROCESS_TO_FILE = "PreprocessToFile"; + private const string PREPROCESS_TO_STDOUT = "PreprocessToStdout"; + private const string PREPROCESS_KEEP_COMMENTS = "PreprocessKeepComments"; + private const string RUNTIME_TYPE_INFO = "RuntimeTypeInfo"; + private const string OBJECT_FILE_NAME = "ObjectFileName"; + private const string ANSI = "Ansi"; + + #endregion + + /// + /// QccCompiler default constructor + /// + public QccCompiler() + : base(Resources.ResourceManager) + { + _preprocessOutput = new ITaskItem[0]; + _switchOrderList.Add(ADDITIONAL_INCLUDEDIRECTORIES); + _switchOrderList.Add(ANSI); + _switchOrderList.Add(PREPROCESSOR_DEFINITIONS); + _switchOrderList.Add(UNDEFINE_PREPROCESSOR_DEFINITION); + _switchOrderList.Add(PREPROCESS_TO_FILE); + _switchOrderList.Add(PREPROCESS_TO_STDOUT); + _switchOrderList.Add(PREPROCESS_KEEP_COMMENTS); + _switchOrderList.Add(RUNTIME_TYPE_INFO); + _switchOrderList.Add(OBJECT_FILE_NAME); + _switchOrderList.Add(SOURCES); + } + + #region Overrides + + /// + /// Getter/Setter for the AlwaysAppend property + /// + protected override string AlwaysAppend + { + get + { + return LinkSharedLibrary ? "-c -shared" : "-c"; + } + } + + /// + /// Getter/Setter for the AttributeFileTracking property + /// + public override bool AttributeFileTracking + { + get + { + return true; + } + } + + /// + /// Getter/Setter for the TrackedInputFiles property + /// + protected override ITaskItem[] TrackedInputFiles + { + get + { + return Sources; + } + } + + /// + /// Execute the specified tool for building + /// + /// + /// + /// + /// + protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) + { + foreach (ITaskItem item in Sources) + { + string source = item.ItemSpec; + base.LogEventsFromTextOutput(source, MessageImportance.High); + } + return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); + } + + /// + /// Getter/Setter for the WriteTLogNames property + /// + protected override string[] WriteTLogNames + { + get + { + return new[] { "qcc_compiler.write.1.tlog", "qcc_compiler.*.write.1.tlog" }; + } + } + + /// + /// Getter/Setter for the CommandTLogName property + /// + protected override string CommandTLogName + { + get + { + return "qcc_compiler.command.1.tlog"; + } + } + + /// + /// Getter/Setter for the ReadTLogNames property + /// + protected override string[] ReadTLogNames + { + get + { + return new[] { "qcc_compiler.read.1.tlog", "qcc_compiler.*.read.1.tlog" }; + } + } + #endregion + + #region Properties + + /// + /// GetterSetter for the AdditionalIncludeDirectories property. + /// + public string[] AdditionalIncludeDirectories + { + get + { + if (IsPropertySet(ADDITIONAL_INCLUDEDIRECTORIES)) + { + return ActiveToolSwitches[ADDITIONAL_INCLUDEDIRECTORIES].StringList; + } + return null; + } + set + { + ActiveToolSwitches.Remove(ADDITIONAL_INCLUDEDIRECTORIES); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) + { + DisplayName = "Additional Include Directories", + Description = "Specifies one or more directories to add to the include path; separate with semi-colons if more than one. (-I[path])", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-I", + Name = ADDITIONAL_INCLUDEDIRECTORIES, + StringList = value + }; + ActiveToolSwitches.Add(ADDITIONAL_INCLUDEDIRECTORIES, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the Ansi property + /// + public bool Ansi + { + get + { + return (IsPropertySet(ANSI) && ActiveToolSwitches[ANSI].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(ANSI); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Compile ANSI code", + Description = "Compile ansi code", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-ansi", + Name = ANSI, + BooleanValue = value + }; + ActiveToolSwitches.Add(ANSI, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the MinimalRebuild property + /// + public bool MinimalRebuild + { + get + { + return (IsPropertySet("MinimalRebuild") && ActiveToolSwitches["MinimalRebuild"].BooleanValue); + } + set + { + ActiveToolSwitches.Remove("MinimalRebuild"); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Enable Minimal Rebuild", + Description = "Enables minimal rebuild, which determines whether C++ source files that include changed C++ class definitions (stored in header (.h) files) need to be recompiled.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "/Gm", + ReverseSwitchValue = "/Gm-", + Name = "MinimalRebuild", + BooleanValue = value + }; + ActiveToolSwitches.Add("MinimalRebuild", switch2); + AddActiveSwitchToolValue(switch2); + switch2.Overrides.AddLast(new KeyValuePair("Gm", "Gm-")); + switch2.Overrides.AddLast(new KeyValuePair("Gm-", "Gm")); + } + } + + /// + /// Getter/Setter for the ObjectFileName property + /// + public string ObjectFileName + { + get + { + if (IsPropertySet(OBJECT_FILE_NAME)) + { + return ActiveToolSwitches[OBJECT_FILE_NAME].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(OBJECT_FILE_NAME); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) + { + DisplayName = "Object File Name", + Description = "Specifies a name to override the default object file name; can be file or directory name. (-o[name])", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-o", + Name = OBJECT_FILE_NAME, + Value = value + }; + ActiveToolSwitches.Add(OBJECT_FILE_NAME, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the ExpandAttributedSource property + /// + public bool ExpandAttributedSource + { + get + { + return (IsPropertySet("ExpandAttributedSource") && ActiveToolSwitches["ExpandAttributedSource"].BooleanValue); + } + set + { + ActiveToolSwitches.Remove("ExpandAttributedSource"); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Expand Attributed Source", + Description = "Create listing file with expanded attributes injected into source file. (/Fx)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "/Fx", + Name = "ExpandAttributedSource", + BooleanValue = value + }; + ActiveToolSwitches.Add("ExpandAttributedSource", switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the FavorSizeOrSpeed property + /// + public string FavorSizeOrSpeed + { + get + { + if (IsPropertySet("FavorSizeOrSpeed")) + { + return ActiveToolSwitches["FavorSizeOrSpeed"].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove("FavorSizeOrSpeed"); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Favor Size Or Speed", + Description = "Whether to favor code size or code speed; 'Global Optimization' must be turned on. (/Ot, /Os)", + ArgumentRelationList = new ArrayList() + }; + string[][] switchMap = + { + new[] { "Size", "/Os" }, + new[] { "Speed", "/Ot" }, + new[] { "Neither", "" } + }; + switch2.SwitchValue = ReadSwitchMap("FavorSizeOrSpeed", switchMap, value); + switch2.Name = "FavorSizeOrSpeed"; + switch2.Value = value; +#if PLATFORM_VS2010 + switch2.MultiValues = true; +#else + switch2.MultipleValues = true; +#endif + ActiveToolSwitches.Add("FavorSizeOrSpeed", switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the PreprocessKeepComments property + /// + public bool PreprocessKeepComments + { + get + { + return (IsPropertySet(PREPROCESS_KEEP_COMMENTS) && ActiveToolSwitches[PREPROCESS_KEEP_COMMENTS].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(PREPROCESS_KEEP_COMMENTS); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Keep Comments", + Description = "Suppresses comment strip from source code; requires that one of the 'Preprocessing' options be set. (-C)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-C", + Name = PREPROCESS_KEEP_COMMENTS, + BooleanValue = value + }; + ActiveToolSwitches.Add(PREPROCESS_KEEP_COMMENTS, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for hte PreprocessorDefinitions property + /// + public string[] PreprocessorDefinitions + { + get + { + if (IsPropertySet(PREPROCESSOR_DEFINITIONS)) + { + return ActiveToolSwitches[PREPROCESSOR_DEFINITIONS].StringList; + } + return null; + } + set + { + ActiveToolSwitches.Remove(PREPROCESSOR_DEFINITIONS); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) + { + DisplayName = "Preprocessor Definitions", + Description = "Defines a preprocessing symbols for your source file.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-D", + Name = PREPROCESSOR_DEFINITIONS, + StringList = value + }; + ActiveToolSwitches.Add(PREPROCESSOR_DEFINITIONS, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the PreprocessOutput property + /// + [Output] + public ITaskItem[] PreprocessOutput + { + get + { + return _preprocessOutput; + } + set + { + _preprocessOutput = value; + } + } + + /// + /// Getter/Setter for the PreprocessOutputPath + /// + public string PreprocessOutputPath + { + get + { + if (IsPropertySet(PREPROCESS_TO_STDOUT)) + { + return ActiveToolSwitches[PREPROCESS_TO_STDOUT].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(PREPROCESS_TO_STDOUT); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Preprocess Output Path", + Description = "Specify the output path for the preprocessor. The default location is the same as the source file(s).", + ArgumentRelationList = new ArrayList(), + Name = PREPROCESS_TO_STDOUT, + Value = value, + SwitchValue = "E" + }; + ActiveToolSwitches.Add(PREPROCESS_TO_STDOUT, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the PreprocessSuppressLineNumbers property + /// + public bool PreprocessSuppressLineNumbers + { + get + { + return (IsPropertySet("PreprocessSuppressLineNumbers") && ActiveToolSwitches["PreprocessSuppressLineNumbers"].BooleanValue); + } + set + { + ActiveToolSwitches.Remove("PreprocessSuppressLineNumbers"); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Preprocess Suppress Line Numbers", + Description = "Preprocess without #line directives.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "/EP", + Name = "PreprocessSuppressLineNumbers", + BooleanValue = value + }; + ActiveToolSwitches.Add("PreprocessSuppressLineNumbers", switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the PreprocessToFile property + /// + public bool PreprocessToFile + { + get + { + return (IsPropertySet(PREPROCESS_TO_FILE) && ActiveToolSwitches[PREPROCESS_TO_FILE].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(PREPROCESS_TO_FILE); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Preprocess to a File", + Description = "Preprocesses C and C++ source files and writes the preprocessed output to a file. This option suppresses compilation, thus it does not produce an .obj file.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-P", + Name = PREPROCESS_TO_FILE, + BooleanValue = value + }; + ActiveToolSwitches.Add(PREPROCESS_TO_FILE, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the UndefinePreprocessorDefinition property + /// + public string[] UndefinePreprocessorDefinition + { + get + { + if (IsPropertySet(UNDEFINE_PREPROCESSOR_DEFINITION)) + { + return ActiveToolSwitches[UNDEFINE_PREPROCESSOR_DEFINITION].StringList; + } + return null; + } + set + { + ActiveToolSwitches.Remove(UNDEFINE_PREPROCESSOR_DEFINITION); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) + { + DisplayName = "Undefine Preprocessor Definitions", + Description = "Specifies one or more preprocessor undefines. (-U[macro])", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-U", + Name = UNDEFINE_PREPROCESSOR_DEFINITION, + StringList = value + }; + ActiveToolSwitches.Add(UNDEFINE_PREPROCESSOR_DEFINITION, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + public bool RuntimeTypeInfo { get; set; } + public bool ShortEnums { get; set; } + + #endregion + } +} diff --git a/src_vs2012/BuildTasks/QccExec.cs b/src_vs2012/BuildTasks/QccExec.cs new file mode 100644 index 00000000..8b30c808 --- /dev/null +++ b/src_vs2012/BuildTasks/QccExec.cs @@ -0,0 +1,33 @@ +using BlackBerry.BuildTasks.Helpers; +using Microsoft.Build.Tasks; + +namespace BlackBerry.BuildTasks +{ + /// + /// Simple extension of Exec task that also presets some environment variables (copied ideas from bbndk-env_xxx.bat script from any NDK). + /// + public sealed class QccExec : Exec + { + public override bool Execute() + { + EnvironmentVariables = ProcessSetupHelper.Update(EnvironmentVariables, QnxHost, QnxTarget); + return base.Execute(); + } + + #region Properties + + public string QnxHost + { + get; + set; + } + + public string QnxTarget + { + get; + set; + } + + #endregion + } +} diff --git a/src_vs2012/BuildTasks/QccLib.cs b/src_vs2012/BuildTasks/QccLib.cs new file mode 100644 index 00000000..170dd016 --- /dev/null +++ b/src_vs2012/BuildTasks/QccLib.cs @@ -0,0 +1,243 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using BlackBerry.BuildTasks.Properties; +using Microsoft.Build.CPPTasks; +using System.Collections; + +namespace BlackBerry.BuildTasks +{ + public sealed class QccLib : QccTask + { + #region Member Variables and Constants + + private const string ADDITIONAL_DEPENDENCIES = "AdditionalDependencies"; + private const string ADDITIONAL_LIB_DIR = "AdditionalLibraryDirectories"; + private const string OUTPUT_FILE = "OutputFile"; + private const string LINK_STATIC = "LinkStatic"; + private const string TREAT_LIB_WARNING_AS_ERROR = "TreatLibWarningAsErrors"; + + #endregion + + /// + /// QccLib default constructor + /// + public QccLib() + : base(Resources.ResourceManager) + { + _switchOrderList.Add(ADDITIONAL_DEPENDENCIES); + _switchOrderList.Add(ADDITIONAL_LIB_DIR); + _switchOrderList.Add(TREAT_LIB_WARNING_AS_ERROR); + _switchOrderList.Add(OUTPUT_FILE); + _switchOrderList.Add(SOURCES); + } + + #region Overrides + + /// + /// Getter/Setter for the AlwaysAppend property + /// + protected override string AlwaysAppend + { + get + { + return string.Empty; + } + } + + /// + /// Getter/Setter for the CommandTLogName property + /// + protected override string CommandTLogName + { + get { return "qcc_lib.command.1.tlog"; } + } + + /// + /// Getter/Setter for the ReadTLogNames property + /// + protected override string[] ReadTLogNames + { + get { return new[] { "qcc_lib.read.1.tlog", "qcc_lib.*.read.1.tlog" }; } + } + + /// + /// Getter/Setter for the WriteTLogNames + /// + protected override string[] WriteTLogNames + { + get + { + return new[] { "qcc_lib.write.1.tlog", "qcc_lib.*.write.1.tlog" }; + } + } + + /// + /// Method return the EnhancedSecuritySwitch + /// + /// + protected override string GetEnhancedSecuritySwitchValue() + { + return string.Empty; + } + + #endregion + + #region Properties + /// + /// Getter/Setter for the LinkStatic property + /// + public bool LinkStatic + { + get + { + return (IsPropertySet(LINK_STATIC) && ActiveToolSwitches[LINK_STATIC].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(LINK_STATIC); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Link Static", + Description = "Static link Lib", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-static", + Name = LINK_STATIC, + BooleanValue = value + }; + ActiveToolSwitches.Add(LINK_STATIC, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the AdditionalDependencies property + /// + public string[] AdditionalDependencies + { + get + { + if (IsPropertySet(ADDITIONAL_DEPENDENCIES)) + { + return ActiveToolSwitches[ADDITIONAL_DEPENDENCIES].StringList; + } + return null; + } + set + { + ActiveToolSwitches.Remove(ADDITIONAL_DEPENDENCIES); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) + { + DisplayName = "Additional Dependencies", + Description = "Specifies additional items to add to the link command line [i.e. bps] ", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-l", + Name = ADDITIONAL_DEPENDENCIES, + StringList = value + }; + ActiveToolSwitches.Add(ADDITIONAL_DEPENDENCIES, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the AdditionalLibraryDirectories property + /// + public string[] AdditionalLibraryDirectories + { + get + { + if (IsPropertySet(ADDITIONAL_LIB_DIR)) + { + return ActiveToolSwitches[ADDITIONAL_LIB_DIR].StringList; + } + return null; + } + set + { + ActiveToolSwitches.Remove(ADDITIONAL_LIB_DIR); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) + { + DisplayName = "Additional Library Directories", + Description = "Allows the user to override the environmental library path (-Lfolder)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-L", + Name = ADDITIONAL_LIB_DIR, + StringList = value + }; + ActiveToolSwitches.Add(ADDITIONAL_LIB_DIR, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the TreatLibWarningAsErrors property + /// + public bool TreatLibWarningAsErrors + { + get + { + return (IsPropertySet(TREAT_LIB_WARNING_AS_ERROR) && ActiveToolSwitches[TREAT_LIB_WARNING_AS_ERROR].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(TREAT_LIB_WARNING_AS_ERROR); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Treat Lib Warning As Errors", + Description = "-Werror causes no output file to be generated if lib generates a warning.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-Werror", + Name = TREAT_LIB_WARNING_AS_ERROR, + BooleanValue = value + }; + ActiveToolSwitches.Add(TREAT_LIB_WARNING_AS_ERROR, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// GetterSetter for the OutputFile property + /// + public string OutputFile + { + get + { + if (IsPropertySet(OUTPUT_FILE)) + { + return ActiveToolSwitches[OUTPUT_FILE].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(OUTPUT_FILE); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) + { + //Separator = ":", + DisplayName = "Output File", + Description = "The -A option overrides the default name and location of the program that the linker creates.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-A ", + Name = OUTPUT_FILE, + Value = value + }; + ActiveToolSwitches.Add(OUTPUT_FILE, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + #endregion + } +} diff --git a/src_vs2012/BuildTasks/QccLink.cs b/src_vs2012/BuildTasks/QccLink.cs new file mode 100644 index 00000000..20f4026a --- /dev/null +++ b/src_vs2012/BuildTasks/QccLink.cs @@ -0,0 +1,395 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.Collections.Generic; +using BlackBerry.BuildTasks.Properties; +using Microsoft.Build.CPPTasks; +using System.Collections; + +namespace BlackBerry.BuildTasks +{ + public sealed class QccLink : QccTask + { + #region Member Variables and Constants + + private const string ADDITIONAL_DEPENDENCIES = "AdditionalDependencies"; + private const string LINK_ERROR_REPORTING = "LinkErrorReporting"; + private const string ADDITIONAL_LIB_DIR = "AdditionalLibraryDirectories"; + private const string GENERATE_MAP_FILE = "GenerateMapFile"; + private const string IGNORE_ALL_DEFAULT_LIB = "IgnoreAllDefaultLibraries"; + private const string IGNOR_ALL_DEFAULT_CPP_LIB = "IgnoreAllDefaultCppLibraries"; + private const string LINK_INCREMENTAL = "LinkIncremental"; + private const string LINK_STATUS = "LinkStatus"; + private const string LINK_LIB_DEP = "LinkLibraryDependencies"; + private const string OUTPUT_FILE = "OutputFile"; + private const string TREAT_LINK_WARNING_AS_ERR = "TreatLinkerWarningAsErrors"; + + #endregion + + /// + /// QccLink default constructor + /// + public QccLink() + : base(Resources.ResourceManager) + { + _switchOrderList.Add(ADDITIONAL_DEPENDENCIES); + _switchOrderList.Add(LINK_ERROR_REPORTING); + _switchOrderList.Add(ADDITIONAL_LIB_DIR); + _switchOrderList.Add(GENERATE_MAP_FILE); + _switchOrderList.Add(IGNORE_ALL_DEFAULT_LIB); + _switchOrderList.Add(IGNOR_ALL_DEFAULT_CPP_LIB); + _switchOrderList.Add(LINK_INCREMENTAL); + _switchOrderList.Add(LINK_STATUS); + _switchOrderList.Add(LINK_LIB_DEP); + _switchOrderList.Add(OUTPUT_FILE); + _switchOrderList.Add(TREAT_LINK_WARNING_AS_ERR); + _switchOrderList.Add(SOURCES); + } + + #region Overrides + + /// + /// Getter/Setter for AlwaysAppend property + /// + protected override string AlwaysAppend + { + get + { + return LinkSharedLibrary? "-shared" : string.Empty; + } + } + + /// + /// Getter/Setter for CommandTLogName property + /// + protected override string CommandTLogName + { + get { return "qcc_linker.command.1.tlog"; } + } + + /// + /// Getter/Setter for ReadTLog + /// + protected override string[] ReadTLogNames + { + get { return new[] { "qcc_linker.read.1.tlog", "qcc_linker.*.read.1.tlog" }; } + } + + /// + /// Getter/Setter WriteTLogNames property + /// + protected override string[] WriteTLogNames + { + get + { + return new[] { "qcc_linker.write.1.tlog", "qcc_linker.*.write.1.tlog" }; + } + } + + /// + /// Function to return the Enhanced Security value. + /// + protected override string GetEnhancedSecuritySwitchValue() + { + return "-Wl,-z,relro -Wl,-z,now"; + } + #endregion + + #region Properties + + /// + /// Getter/Setter for the AdditionalDependencies property + /// + public string[] AdditionalDependencies + { + get + { + if (IsPropertySet(ADDITIONAL_DEPENDENCIES)) + { + return ActiveToolSwitches[ADDITIONAL_DEPENDENCIES].StringList; + } + return null; + } + set + { + ActiveToolSwitches.Remove(ADDITIONAL_DEPENDENCIES); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) + { + DisplayName = "Additional Dependencies", + Description = "Specifies additional items to add to the link command line [i.e. bps] ", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-l", + Name = ADDITIONAL_DEPENDENCIES, + StringList = value + }; + ActiveToolSwitches.Add(ADDITIONAL_DEPENDENCIES, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the AdditionalLibraryDirectories property + /// + public string[] AdditionalLibraryDirectories + { + get + { + if (IsPropertySet(ADDITIONAL_LIB_DIR)) + { + return ActiveToolSwitches[ADDITIONAL_LIB_DIR].StringList; + } + return null; + } + set + { + ActiveToolSwitches.Remove(ADDITIONAL_LIB_DIR); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.StringArray) + { + DisplayName = "Additional Library Directories", + Description = "Allows the user to override the environmental library path (-Lfolder)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-L", + Name = ADDITIONAL_LIB_DIR, + StringList = value + }; + ActiveToolSwitches.Add(ADDITIONAL_LIB_DIR, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the GenerateMapFile property + /// + public bool GenerateMapFile + { + get + { + return (IsPropertySet(GENERATE_MAP_FILE) && ActiveToolSwitches[GENERATE_MAP_FILE].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(GENERATE_MAP_FILE); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Generate Map File", + Description = "The -M option tells the linker to create a mapfile.", + ArgumentRelationList = new ArrayList() + }; + switch2.ArgumentRelationList.Add(new ArgumentRelation("MapFileName", "true", false, "")); + switch2.SwitchValue = "-M"; + switch2.Name = GENERATE_MAP_FILE; + switch2.BooleanValue = value; + ActiveToolSwitches.Add(GENERATE_MAP_FILE, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the IgnoreAllDefaultLibraries + /// + public bool IgnoreAllDefaultLibraries + { + get + { + return (IsPropertySet(IGNORE_ALL_DEFAULT_LIB) && ActiveToolSwitches[IGNORE_ALL_DEFAULT_LIB].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(IGNORE_ALL_DEFAULT_LIB); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Ignore All Default Libraries", + Description = "The -nostdlib option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. ", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-nostdlib", + Name = IGNORE_ALL_DEFAULT_LIB, + BooleanValue = value + }; + ActiveToolSwitches.Add(IGNORE_ALL_DEFAULT_LIB, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the IgnoreAllDefaultCppLibraries property + /// + public bool IgnoreAllDefaultCppLibraries + { + get + { + return (IsPropertySet(IGNOR_ALL_DEFAULT_CPP_LIB) && ActiveToolSwitches[IGNOR_ALL_DEFAULT_CPP_LIB].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(IGNOR_ALL_DEFAULT_CPP_LIB); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Ignore All Default C++ Libraries", + Description = "The -nostdlib++ option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. ", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-nostdlib++", + Name = IGNOR_ALL_DEFAULT_CPP_LIB, + BooleanValue = value + }; + ActiveToolSwitches.Add(IGNOR_ALL_DEFAULT_CPP_LIB, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the LinkIncremental Property + /// + public bool LinkIncremental + { + get + { + return (IsPropertySet(LINK_INCREMENTAL) && ActiveToolSwitches[LINK_INCREMENTAL].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(LINK_INCREMENTAL); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Enable Incremental Linking", + Description = "Enables incremental linking. (/INCREMENTAL, /INCREMENTAL:NO)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "/INCREMENTAL", + ReverseSwitchValue = "/INCREMENTAL:NO", + Name = LINK_INCREMENTAL, + BooleanValue = value + }; + ActiveToolSwitches.Add(LINK_INCREMENTAL, switch2); + AddActiveSwitchToolValue(switch2); + switch2.Overrides.AddLast(new KeyValuePair("INCREMENTAL", "INCREMENTAL:NO")); + switch2.Overrides.AddLast(new KeyValuePair("INCREMENTAL:NO", "INCREMENTAL")); + } + } + + /// + /// Getter/Setter for the LinkStatus property + /// + public bool LinkStatus + { + get + { + return (IsPropertySet(LINK_STATUS) && ActiveToolSwitches[LINK_STATUS].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(LINK_STATUS); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Link Status", + Description = "Specifies whether the linker should display a progress indicator showing what percentage of the link is complete. The default is to not display this status information. (/LTCG:STATUS|LTCG:NOSTATUS)", + ArgumentRelationList = new ArrayList(), + SwitchValue = "/LTCG:STATUS", + ReverseSwitchValue = "/LTCG:NOSTATUS", + Name = LINK_STATUS, + BooleanValue = value + }; + ActiveToolSwitches.Add(LINK_STATUS, switch2); + AddActiveSwitchToolValue(switch2); + switch2.Overrides.AddLast(new KeyValuePair("LTCG:STATUS", "LTCG:NOSTATUS")); + switch2.Overrides.AddLast(new KeyValuePair("LTCG:NOSTATUS", "LTCG:STATUS")); + } + } + + /// + /// Getter/Setter for the LinkLibraryDependencies + /// + public bool LinkLibraryDependencies + { + get + { + return (IsPropertySet(LINK_LIB_DEP) && ActiveToolSwitches[LINK_LIB_DEP].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(LINK_LIB_DEP); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Link Library Dependencies", + Description = "Specifies whether or not library outputs from project dependencies are automatically linked in.", + ArgumentRelationList = new ArrayList(), + Name = LINK_LIB_DEP, + BooleanValue = value + }; + ActiveToolSwitches.Add(LINK_LIB_DEP, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the OutputFile property + /// + public string OutputFile + { + get + { + if (IsPropertySet(OUTPUT_FILE)) + { + return ActiveToolSwitches[OUTPUT_FILE].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(OUTPUT_FILE); + + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.File) + { + DisplayName = "Output File", + Description = "The -o option overrides the default name and location of the program that the linker creates.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-o ", + Name = OUTPUT_FILE, + Value = value + }; + ActiveToolSwitches.Add(OUTPUT_FILE, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the TreatLinkerWarningAsErrors property. + /// + public bool TreatLinkerWarningAsErrors + { + get + { + return (IsPropertySet(TREAT_LINK_WARNING_AS_ERR) && ActiveToolSwitches[TREAT_LINK_WARNING_AS_ERR].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(TREAT_LINK_WARNING_AS_ERR); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Treat Linker Warning As Errors", + Description = "/WX causes no output file to be generated if the linker generates a warning.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "/WX", + ReverseSwitchValue = "/WX:NO", + Name = TREAT_LINK_WARNING_AS_ERR, + BooleanValue = value + }; + ActiveToolSwitches.Add(TREAT_LINK_WARNING_AS_ERR, switch2); + AddActiveSwitchToolValue(switch2); + switch2.Overrides.AddLast(new KeyValuePair("WX", "WX:NO")); + switch2.Overrides.AddLast(new KeyValuePair("WX:NO", "WX")); + } + } + + #endregion + } +} diff --git a/src_vs2012/BuildTasks/QccTask.cs b/src_vs2012/BuildTasks/QccTask.cs new file mode 100644 index 00000000..b5938438 --- /dev/null +++ b/src_vs2012/BuildTasks/QccTask.cs @@ -0,0 +1,723 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections; +using System.Resources; +using Microsoft.Build.CPPTasks; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks +{ + public abstract class QccTask : TrackedVCToolTask + { + #region Fields + + // Fields + protected readonly ArrayList _switchOrderList; + + //constant fields + private const string GENERATE_DEBUG_INFORMATION = "GenerateDebugInformation"; + private const string WARING_LEVEL = "WarningLevel"; + private const string TREAT_WARNING_AS_ERROR = "TreatWarningAsError"; + private const string TRACKER_LOG_DIRECTORY = "TrackerLogDirectory"; + private const string OPTIMIZATION = "Optimization"; + private const string GCC_EXCEPTION_HANDLING = "GccExceptionHandling"; + protected const string SOURCES = "Sources"; + private const string ADDITIONAL_OPTIONS = "AdditionalOptions"; + private const string BUILDING_IN_IDE = "BuildingInIDE"; + private const string ENHANCED_SECURITY = "EnhancedSecurity"; + private const string POSITION_INDEPENDENT_EXECUTABLE = "PIE"; + private const string COMPILER_VERSION_TARGET = "CompilerVersionTarget"; + private const string VERBOSE = "Verbose"; + private const string COMPILE_AS = "CompileAs"; + + private static string ERROR = " error:"; + private static string WARNING = " warning:"; + + #endregion + + /// + /// QnxTasks default constructor + /// + /// + public QccTask(ResourceManager res) + : base(res) + { + _switchOrderList = new ArrayList(); + _switchOrderList.Add(COMPILER_VERSION_TARGET); + _switchOrderList.Add("AlwaysAppend"); + _switchOrderList.Add(GENERATE_DEBUG_INFORMATION); + _switchOrderList.Add(VERBOSE); + _switchOrderList.Add(WARING_LEVEL); + _switchOrderList.Add(TREAT_WARNING_AS_ERROR); + _switchOrderList.Add(TRACKER_LOG_DIRECTORY); + _switchOrderList.Add(OPTIMIZATION); + _switchOrderList.Add(GCC_EXCEPTION_HANDLING); + _switchOrderList.Add(ADDITIONAL_OPTIONS); + _switchOrderList.Add(BUILDING_IN_IDE); + _switchOrderList.Add(ENHANCED_SECURITY); + _switchOrderList.Add(POSITION_INDEPENDENT_EXECUTABLE); + _switchOrderList.Add(COMPILE_AS); + } + + #region Overrides + + /// + /// don't use response file for msbuild because it is removed before qcc to run GCC compiler + /// + /// + /// + protected override string GetResponseFileSwitch(string responseFilePath) + { + return string.Empty; + } + + /// + /// instead pass the response file to command line commands + /// + /// + protected override string GenerateCommandLineCommands() + { + string cmd = GenerateResponseFileCommands(); + return cmd; + } + + /// + /// Function to assign out of date sources + /// + /// + /// + protected override ITaskItem[] AssignOutOfDateSources(ITaskItem[] sources) + { + ActiveToolSwitches[SOURCES].TaskItemArray = sources; + return sources; + } + + /// + /// Getter/Setter for SwitchOrderList property + /// + protected override ArrayList SwitchOrderList + { + get + { + return _switchOrderList; + } + } + + /// + /// Getter/Setter for TrackedInputFiles property + /// + protected override ITaskItem[] TrackedInputFiles + { + get + { + return Sources; + } + } + + /// + /// Getter/Setter for TrackerIntermediateDirectory + /// + protected override string TrackerIntermediateDirectory + { + get + { + if (TrackerLogDirectory != null) + { + return TrackerLogDirectory; + } + return string.Empty; + } + } + + /// + /// Getter/Setter for ToolName property + /// + protected override string ToolName + { + get { return QccExe; } + } + + /// + /// Getter/Setter for LogEventsFromTextOutput + /// + /// + /// + protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) + { + base.LogEventsFromTextOutput(Reformat(singleLine), messageImportance); + } + + + + /// + /// Reformat the qcc compiler error to msbuild known error format + /// singeLine: main.c:53: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int' + /// or main.c:38:19: error: hello.h: No such file or directory + /// output: main.c(53): error QCC001: expected '=', ',', ';', 'asm' or '__attribute__' before 'int' + /// TODO: this method need to be updated in case any more error formats of qcc compiler + /// + /// + /// + private string Reformat(string singleLine) + { + string msbuilError = singleLine; + string[] separators = { ERROR, WARNING }; + string errCode = singleLine.Contains(ERROR) ? "error qcc" : "warning qcc"; + string[] parts = singleLine.Split(separators, StringSplitOptions.None); + if (parts.Length > 1) + { + string[] segments = parts[0].Split(new[]{':'}, StringSplitOptions.RemoveEmptyEntries); + if (segments.Length == 3) + msbuilError = String.Format("{0}({1}-{2}): {3}: {4}", segments[0], segments[1], segments[2], errCode, parts[1]); + if ( segments.Length == 2 ) + msbuilError = String.Format("{0}({1}): {2}: {3}", segments[0], segments[1], errCode, parts[1]); + } + return msbuilError; + } + + /// + /// getter/setter for UseUnicodeOutput + /// + protected override bool UseUnicodeOutput + { + get + { + return BuildingInIDE; + } + } + + #endregion + + #region Properties + + /// + /// Getter/Setter for GenerateDebugInformation property + /// + public bool GenerateDebugInformation + { + get + { + if (IsPropertySet(GENERATE_DEBUG_INFORMATION)) + { + return ActiveToolSwitches[GENERATE_DEBUG_INFORMATION].BooleanValue; + } + return false; + } + set + { + ActiveToolSwitches.Remove(GENERATE_DEBUG_INFORMATION); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Generate Debug Info", + Description = "Generate Debug Info (-g)", + ArgumentRelationList = new ArrayList() + }; + switch2.SwitchValue = "-g"; + switch2.Name = GENERATE_DEBUG_INFORMATION; + switch2.BooleanValue = value; + ActiveToolSwitches.Add(GENERATE_DEBUG_INFORMATION, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for WarningLevel property + /// + public string WarningLevel + { + get + { + if (IsPropertySet(WARING_LEVEL)) + { + return ActiveToolSwitches[WARING_LEVEL].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(WARING_LEVEL); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Warning Level", + Description = "Select how strict you want the compiler to be about code errors. (-w0 - -w4)", + ArgumentRelationList = new ArrayList() + }; + string[][] switchMap = + { + new[] { "TurnOffAllWarnings", "-w0" }, + new[] { "Level1", "-w1" }, + new[] { "Level2", "-w2" }, + new[] { "Level3", "-w3" }, + new[] { "Level4", "-w4" }, + new[] { "Level5", "-w5" }, + new[] { "Level6", "-w6" }, + new[] { "Level7", "-w7" }, + new[] { "Level8", "-w8" }, + new[] { "Level9", "-w9" }, + new[] { "EnableAllWarnings", "-Wall" } + }; + switch2.SwitchValue = ReadSwitchMap(WARING_LEVEL, switchMap, value); + switch2.Name = WARING_LEVEL; + switch2.Value = value; +#if PLATFORM_VS2010 + switch2.MultiValues = true; +#else + switch2.MultipleValues = true; +#endif + ActiveToolSwitches.Add(WARING_LEVEL, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for TreatWarningAsError property + /// + public bool TreatWarningAsError + { + get + { + if (IsPropertySet(TREAT_WARNING_AS_ERROR)) + { + return ActiveToolSwitches[TREAT_WARNING_AS_ERROR].BooleanValue; + } + return false; + } + set + { + ActiveToolSwitches.Remove(TREAT_WARNING_AS_ERROR); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Treat Warnings as Errors", + Description = "Treat Warnings as Errors", + ArgumentRelationList = new ArrayList() + }; + switch2.ArgumentRelationList.Add(new ArgumentRelation(TREAT_WARNING_AS_ERROR, "true", false, "")); + switch2.SwitchValue = "-Werror"; + switch2.Name = TREAT_WARNING_AS_ERROR; + switch2.BooleanValue = value; + ActiveToolSwitches.Add(TREAT_WARNING_AS_ERROR, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for BuildingInIDE property + /// + public bool BuildingInIDE + { + get + { + return (IsPropertySet(BUILDING_IN_IDE) && ActiveToolSwitches[BUILDING_IN_IDE].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(BUILDING_IN_IDE); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + ArgumentRelationList = new ArrayList(), + Name = BUILDING_IN_IDE, + BooleanValue = value + }; + ActiveToolSwitches.Add(BUILDING_IN_IDE, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for GccExceptHandling property + /// + public string GccExceptionHandling + { + get + { + if (IsPropertySet("ExceptionHandling")) + { + return ActiveToolSwitches["ExceptionHandling"].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove("ExceptionHandling"); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Enable C++ Exceptions", + Description = "Specifies the model of exception handling to be used by the compiler.", + ArgumentRelationList = new ArrayList() + }; + string[][] switchMap = + { + new[] { "Async", "/EHa" }, + new[] { "Sync", "/EHsc" }, + new[] { "SyncCThrow", "/EHs" }, + new[] { "false", "" } + }; + switch2.SwitchValue = ReadSwitchMap("ExceptionHandling", switchMap, value); + switch2.Name = "ExceptionHandling"; + switch2.Value = value; +#if PLATFORM_VS2010 + switch2.MultiValues = true; +#else + switch2.MultipleValues = true; +#endif + ActiveToolSwitches.Add("ExceptionHandling", switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for Optimization property + /// + public string Optimization + { + get + { + if (IsPropertySet(OPTIMIZATION)) + { + return ActiveToolSwitches[OPTIMIZATION].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(OPTIMIZATION); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = OPTIMIZATION, + Description = "Select option for code optimization; choose Custom to use specific optimization options. (-O0, -O1, -O2, -O3)", + ArgumentRelationList = new ArrayList() + }; + string[][] switchMap = + { + new[] { "Disabled", "-O0" }, + new[] { "MinSpace", "-O1" }, + new[] { "MaxSpeed", "-O2" }, + new[] { "Full", "-O3" } + }; + switch2.SwitchValue = ReadSwitchMap(OPTIMIZATION, switchMap, value); + switch2.Name = OPTIMIZATION; + switch2.Value = value; +#if PLATFORM_VS2010 + switch2.MultiValues = true; +#else + switch2.MultipleValues = true; +#endif + ActiveToolSwitches.Add(OPTIMIZATION, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for PlatformToolset property + /// + public string PlatformToolset + { + get + { + return "qcc"; + } + } + + /// + /// Getter/Setter for TrackerLogDirectory + /// + public string TrackerLogDirectory + { + get + { + if (IsPropertySet(TRACKER_LOG_DIRECTORY)) + { + return ActiveToolSwitches[TRACKER_LOG_DIRECTORY].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(TRACKER_LOG_DIRECTORY); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Directory) + { + DisplayName = "Tracker Log Directory", + Description = "Tracker Log Directory.", + ArgumentRelationList = new ArrayList(), + Value = EnsureTrailingSlash(value) + }; + ActiveToolSwitches.Add(TRACKER_LOG_DIRECTORY, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for TargetMachine property + /// + public string TargetMachine + { + get + { + if (IsPropertySet("TargetMachine")) + { + return ActiveToolSwitches["TargetMachine"].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove("TargetMachine"); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Target Machine", + Description = "The /MACHINE option specifies the target platform for the program.", + ArgumentRelationList = new ArrayList() + }; + string[][] switchMap = + { + new[] { "MachineARM", "/MACHINE:ARM" }, + new[] { "MachineEBC", "/MACHINE:EBC" }, + new[] { "MachineIA64", "/MACHINE:IA64" }, + new[] { "MachineMIPS", "/MACHINE:MIPS" }, + new[] { "MachineMIPS16", "/MACHINE:MIPS16" }, + new[] { "MachineMIPSFPU", "/MACHINE:MIPSFPU" }, + new[] { "MachineMIPSFPU16", "/MACHINE:MIPSFPU16" }, + new[] { "MachineSH4", "/MACHINE:SH4" }, + new[] { "MachineTHUMB", "/MACHINE:THUMB" }, + new[] { "MachineX64", "/MACHINE:X64" }, + new[] { "MachineX86", "/MACHINE:X86" } + }; + switch2.SwitchValue = ReadSwitchMap("TargetMachine", switchMap, value); + switch2.Name = "TargetMachine"; + switch2.Value = value; +#if PLATFORM_VS2010 + switch2.MultiValues = true; +#else + switch2.MultipleValues = true; +#endif + ActiveToolSwitches.Add("TargetMachine", switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for CompileAs property + /// + public string CompileAs + { + get + { + if (IsPropertySet(COMPILE_AS)) + { + return ActiveToolSwitches[COMPILE_AS].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(COMPILE_AS); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Compile As", + Description = "Select compile language option for .c and .cpp files. (-lang-c, -lang-c++)", + ArgumentRelationList = new ArrayList() + }; + string[][] switchMap = + { + new[] { "CompileAsC", "-lang-c" }, + new[] { "CompileAsCpp", "-lang-c++" } + }; + switch2.SwitchValue = ReadSwitchMap(COMPILE_AS, switchMap, value); + switch2.Name = COMPILE_AS; + switch2.Value = value; +#if PLATFORM_VS2010 + switch2.MultiValues = true; +#else + switch2.MultipleValues = true; +#endif + ActiveToolSwitches.Add(COMPILE_AS, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for Verbose property + /// + public bool Verbose + { + get + { + return (IsPropertySet(VERBOSE) && ActiveToolSwitches[VERBOSE].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(VERBOSE); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Verbose", + Description = "Verbose", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-v", + Name = VERBOSE, + BooleanValue = value + }; + ActiveToolSwitches.Add(VERBOSE, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for EnhancedSecurity property + /// + public bool EnhancedSecurity + { + get + { + return (IsPropertySet(ENHANCED_SECURITY) && ActiveToolSwitches[ENHANCED_SECURITY].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(ENHANCED_SECURITY); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Enhanced Security(-fstack-protector-all)", + Description = " ", + ArgumentRelationList = new ArrayList(), + SwitchValue = GetEnhancedSecuritySwitchValue(), + Name = ENHANCED_SECURITY, + BooleanValue = value + }; + ActiveToolSwitches.Add(ENHANCED_SECURITY, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Return the Get Enhanced Security string. + /// + protected virtual string GetEnhancedSecuritySwitchValue() + { + return "-fstack-protector-all"; + } + + /// + /// Getter/Setter for the PIE property + /// + public bool PIE + { + get + { + return (IsPropertySet(POSITION_INDEPENDENT_EXECUTABLE) && ActiveToolSwitches[POSITION_INDEPENDENT_EXECUTABLE].BooleanValue); + } + set + { + ActiveToolSwitches.Remove(POSITION_INDEPENDENT_EXECUTABLE); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.Boolean) + { + DisplayName = "Position Independent Executable(fPIE)", + Description = " ", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-fPIE", + Name = POSITION_INDEPENDENT_EXECUTABLE, + BooleanValue = value + }; + ActiveToolSwitches.Add(POSITION_INDEPENDENT_EXECUTABLE, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the ProfilingCall property + /// + public bool ProfilingCall { get; set; } + + /// + /// Getter/Setter for the CodeCoverage property + /// + public bool CodeCoverage { get; set; } + + /// + /// Getter/Setter for the Mudflap property + /// + public bool Mudflap { get; set; } + + /// + /// Getter/Setter for the QccExe property + /// + public string QccExe { get; set; } + + /// + /// Getter/Setter for the CompilerVersionTarget property + /// + public string CompilerVersionTarget + { + get + { + if (IsPropertySet(COMPILER_VERSION_TARGET)) + { + return ActiveToolSwitches[COMPILER_VERSION_TARGET].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(COMPILER_VERSION_TARGET); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.String) + { + DisplayName = "Compiler version and target", + Description = " ", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-V", + }; + switch2.Name = COMPILER_VERSION_TARGET; + switch2.Value = value; + + ActiveToolSwitches.Add(COMPILER_VERSION_TARGET, switch2); + AddActiveSwitchToolValue(switch2); + } + } + + /// + /// Getter/Setter for the LinkSharedLibrary property + /// + public bool LinkSharedLibrary { get; set; } + + /// + /// Getter/Setter for the Sources property + /// + [Required] + public ITaskItem[] Sources + { + get + { + if (IsPropertySet(SOURCES)) + { + return ActiveToolSwitches[SOURCES].TaskItemArray; + } + return null; + } + set + { + ActiveToolSwitches.Remove(SOURCES); + ToolSwitch switch2 = new ToolSwitch(ToolSwitchType.ITaskItemArray) + { + Separator = " ", + Required = true, + ArgumentRelationList = new ArrayList(), + TaskItemArray = value + }; + ActiveToolSwitches.Add(SOURCES, switch2); + AddActiveSwitchToolValue(switch2); + } + } + #endregion + } +} diff --git a/src_vs2012/BuildTasks/RemoveFlagFile.cs b/src_vs2012/BuildTasks/RemoveFlagFile.cs new file mode 100644 index 00000000..a52dc442 --- /dev/null +++ b/src_vs2012/BuildTasks/RemoveFlagFile.cs @@ -0,0 +1,61 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace BlackBerry.BuildTasks +{ + /// + /// MSBuild Task for reading in the flag file from the start debugging button. + /// + public sealed class RemoveFlagFile : Task + { + private string _flagFile; + + /// + /// Execute the MSBuild Task + /// + public override bool Execute() + { + bool removed; + try + { + File.Delete(_flagFile); + removed = true; + } + catch (DirectoryNotFoundException dirNotFound) + { + Console.WriteLine(dirNotFound.Message); + removed = false; + } + + return removed; + } + + /// + /// Setter for FlagFile property + /// + [Required] + public string FlagFile + { + set + { + _flagFile = value; + } + } + } +} diff --git a/src_vs2012/BuildTasks/SSHDelete.cs b/src_vs2012/BuildTasks/SSHDelete.cs new file mode 100644 index 00000000..70fdecc3 --- /dev/null +++ b/src_vs2012/BuildTasks/SSHDelete.cs @@ -0,0 +1,330 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System.Collections; +using BlackBerry.BuildTasks.Properties; +using Microsoft.Build.CPPTasks; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks +{ + public sealed class SSHDelete : TrackedVCToolTask + { + #region Member Variables and Constants + + private readonly ArrayList _switchOrderList; + + private const string DEVICE = "Device"; + private const string PRIVATE_KEY_PATH = "PrivateKeyPath"; + private const string DELETE_FILES = "DeleteFiles"; + private const string PACKAGE_ID = "PackageId"; + private const string PACKAGE_NAME = "PackageName"; + + #endregion + + /// + /// SSHDelete default constructor + /// + public SSHDelete() + : base(Resources.ResourceManager) + { + _switchOrderList = new ArrayList(); + _switchOrderList.Add(PRIVATE_KEY_PATH); + } + + #region Overrides + + /// + /// Return the Response File Switch string + /// + /// + protected override string GetResponseFileSwitch(string responseFilePath) + { + return string.Empty; + } + + /// + /// Return the command line string + /// + protected override string GenerateCommandLineCommands() + { + return GenerateResponseFileCommands(); + } + + /// + /// Getter/Setter for the CommandTLogName property + /// + protected override string CommandTLogName + { + get { return "SSHDelete.command.1.tlog"; } + } + + /// + /// Getter/Setter for the ReadTLogNames string + /// + protected override string[] ReadTLogNames + { + get { return new[] { "SSHDelete.read.1.tlog", "SSHDelete.*.read.1.tlog" }; } + } + + /// + /// Getter/Setter for the WriteTLogNames string + /// + protected override string[] WriteTLogNames + { + get + { + return new[] { "SSHDelete.write.1.tlog", "SSHDelete.*.write.1.tlog" }; + } + } + + /// + /// Getter/Setter for the TrackedInputFiles string + /// + protected override ITaskItem[] TrackedInputFiles + { + get + { + if (IsPropertySet(DELETE_FILES)) + { + return ActiveToolSwitches[DELETE_FILES].TaskItemArray; + } + return null; + } + } + + /// + /// Getter/Setter for the ToolName property + /// + protected override string ToolName + { + get + { + return ToolExe; + } + } + + /// + /// Getter/Setter for the TrackerIntermediateDirectory property + /// + protected override string TrackerIntermediateDirectory + { + get + { + return string.Empty; + } + } + + /// + /// Function to generate the response file commands string + /// + protected override string GenerateResponseFileCommands() + { + string cmd = base.GenerateResponseFileCommands(); + + cmd += " -o \"StrictHostKeyChecking no\""; + + if (IsPropertySet(DEVICE)) + { + cmd += " devuser@" + ActiveToolSwitches[DEVICE].Value; + } + + if (IsPropertySet(DELETE_FILES)) + { + string path = "../../../../apps/" + PackageName + "." + PackageId + "/"; + cmd += " '"; + foreach (ITaskItem taskItem in ActiveToolSwitches[DELETE_FILES].TaskItemArray) + { + cmd += "rm " + path + taskItem.GetMetadata("Identity") + "; "; + } + cmd += "'"; + } + else + { + cmd += "'pwd;'"; + } + + return cmd; + } + + /// + /// Getter/Setter for the SwitchOrderList property. + /// + protected override ArrayList SwitchOrderList + { + get + { + return _switchOrderList; + } + } + + #endregion + + #region Properties + + /// + /// Getter/Setter for the Device property + /// + public string Device + { + get + { + if (IsPropertySet(DEVICE)) + { + return ActiveToolSwitches[DEVICE].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(DEVICE); + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = DEVICE, + DisplayName = "Device IP", + Description = "Specifies the target device's IP address.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "devuser@", + Value = value + }; + ActiveToolSwitches.Add(DEVICE, toolSwitch); + AddActiveSwitchToolValue(toolSwitch); + } + } + + /// + /// Getter/Setter for the PrivateKeyPath property + /// + public string PrivateKeyPath + { + get + { + if (IsPropertySet(PRIVATE_KEY_PATH)) + { + return ActiveToolSwitches[PRIVATE_KEY_PATH].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(PRIVATE_KEY_PATH); + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PRIVATE_KEY_PATH, + DisplayName = "Path to public key", + Description = "The -i option specifies the public SSH key to use.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-i ", + Value = value + }; + ActiveToolSwitches.Add(PRIVATE_KEY_PATH, toolSwitch); + AddActiveSwitchToolValue(toolSwitch); + } + } + + /// + /// Getter/Setter for the PackageId property + /// + public string PackageId + { + get + { + if (IsPropertySet(PACKAGE_ID)) + { + return ActiveToolSwitches[PACKAGE_ID].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(PACKAGE_ID); + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PACKAGE_ID, + DisplayName = "Package ID", + Description = "The -package-id option specifies the application's package id.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-package-id ", + Value = value + }; + ActiveToolSwitches.Add(PACKAGE_ID, toolSwitch); + AddActiveSwitchToolValue(toolSwitch); + } + } + + /// + /// Getter/Setter for the PackageName property + /// + public string PackageName + { + get + { + if (IsPropertySet(PACKAGE_NAME)) + { + return ActiveToolSwitches[PACKAGE_NAME].Value; + } + return null; + } + set + { + ActiveToolSwitches.Remove(PACKAGE_NAME); + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.String) + { + Name = PACKAGE_NAME, + DisplayName = "Package Name", + Description = "The -package-name option specifies the application's package name.", + ArgumentRelationList = new ArrayList(), + SwitchValue = "-package-name ", + Value = value + }; + ActiveToolSwitches.Add(PACKAGE_NAME, toolSwitch); + AddActiveSwitchToolValue(toolSwitch); + } + } + + /// + /// Getter/Setter for the DeleteFiles property + /// + public +#if PLATFORM_VS2013 + new +#endif + ITaskItem[] DeleteFiles + { + get + { + if (IsPropertySet(DELETE_FILES)) + { + return ActiveToolSwitches[DELETE_FILES].TaskItemArray; + } + return null; + } + set + { + ActiveToolSwitches.Remove(DELETE_FILES); + ToolSwitch toolSwitch = new ToolSwitch(ToolSwitchType.ITaskItemArray) + { + Name = DELETE_FILES, + DisplayName = "Files to delete", + Description = "Delete all items in the array from the device.", + TaskItemArray = value + }; + ActiveToolSwitches.Add(DELETE_FILES, toolSwitch); + AddActiveSwitchToolValue(toolSwitch); + } + } + + #endregion + } +} diff --git a/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.Properties.cs b/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.Properties.cs new file mode 100644 index 00000000..1e728298 --- /dev/null +++ b/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.Properties.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using BlackBerry.BuildTasks.Helpers; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks.Templates +{ + partial class ConfigPriTemplate : TemplateHelper.IWriter + { + private string[] _additionalLibraryDirs; + private string[] _additionalIncludeDirs; + + private string _precompiledHeaderName; + + #region Properties + + public string SolutionName + { + get; + set; + } + + /// + /// Gets the current version of the current library. + /// + public Version Version + { + get { return Assembly.GetExecutingAssembly().GetName().Version; } + } + + public ITaskItem LinkItem + { + get; + set; + } + + public ITaskItem[] CompileItems + { + get; + set; + } + + public ITaskItem[] IncludeItems + { + get; + set; + } + + public string[] CompileDirs + { + get; + set; + } + + public string[] IncludeDirs + { + get; + set; + } + + public string[] AdditionalLibraryDirs + { + get { return _additionalLibraryDirs; } + set { _additionalLibraryDirs = TemplateHelper.NormalizePaths(value); } + } + + public bool HasAdditionalLibraryDirs + { + get { return _additionalLibraryDirs != null && _additionalLibraryDirs.Length > 0; } + } + + public string[] AdditionalIncludeDirs + { + get { return _additionalIncludeDirs; } + set { _additionalIncludeDirs = TemplateHelper.NormalizePaths(value); } + } + + public bool HasAdditionalIncludeDirs + { + get { return _additionalIncludeDirs != null && _additionalIncludeDirs.Length > 0; } + } + + public string[] PreprocessorDefinitions + { + get; + set; + } + + public string[] UndefinePreprocessorDefinitions + { + get; + set; + } + + public string PrecompiledHeaderName + { + get { return _precompiledHeaderName; } + set { _precompiledHeaderName = TemplateHelper.Normalize(value); } + } + + public ITaskItem[] QmlItems + { + get; + set; + } + + public string[] QmlDirs + { + get; + set; + } + + #endregion + + private void WriteCollectionNewLine(IEnumerable items, string prefix) + { + TemplateHelper.WriteCollection(this, items, prefix, Environment.NewLine); + } + + private void WriteRelativePaths(ITaskItem[] items, string prefix, string suffix) + { + TemplateHelper.WriteRelativePaths(this, items, prefix, suffix); + } + + private void WriteRelativePaths(string[] items, string prefix, string suffix) + { + TemplateHelper.WriteRelativePaths(this, items, prefix, suffix); + } + + private void WriteRelativePathsTuple(string[] items1, string[] items2, string prefix, string suffix) + { + TemplateHelper.WriteRelativePathsTuple(this, items1, items2, prefix, suffix); + } + + private bool HasDependencyLibrariesReferences() + { + return TemplateHelper.HasDependencyLibrariesReferences(LinkItem); + } + + private void WriteDependencyLibrariesReferences() + { + TemplateHelper.WriteDependencyLibrariesReferences(this, LinkItem); + } + } +} diff --git a/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.cs b/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.cs new file mode 100644 index 00000000..deb4dfed --- /dev/null +++ b/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.cs @@ -0,0 +1,473 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 12.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace BlackBerry.BuildTasks.Templates +{ + using System.Text; + using System.Collections.Generic; + using System; + + /// + /// Class to produce the template output + /// + + #line 1 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "12.0.0.0")] + internal partial class ConfigPriTemplate : ConfigPriTemplateBase + { +#line hidden + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write("#\r\n# Cascades Application config file for ["); + + #line 5 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(SolutionName)); + + #line default + #line hidden + this.Write("] created at ["); + + #line 5 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(DateTime.Now)); + + #line default + #line hidden + this.Write("] by BlackBerry NDK plugin for Visual Studio (v"); + + #line 5 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(Version)); + + #line default + #line hidden + this.Write(").\r\n# Any manual changes made by user will be overwritten! Use the project settin" + + "gs instead.\r\n#\r\n\r\nBASEDIR = $$quote($$_PRO_FILE_PWD_)\r\n\r\n"); + + #line 11 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + if (!string.IsNullOrEmpty(PrecompiledHeaderName)) { + + #line default + #line hidden + this.Write("#############################################\r\n# Precompiled header\r\nCONFIG += pr" + + "ecompile_header\r\nPRECOMPILED_HEADER = $$quote($$BASEDIR/"); + + #line 15 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(PrecompiledHeaderName)); + + #line default + #line hidden + this.Write(")\r\n"); + + #line 16 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + } + + #line default + #line hidden + this.Write("\r\n#############################################\r\n# Libs, undefines and defines\r\n"); + + #line 20 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + if (HasAdditionalLibraryDirs) { + + #line default + #line hidden + this.Write("QMAKE_LIBDIR += "); + + #line 21 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePaths(AdditionalLibraryDirs, " \"", "\""); + + #line default + #line hidden + + #line 22 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + } + + #line default + #line hidden + + #line 23 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + if (HasDependencyLibrariesReferences()) { + + #line default + #line hidden + this.Write("LIBS += "); + + #line 24 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteDependencyLibrariesReferences(); + + #line default + #line hidden + + #line 25 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + } + + #line default + #line hidden + this.Write("\r\n"); + + #line 27 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + + WriteCollectionNewLine(UndefinePreprocessorDefinitions, "DEFINES -= "); + WriteCollectionNewLine(PreprocessorDefinitions, "DEFINES += "); + + + #line default + #line hidden + this.Write("\r\n#############################################\r\n# Source files, headers and QMLs" + + "\r\nSOURCES += "); + + #line 34 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePaths(CompileItems, " $$quote($$BASEDIR/", ")"); + + #line default + #line hidden + this.Write("\r\nHEADERS += "); + + #line 36 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePaths(IncludeItems, " $$quote($$BASEDIR/", ")"); + + #line default + #line hidden + this.Write("\r\nINCLUDEPATH += "); + + #line 38 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePaths(IncludeDirs, " $$quote($$BASEDIR/", ")"); + + #line default + #line hidden + this.Write("\r\n"); + + #line 40 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + if (HasAdditionalIncludeDirs) { + + #line default + #line hidden + this.Write("INCLUDEPATH += "); + + #line 41 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePaths(AdditionalIncludeDirs, " \"", "\""); + + #line default + #line hidden + + #line 42 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + } + + #line default + #line hidden + this.Write("\r\nOTHER_FILES += "); + + #line 44 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePaths(QmlItems, " $$quote($$BASEDIR/", ")"); + + #line default + #line hidden + this.Write("\r\n#############################################\r\n# Translations\r\nTRANSLATIONS = $" + + "$quote($${TARGET}.ts)\r\n\r\nlupdate_inclusion {\r\n\r\n SOURCES += "); + + #line 52 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePathsTuple(CompileDirs, new[] { "*.c", "*.c++", "*.cc", "*.cpp", "*.cxx" }, " $$quote($$BASEDIR/../", ")"); + + #line default + #line hidden + this.Write("\r\n SOURCES += "); + + #line 54 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePathsTuple(QmlDirs, new[] { "*.qml", "*.js", "*.qs" }, " $$quote($$BASEDIR/../", ")"); + + #line default + #line hidden + this.Write("\r\n HEADERS += "); + + #line 56 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\ConfigPriTemplate.tt" + WriteRelativePathsTuple(IncludeDirs, new[] { "*.h", "*.h++", "*.hh", "*.hpp", "*.hxx" }, " $$quote($$BASEDIR/../", ")"); + + #line default + #line hidden + this.Write("\r\n}\r\n\r\n\r\n\r\n"); + return this.GenerationEnvironment.ToString(); + } + } + + #line default + #line hidden + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "12.0.0.0")] + internal class ConfigPriTemplateBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion + } + #endregion +} diff --git a/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.tt b/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.tt new file mode 100644 index 00000000..54978613 --- /dev/null +++ b/src_vs2012/BuildTasks/Templates/ConfigPriTemplate.tt @@ -0,0 +1,61 @@ +<#@ template language="C#" visibility="internal" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +# +# Cascades Application config file for [<#= SolutionName #>] created at [<#= DateTime.Now #>] by BlackBerry NDK plugin for Visual Studio (v<#= Version #>). +# Any manual changes made by user will be overwritten! Use the project settings instead. +# + +BASEDIR = $$quote($$_PRO_FILE_PWD_) + +<# if (!string.IsNullOrEmpty(PrecompiledHeaderName)) { #> +############################################# +# Precompiled header +CONFIG += precompile_header +PRECOMPILED_HEADER = $$quote($$BASEDIR/<#= PrecompiledHeaderName #>) +<# } #> + +############################################# +# Libs, undefines and defines +<# if (HasAdditionalLibraryDirs) { #> +QMAKE_LIBDIR += <# WriteRelativePaths(AdditionalLibraryDirs, " \"", "\""); #> +<# } #> +<# if (HasDependencyLibrariesReferences()) { #> +LIBS += <# WriteDependencyLibrariesReferences(); #> +<# } #> + +<# + WriteCollectionNewLine(UndefinePreprocessorDefinitions, "DEFINES -= "); + WriteCollectionNewLine(PreprocessorDefinitions, "DEFINES += "); +#> + +############################################# +# Source files, headers and QMLs +SOURCES += <# WriteRelativePaths(CompileItems, " $$quote($$BASEDIR/", ")"); #> + +HEADERS += <# WriteRelativePaths(IncludeItems, " $$quote($$BASEDIR/", ")"); #> + +INCLUDEPATH += <# WriteRelativePaths(IncludeDirs, " $$quote($$BASEDIR/", ")"); #> + +<# if (HasAdditionalIncludeDirs) { #> +INCLUDEPATH += <# WriteRelativePaths(AdditionalIncludeDirs, " \"", "\""); #> +<# } #> + +OTHER_FILES += <# WriteRelativePaths(QmlItems, " $$quote($$BASEDIR/", ")"); #> + +############################################# +# Translations +TRANSLATIONS = $$quote($${TARGET}.ts) + +lupdate_inclusion { + + SOURCES += <# WriteRelativePathsTuple(CompileDirs, new[] { "*.c", "*.c++", "*.cc", "*.cpp", "*.cxx" }, " $$quote($$BASEDIR/../", ")"); #> + + SOURCES += <# WriteRelativePathsTuple(QmlDirs, new[] { "*.qml", "*.js", "*.qs" }, " $$quote($$BASEDIR/../", ")"); #> + + HEADERS += <# WriteRelativePathsTuple(IncludeDirs, new[] { "*.h", "*.h++", "*.hh", "*.hpp", "*.hxx" }, " $$quote($$BASEDIR/../", ")"); #> + +} + + + diff --git a/src_vs2012/BuildTasks/Templates/MakefileTemplate.Properties.cs b/src_vs2012/BuildTasks/Templates/MakefileTemplate.Properties.cs new file mode 100644 index 00000000..6f308206 --- /dev/null +++ b/src_vs2012/BuildTasks/Templates/MakefileTemplate.Properties.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using BlackBerry.BuildTasks.Helpers; +using Microsoft.Build.Framework; + +namespace BlackBerry.BuildTasks.Templates +{ + partial class MakefileTemplate : TemplateHelper.IWriter + { + private string[] _additionalIncludeDirectories; + private string[] _additionalLibraryDirectories; + + #region Properties + + public string SolutionName + { + get; + set; + } + + /// + /// Gets the current version of the current library. + /// + public Version Version + { + get { return Assembly.GetExecutingAssembly().GetName().Version; } + } + + public ITaskItem[] CompileItems + { + get; + set; + } + + public string TargetFile + { + get; + set; + } + + public string TargetCompiler + { + get; + set; + } + + public string TargetCompilerVersion + { + get; + set; + } + + public string CompilerFlags + { + get; + set; + } + + public ITaskItem[] CompileItemsAsC + { + get; + set; + } + + public ITaskItem[] CompileItemsAsCpp + { + get; + set; + } + + public ITaskItem LinkItem + { + get; + set; + } + + public string OutDir + { + get; + set; + } + + public string TargetBarFile + { + get; + set; + } + + public string ConfigurationType + { + get; + set; + } + + public string ProjectDir + { + get; + set; + } + + public string[] AdditionalIncludeDirectories + { + get { return _additionalIncludeDirectories; } + set { _additionalIncludeDirectories = TemplateHelper.NormalizePaths(value); } + } + + public string[] AdditionalLibraryDirectories + { + get { return _additionalLibraryDirectories; } + set { _additionalLibraryDirectories = TemplateHelper.NormalizePaths(value); } + } + + #endregion + + private static string[] GetRootedDirs(string projectDir, string[] items) + { + return TemplateHelper.GetRootedDirs(projectDir, items); + } + + private void WriteCollection(IEnumerable items, string prefix) + { + TemplateHelper.WriteCollection(this, items, prefix, " "); + } + + private string GetFullPath8Dot3(ITaskItem item) + { + return TemplateHelper.GetFullPath8Dot3(item); + } + + private void Write8Dot3Collection(ITaskItem[] items, string prefix, string suffix) + { + TemplateHelper.Write8Dot3Collection(this, items, prefix, suffix); + } + + private void WriteNameCollection(ITaskItem[] items, string prefix, string suffix) + { + TemplateHelper.WriteNameCollection(this, items, prefix, suffix); + } + + private void WriteDependencyLibrariesReferences() + { + TemplateHelper.WriteDependencyLibrariesReferences(this, LinkItem); + } + } +} diff --git a/src_vs2012/BuildTasks/Templates/MakefileTemplate.cs b/src_vs2012/BuildTasks/Templates/MakefileTemplate.cs new file mode 100644 index 00000000..4999e577 --- /dev/null +++ b/src_vs2012/BuildTasks/Templates/MakefileTemplate.cs @@ -0,0 +1,858 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 11.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace BlackBerry.BuildTasks.Templates +{ + using System.Text; + using System.Collections.Generic; + using System; + + /// + /// Class to produce the template output + /// + + #line 1 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "11.0.0.0")] + internal partial class MakefileTemplate : MakefileTemplateBase + { +#line hidden + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write("#\r\n# Makefile for ["); + + #line 5 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(SolutionName)); + + #line default + #line hidden + this.Write("] created at ["); + + #line 5 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(DateTime.Now)); + + #line default + #line hidden + this.Write("] by BlackBerry NDK plugin for Visual Studio (v"); + + #line 5 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(Version)); + + #line default + #line hidden + this.Write(@"). +# Any manual changes made by user will be overwritten! Use the project settings instead. +# + +############################################# +# Initials +RM := rm -rf + +# Empty variable definitions. +O_SRCS := +CPP_SRCS := +C_UPPER_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +II_SRCS := +ASM_SRCS := +CXX_SRCS := +I_SRCS := +CC_SRCS := +OBJS := +C_DEPS := +CC_DEPS := +ARCHIVES := +CPP_DEPS := +I_DEPS := +CXX_DEPS := +C_UPPER_DEPS := +II_DEPS := + +USER_OBJS := +LIBS := + +############################################# +# Sources + +"); + + #line 41 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + if (CompileItemsAsC.Length > 0) + { + + #line default + #line hidden + this.Write("C_SRCS += "); + + #line 43 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + Write8Dot3Collection(CompileItemsAsC, " ", ""); + + #line default + #line hidden + this.Write("\r\nC_DEPS += "); + + #line 45 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + WriteNameCollection(CompileItemsAsC, " ./", ".d"); + + #line default + #line hidden + + #line 46 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } /* CompileItemsAsC.Length > 0 */ + + #line default + #line hidden + this.Write("\r\n"); + + #line 48 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + if (CompileItemsAsCpp.Length > 0) + { + + #line default + #line hidden + this.Write("CPP_SRCS += "); + + #line 50 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + Write8Dot3Collection(CompileItemsAsCpp, " ", ""); + + #line default + #line hidden + this.Write("\r\nCPP_DEPS += "); + + #line 52 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + WriteNameCollection(CompileItemsAsCpp, " ./", ".d"); + + #line default + #line hidden + + #line 53 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } /* CompileItemsAsCpp.Length > 0 */ + + #line default + #line hidden + this.Write("\r\nOBJS += "); + + #line 55 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + WriteNameCollection(CompileItems, " ./", ".o"); + + #line default + #line hidden + this.Write("\r\n#############################################\r\n# Targets\r\n\r\nall: \""); + + #line 60 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\"\r\n\r\nDevice-Debug: \""); + + #line 62 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\"\r\n\r\nDevice-Release: \""); + + #line 64 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\"\r\n\r\nSimulator-Debug: \""); + + #line 66 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\"\r\n\r\n\""); + + #line 68 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\": $(OBJS) $(USER_OBJS) $(LIB_DEPS)\r\n\t"); + + #line 69 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + switch (ConfigurationType) + { + case "Application": + { + // Invoke linker + + + #line default + #line hidden + this.Write("qcc -o \""); + + #line 74 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(OutDir)); + + #line default + #line hidden + + #line 74 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\" $(OBJS) $(USER_OBJS) $(LIBS) "); + + #line 74 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(CompilerFlags)); + + #line default + #line hidden + this.Write(" "); + + #line 74 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + + if (LinkItem.GetMetadata("CompileAs") == "CompileAsC") { + + #line default + #line hidden + this.Write("-lang-c "); + + #line 76 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } else { + + #line default + #line hidden + this.Write("-lang-c++ "); + + #line 76 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + if (LinkItem.GetMetadata("GenerateDebugInformation") == "true") { + + #line default + #line hidden + this.Write("-g "); + + #line 77 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + + // For added security, remap some sections of ELF as read-only. + + + #line default + #line hidden + this.Write("-Wl,-z,relro,-z,now "); + + #line 80 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + + WriteDependencyLibrariesReferences(); + WriteCollection(GetRootedDirs(ProjectDir, LinkItem.GetMetadata("AdditionalLibraryDirectories").Split(';')), "-L"); + WriteCollection(AdditionalLibraryDirectories, "-L"); + } + break; + case "StaticLibrary": + { + + + #line default + #line hidden + this.Write("qcc -A \""); + + #line 89 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(OutDir)); + + #line default + #line hidden + + #line 89 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write(" $(OBJS) $(USER_OBJS) $(LIBS) "); + + #line 89 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(CompilerFlags)); + + #line default + #line hidden + this.Write(" -w1"); + + #line 89 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + } + break; + case "DynamicLibrary": + { + // In case of reverse dependencies, may need to add "-Wl,-export-dynamic" + // Also note that the soname is currently the same as the target name, and no version information is added. + + + #line default + #line hidden + this.Write("qcc -shared -Wl,-soname,\""); + + #line 96 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\" -o \""); + + #line 96 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(OutDir)); + + #line default + #line hidden + + #line 96 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\" $(OBJS) $(USER_OBJS) $(LIBS) "); + + #line 96 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(CompilerFlags)); + + #line default + #line hidden + + #line 96 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + } + break; + default: + + + #line default + #line hidden + this.Write("!! Error - unsupported configuration type !!"); + + #line 100 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + break; + } + + + #line default + #line hidden + this.Write("\r\n\r\nclean: FORCE\r\n\t-$(RM) $(OBJS)$(C_DEPS)$(CC_DEPS)$(COM_QNX_QCC_OUTPUTTYPE_LINK" + + "ER_OUTPUTS)$(CPP_DEPS)$(I_DEPS)$(CXX_DEPS)$(C_UPPER_DEPS)$(II_DEPS) \""); + + #line 107 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(OutDir)); + + #line default + #line hidden + + #line 107 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetFile)); + + #line default + #line hidden + this.Write("\""); + + #line 107 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + if (ConfigurationType == "Application") + { + + + #line default + #line hidden + this.Write(" \""); + + #line 110 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(OutDir)); + + #line default + #line hidden + + #line 110 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(TargetBarFile)); + + #line default + #line hidden + this.Write("\"\r\n"); + + #line 111 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + + #line default + #line hidden + this.Write("\r\nFORCE:\r\n\t\r\n\r\n.PHONY: all clean dependents\r\n\r\n"); + + #line 118 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + + var warningMap = new Dictionary(); + warningMap.Add("TurnOffAllWarnings", "-w0 "); + warningMap.Add("Level1", "-w1 "); + warningMap.Add("Level2", "-w2 "); + warningMap.Add("Level3", "-w3 "); + warningMap.Add("Level4", "-w4 "); + warningMap.Add("Level5", "-w5 "); + warningMap.Add("Level6", "-w6 "); + warningMap.Add("Level7", "-w7 "); + warningMap.Add("Level8", "-w8 "); + warningMap.Add("Level9", "-w9 "); + warningMap.Add("EnableAllWarnings", "-Wall "); + + foreach(var compileItem in CompileItems) + { + var filename = compileItem.GetMetadata("Filename"); + var shortPath = GetFullPath8Dot3(compileItem); + + // Now add a compile rule for this item. + + + #line default + #line hidden + + #line 139 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(filename)); + + #line default + #line hidden + this.Write(".o: "); + + #line 139 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(shortPath)); + + #line default + #line hidden + this.Write("\r\n\tqcc -o $@ "); + + #line 140 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(GetFullPath8Dot3(compileItem))); + + #line default + #line hidden + this.Write(" "); + + #line 140 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(CompilerFlags)); + + #line default + #line hidden + this.Write(" -c -Wp,-MMD,$(basename $@).d -Wp,-MT,$@ "); + + #line 140 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + + if (compileItem.GetMetadata("CompileAs") == "CompileAsC") + { + + + #line default + #line hidden + this.Write("-lang-c "); + + #line 144 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write("-lang-c++ "); + + #line 148 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + if (compileItem.GetMetadata("RuntimeTypeInfo") == "false") { + + #line default + #line hidden + this.Write("-fno-rtti "); + + #line 149 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + } + + string warningLevel; + if (warningMap.TryGetValue(compileItem.GetMetadata("WarningLevel"), out warningLevel)) + { + Write(warningLevel); + } + + if (compileItem.GetMetadata("GenerateDebugInformation") == "true") { + + #line default + #line hidden + this.Write("-g "); + + #line 158 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + if (compileItem.GetMetadata("GccExceptionHandling") == "true") { + + #line default + #line hidden + this.Write("-fexceptions "); + + #line 159 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } else { + + #line default + #line hidden + this.Write("-fno-exceptions "); + + #line 159 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + if (compileItem.GetMetadata("EnhancedSecurity") == "true") { + + #line default + #line hidden + this.Write("-fstack-protector-all "); + + #line 160 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + + // Note: Consider letting user decide between "-fpic" and "-fPIC" + // For now we use the safe, cross-platform "-fPIC" + if (ConfigurationType == "DynamicLibrary") { + + #line default + #line hidden + this.Write("-fPIC "); + + #line 164 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + } + + WriteCollection(AdditionalIncludeDirectories, "-I"); + WriteCollection(GetRootedDirs(ProjectDir, compileItem.GetMetadata("AdditionalIncludeDirectories").Replace('\\', '/').Split(';')), "-I"); + WriteCollection(compileItem.GetMetadata("UndefinePreprocessorDefinitions").Split(';'), "-U"); + WriteCollection(compileItem.GetMetadata("PreprocessorDefinitions").Split(';'), "-D"); + Write(compileItem.GetMetadata("AdditionalOptions")); + + + #line default + #line hidden + this.Write("\r\n\r\n"); + + #line 174 "T:\vs-plugin\src_vs2012\BuildTasks\Templates\MakefileTemplate.tt" + + } + + + #line default + #line hidden + this.Write(@"############################################# +# Include all dependency files + +ifneq ($(MAKECMDGOALS),clean) + ifneq ($(strip $(C_DEPS)),) + -include $(C_DEPS) + endif + ifneq ($(strip $(CC_DEPS)),) + -include $(CC_DEPS) + endif + ifneq ($(strip $(CPP_DEPS)),) + -include $(CPP_DEPS) + endif + ifneq ($(strip $(I_DEPS)),) + -include $(I_DEPS) + endif + ifneq ($(strip $(CXX_DEPS)),) + -include $(CXX_DEPS) + endif + ifneq ($(strip $(C_UPPER_DEPS)),) + -include $(C_UPPER_DEPS) + endif + ifneq ($(strip $(II_DEPS)),) + -include $(II_DEPS) + endif +endif + +# End +############################################# +"); + return this.GenerationEnvironment.ToString(); + } + } + + #line default + #line hidden + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "11.0.0.0")] + internal class MakefileTemplateBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion + } + #endregion +} diff --git a/src_vs2012/BuildTasks/Templates/MakefileTemplate.tt b/src_vs2012/BuildTasks/Templates/MakefileTemplate.tt new file mode 100644 index 00000000..a94ef002 --- /dev/null +++ b/src_vs2012/BuildTasks/Templates/MakefileTemplate.tt @@ -0,0 +1,205 @@ +<#@ template language="C#" visibility="internal" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +# +# Makefile for [<#= SolutionName #>] created at [<#= DateTime.Now #>] by BlackBerry NDK plugin for Visual Studio (v<#= Version #>). +# Any manual changes made by user will be overwritten! Use the project settings instead. +# + +############################################# +# Initials +RM := rm -rf + +# Empty variable definitions. +O_SRCS := +CPP_SRCS := +C_UPPER_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +II_SRCS := +ASM_SRCS := +CXX_SRCS := +I_SRCS := +CC_SRCS := +OBJS := +C_DEPS := +CC_DEPS := +ARCHIVES := +CPP_DEPS := +I_DEPS := +CXX_DEPS := +C_UPPER_DEPS := +II_DEPS := + +USER_OBJS := +LIBS := + +############################################# +# Sources + +<# if (CompileItemsAsC.Length > 0) + { #> +C_SRCS += <# Write8Dot3Collection(CompileItemsAsC, " ", ""); #> + +C_DEPS += <# WriteNameCollection(CompileItemsAsC, " ./", ".d"); #> +<# } /* CompileItemsAsC.Length > 0 */ #> + +<# if (CompileItemsAsCpp.Length > 0) + { #> +CPP_SRCS += <# Write8Dot3Collection(CompileItemsAsCpp, " ", ""); #> + +CPP_DEPS += <# WriteNameCollection(CompileItemsAsCpp, " ./", ".d"); #> +<# } /* CompileItemsAsCpp.Length > 0 */ #> + +OBJS += <# WriteNameCollection(CompileItems, " ./", ".o"); #> + +############################################# +# Targets + +all: "<#= TargetFile #>" + +Device-Debug: "<#= TargetFile #>" + +Device-Release: "<#= TargetFile #>" + +Simulator-Debug: "<#= TargetFile #>" + +"<#= TargetFile #>": $(OBJS) $(USER_OBJS) $(LIB_DEPS) + <# switch (ConfigurationType) + { + case "Application": + { + // Invoke linker + #>qcc -o "<#= OutDir #><#= TargetFile #>" $(OBJS) $(USER_OBJS) $(LIBS) <#= CompilerFlags #> <# + + if (LinkItem.GetMetadata("CompileAs") == "CompileAsC") { #>-lang-c <# } else { #>-lang-c++ <# } + if (LinkItem.GetMetadata("GenerateDebugInformation") == "true") { #>-g <# } + + // For added security, remap some sections of ELF as read-only. + #>-Wl,-z,relro,-z,now <# + + WriteDependencyLibrariesReferences(); + WriteCollection(GetRootedDirs(ProjectDir, LinkItem.GetMetadata("AdditionalLibraryDirectories").Split(';')), "-L"); + WriteCollection(AdditionalLibraryDirectories, "-L"); + } + break; + case "StaticLibrary": + { + #>qcc -A "<#= OutDir #><#= TargetFile #> $(OBJS) $(USER_OBJS) $(LIBS) <#= CompilerFlags #> -w1<# + } + break; + case "DynamicLibrary": + { + // In case of reverse dependencies, may need to add "-Wl,-export-dynamic" + // Also note that the soname is currently the same as the target name, and no version information is added. + #>qcc -shared -Wl,-soname,"<#= TargetFile #>" -o "<#= OutDir #><#= TargetFile #>" $(OBJS) $(USER_OBJS) $(LIBS) <#= CompilerFlags #><# + } + break; + default: + #>!! Error - unsupported configuration type !!<# + break; + } +#> + + +clean: FORCE + -$(RM) $(OBJS)$(C_DEPS)$(CC_DEPS)$(COM_QNX_QCC_OUTPUTTYPE_LINKER_OUTPUTS)$(CPP_DEPS)$(I_DEPS)$(CXX_DEPS)$(C_UPPER_DEPS)$(II_DEPS) "<#= OutDir #><#= TargetFile #>"<# + if (ConfigurationType == "Application") + { +#> "<#= OutDir #><#= TargetBarFile #>" +<# } #> + +FORCE: + + +.PHONY: all clean dependents + +<# + + var warningMap = new Dictionary(); + warningMap.Add("TurnOffAllWarnings", "-w0 "); + warningMap.Add("Level1", "-w1 "); + warningMap.Add("Level2", "-w2 "); + warningMap.Add("Level3", "-w3 "); + warningMap.Add("Level4", "-w4 "); + warningMap.Add("Level5", "-w5 "); + warningMap.Add("Level6", "-w6 "); + warningMap.Add("Level7", "-w7 "); + warningMap.Add("Level8", "-w8 "); + warningMap.Add("Level9", "-w9 "); + warningMap.Add("EnableAllWarnings", "-Wall "); + + foreach(var compileItem in CompileItems) + { + var filename = compileItem.GetMetadata("Filename"); + var shortPath = GetFullPath8Dot3(compileItem); + + // Now add a compile rule for this item. + #><#= filename #>.o: <#= shortPath #> + qcc -o $@ <#= GetFullPath8Dot3(compileItem) #> <#= CompilerFlags #> -c -Wp,-MMD,$(basename $@).d -Wp,-MT,$@ <# + + if (compileItem.GetMetadata("CompileAs") == "CompileAsC") + { + #>-lang-c <# + } + else + { + #>-lang-c++ <# + if (compileItem.GetMetadata("RuntimeTypeInfo") == "false") { #>-fno-rtti <# } + } + + string warningLevel; + if (warningMap.TryGetValue(compileItem.GetMetadata("WarningLevel"), out warningLevel)) + { + Write(warningLevel); + } + + if (compileItem.GetMetadata("GenerateDebugInformation") == "true") { #>-g <# } + if (compileItem.GetMetadata("GccExceptionHandling") == "true") { #>-fexceptions <# } else { #>-fno-exceptions <# } + if (compileItem.GetMetadata("EnhancedSecurity") == "true") { #>-fstack-protector-all <# } + + // Note: Consider letting user decide between "-fpic" and "-fPIC" + // For now we use the safe, cross-platform "-fPIC" + if (ConfigurationType == "DynamicLibrary") { #>-fPIC <# } + + WriteCollection(AdditionalIncludeDirectories, "-I"); + WriteCollection(GetRootedDirs(ProjectDir, compileItem.GetMetadata("AdditionalIncludeDirectories").Replace('\\', '/').Split(';')), "-I"); + WriteCollection(compileItem.GetMetadata("UndefinePreprocessorDefinitions").Split(';'), "-U"); + WriteCollection(compileItem.GetMetadata("PreprocessorDefinitions").Split(';'), "-D"); + Write(compileItem.GetMetadata("AdditionalOptions")); + #> + + +<# + } +#> +############################################# +# Include all dependency files + +ifneq ($(MAKECMDGOALS),clean) + ifneq ($(strip $(C_DEPS)),) + -include $(C_DEPS) + endif + ifneq ($(strip $(CC_DEPS)),) + -include $(CC_DEPS) + endif + ifneq ($(strip $(CPP_DEPS)),) + -include $(CPP_DEPS) + endif + ifneq ($(strip $(I_DEPS)),) + -include $(I_DEPS) + endif + ifneq ($(strip $(CXX_DEPS)),) + -include $(CXX_DEPS) + endif + ifneq ($(strip $(C_UPPER_DEPS)),) + -include $(C_UPPER_DEPS) + endif + ifneq ($(strip $(II_DEPS)),) + -include $(II_DEPS) + endif +endif + +# End +############################################# diff --git a/src_vs2012/DebugEngine/BlackBerry.DebugEngine.csproj b/src_vs2012/DebugEngine/BlackBerry.DebugEngine.csproj new file mode 100644 index 00000000..85781f44 --- /dev/null +++ b/src_vs2012/DebugEngine/BlackBerry.DebugEngine.csproj @@ -0,0 +1,200 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {59A7B188-E307-4495-A3AF-4ED76B086A87} + Library + Properties + BlackBerry.DebugEngine + BlackBerry.DebugEngine + v4.5 + 512 + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2012 + prompt + 4 + true + false + AnyCPU + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2012 + prompt + 4 + false + AnyCPU + + + + False + ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies\v2.0\Microsoft.VisualStudio.Debugger.Interop.10.0.dll + + + + False + ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\Microsoft.VisualStudio.Shell.11.0.dll + + + + False + True + C:\Program Files (x86)\Microsoft Visual Studio 2010 SDK SP1\VisualStudioIntegration\Common\Assemblies\v2.0\Microsoft.VisualStudio.Shell.Interop.10.0.dll + + + False + C:\Program Files (x86)\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\Assemblies\Microsoft.VisualStudio.Shell.Interop.8.0.dll + + + False + C:\Program Files (x86)\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\Assemblies\Microsoft.VisualStudio.Shell.Interop.9.0.dll + + + + + + False + ..\..\..\..\..\Microsoft.VisualStudio.Debugger.InteropA.dll + + + + + {faddd789-6cb5-4f9d-8481-1c0c72e5f19f} + BlackBerry.NativeCore + + + + + AD7.Definitions\AD7Enums.cs + + + AD7.Definitions\AD7Guids.cs + + + AD7.Definitions\AD7Hresult.cs + + + AD7.Impl\AD7BoundBreakpoint.cs + + + AD7.Impl\AD7BreakpointResolution.cs + + + AD7.Impl\AD7DocumentContext.cs + + + AD7.Impl\AD7Engine.cs + + + AD7.Impl\AD7Enums.cs + + + AD7.Impl\AD7ErrorBreakpointResolution.cs + + + AD7.Impl\AD7Events.cs + + + AD7.Impl\AD7Expression.cs + + + AD7.Impl\AD7MemoryAddress.cs + + + AD7.Impl\AD7Module.cs + + + AD7.Impl\AD7PendingBreakpoint.cs + + + AD7.Impl\AD7Port.cs + + + AD7.Impl\AD7PortRequest.cs + + + AD7.Impl\AD7PortSupplier.cs + + + AD7.Impl\AD7Process.cs + + + AD7.Impl\AD7ProgramNode.cs + + + AD7.Impl\AD7ProgramNodeAttach.cs + + + AD7.Impl\AD7ProgramProvider.cs + + + AD7.Impl\AD7Property.cs + + + AD7.Impl\AD7StackFrame.cs + + + AD7.Impl\AD7Thread.cs + + + DebugEngineStatus.cs + + + Engine.Impl\BreakpointManager.cs + + + Engine.Impl\EngineCallback.cs + + + Engine.Impl\EngineUtils.cs + + + Engine.Impl\EventDispatcher.cs + + + Engine.Impl\HandleBreakpoints.cs + + + Engine.Impl\HandleOutputs.cs + + + Engine.Impl\HandleProcessExecution.cs + + + Engine.Impl\VariableInfo.cs + + + Properties\AssemblyInfo.cs + + + NativeMethods.cs + + + Helpers\MessageBoxHelper.cs + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/GDBHost/BlackBerry.GDBHost.vcxproj b/src_vs2012/GDBHost/BlackBerry.GDBHost.vcxproj new file mode 100644 index 00000000..831a0ade --- /dev/null +++ b/src_vs2012/GDBHost/BlackBerry.GDBHost.vcxproj @@ -0,0 +1,105 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {9A560339-44DB-413F-868C-403962C2CF01} + Win32Proj + GDBWrapper + + + + Application + true + Unicode + false + v110 + + + Application + false + true + Unicode + false + v110 + + + + + + + + + + + + + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + false + + + xcopy "$(OutDir)BlackBerry.GDBHost.exe" "$(OutputPath)" /d /y + Copying Executable to output directory. + + + + + + + + + + + + + + Create + Create + + + + + + \ No newline at end of file diff --git a/src_vs2012/GDBHost/BlackBerry.GDBHost.vcxproj.filters b/src_vs2012/GDBHost/BlackBerry.GDBHost.vcxproj.filters new file mode 100644 index 00000000..1821ebcc --- /dev/null +++ b/src_vs2012/GDBHost/BlackBerry.GDBHost.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src_vs2012/GDBHost/GDBWrapper.cpp b/src_vs2012/GDBHost/GDBWrapper.cpp new file mode 100644 index 00000000..6300d455 --- /dev/null +++ b/src_vs2012/GDBHost/GDBWrapper.cpp @@ -0,0 +1,165 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + + +// GDBWrapper.cpp : Utility to run GDB in console mode so that CTRL-C works. +// + +#include "stdafx.h" + +#include +#include + +#include "GDBWrapper.h" +#include "Log.h" + + +/// +/// CTRL-C handler. +/// +/// CTRL type. +/// True; False. +static BOOL WINAPI GDBWrapperCtrlHandler(DWORD dwCtrlType) +{ + LogPrint(_T("ctrlHandler")); + if (dwCtrlType == CTRL_C_EVENT) + { + LogPrint(_T("ctrlHandler got CTRL_C_EVENT")); + return true; + } + + LogPrint(_T("ctrlHandler returns false")); + return false; +} + +/// +/// Constructor. +/// +/// String with full path and command to initialize GDB/MI. +/// Ctrl-C event handle +/// Terminate event handle +GDBWrapper::GDBWrapper(LPCTSTR lpszGdbCommandpcGDBCmd, HANDLE hEventCtrlC, HANDLE hEventTerminate) + : m_lpszGdbCommand(NULL), m_eventCtrlC(hEventCtrlC), m_eventTerminate(hEventCtrlC), m_isClosed(FALSE), m_hProcess(NULL) +{ + // Copy path to GDB + if (lpszGdbCommandpcGDBCmd != NULL) + { + size_t numChars = _tcslen(lpszGdbCommandpcGDBCmd) + 1; + m_lpszGdbCommand = new TCHAR[numChars * sizeof(TCHAR)]; + + if (m_lpszGdbCommand != NULL) + { + _tcscpy_s(m_lpszGdbCommand, numChars, lpszGdbCommandpcGDBCmd); + } + } + + // Register own CTRL-C handler + if (!SetConsoleCtrlHandler(GDBWrapperCtrlHandler, TRUE)) + { + PrintError(_T("SetConsoleCtrlHandler"), GetLastError()); + } +} + +/// +/// Destructor. +/// +GDBWrapper::~GDBWrapper() +{ + LogPrint(_T("+~GDBWrapper")); + if (!m_isClosed) + { + Shutdown(); + } + LogPrint(_T("-~GDBWrapper")); +} + +HANDLE GDBWrapper::GetProcessHandle() +{ + return m_hProcess; +} + +/// +/// Shut down GDB Wrapper: Update variables and terminate GDBWrapper process. +/// +void GDBWrapper::Shutdown() +{ + LogPrint(_T("+shutdown")); + m_isClosed = TRUE; + + delete[] m_lpszGdbCommand; + m_lpszGdbCommand = NULL; + + // Kill GDB process + if (m_hProcess != NULL) + { + TerminateProcess(m_hProcess, 0); + + if (!CloseHandle(m_hProcess)) + { + PrintError(_T("CloseHandle"), GetLastError()); + } + m_hProcess = NULL; + } + + LogPrint(_T("-shutdown")); +} + +/// +/// Sets up STARTUPINFO structure and launches redirected child. +/// +BOOL GDBWrapper::StartProcess() +{ + if (m_hProcess != NULL) + { + return FALSE; + } + + LPCTSTR lpApplicationName = NULL; + PROCESS_INFORMATION pi; + STARTUPINFO si; + DWORD flags = 0; + + // Set up the start up info struct. + ZeroMemory(&pi, sizeof(pi)); + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + + // Pass the redirected handles + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + // Use this if you want to hide the child: + // si.wShowWindow = SW_HIDE; + // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to + // use the wShowWindow flags. + + // Launch the process + if (!CreateProcess(NULL, m_lpszGdbCommand, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi)) + { + ShowMessage(_T("CreateProcess"), GetLastError(), m_lpszGdbCommand); + return FALSE; + } + + m_hProcess = pi.hProcess; + + if (!CloseHandle(pi.hThread)) + { + PrintError(_T("CloseHandle"), GetLastError()); + return FALSE; + } + + return TRUE; +} diff --git a/src_vs2012/GDBHost/GDBWrapper.h b/src_vs2012/GDBHost/GDBWrapper.h new file mode 100644 index 00000000..4def0b47 --- /dev/null +++ b/src_vs2012/GDBHost/GDBWrapper.h @@ -0,0 +1,35 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +#pragma once + +#include "stdafx.h" + +class GDBWrapper +{ +private: + BOOL m_isClosed; + HANDLE m_hProcess; + HANDLE m_eventCtrlC; + HANDLE m_eventTerminate; + TCHAR* m_lpszGdbCommand; + +public: + GDBWrapper(LPCTSTR lpszGdbCommand, HANDLE hEventCtrlC, HANDLE hEventTerminate); + ~GDBWrapper(); + + HANDLE GetProcessHandle(); + void Shutdown(); + BOOL StartProcess(); +}; diff --git a/src_vs2012/GDBHost/Log.cpp b/src_vs2012/GDBHost/Log.cpp new file mode 100644 index 00000000..f5032bed --- /dev/null +++ b/src_vs2012/GDBHost/Log.cpp @@ -0,0 +1,118 @@ +#include "stdafx.h" +#include "Log.h" + +#include +#include +#include +#include + + +static bool gPrintConsole = true; + +#if LOGS_ENABLED + +static char gLogFilePath[_MAX_PATH]; // contains the path to the output log (needed in LogPrint()) + +void LogInitialize() +{ + GetEnvironmentVariableA("LocalAppData", gLogFilePath, _countof(gLogFilePath)); + strcat_s(gLogFilePath, _countof(gLogFilePath), "\\BlackBerry\\wrapper.log"); + + FILE* file = NULL; + errno_t retCode; + retCode = fopen_s(&file, gLogFilePath, "w"); // just to delete a possible existing file + if (file != NULL && retCode == 0) + { + fclose(file); + } +} + +/// +/// Generic function to print to a log file. +/// +/// Message to be printed to a log file. +void LogPrint(TCHAR* message) +{ + FILE* file = NULL; + errno_t retCode; + + retCode = fopen_s(&file, gLogFilePath, "a"); + if (file != NULL && retCode == 0) + { + _ftprintf(file, _T("%s\r\n"), message); + fclose(file); + } +} + +#endif /* LOGS_ENABLED */ + +void DisableConsolePrinting() +{ + gPrintConsole = false; +} + +static void VsPrintMessage(LPCTSTR format, va_list args) +{ + TCHAR buffer[1024] = _T(""); + + _vstprintf_s(buffer, _countof(buffer), format, args); + + if (gPrintConsole) + { + _tprintf(buffer); + fflush(stdout); + } + + // and also put it into logs... + LogPrint(buffer); +} + +void PrintMessage(LPCTSTR format, ...) +{ + va_list list; + + va_start(list, format); + VsPrintMessage(format, list); + va_end(list); +} + +/// +/// Displays the error number and corresponding message. +/// +/// Name of the API function, that failed +void PrintError(LPCTSTR lpszFunctionName, DWORD lastError) +{ + HLOCAL lpvMessageBuffer = NULL; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpvMessageBuffer, 0, NULL); + PrintMessage(_T("Error: API = %s.\n error code = %d.\n message = %s.\n"), lpszFunctionName, lastError, (LPTSTR)lpvMessageBuffer); + LocalFree(lpvMessageBuffer); +} + +/// +/// Retrieve the system error message for the last-error code. +/// +/// Name of the API function, that failed +void ShowMessage(LPCTSTR lpszFunctionName, DWORD lastError, LPCTSTR arguments) +{ + HLOCAL lpMsgBuf; + HLOCAL lpDisplayBuf; + + if (arguments == NULL) + arguments = _T(""); + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); + + // Display the error message and exit the process + lpDisplayBuf = LocalAlloc(LMEM_ZEROINIT, (_tcslen((LPCTSTR)lpMsgBuf) + _tcslen(lpszFunctionName) + 40 + _tcslen(arguments)) * sizeof(TCHAR)); + _stprintf_s((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), _T("%s failed with error %d: %s\r\n%s"), lpszFunctionName, + lastError, lpMsgBuf, arguments); + + PrintMessage(_T("%s"), (LPCTSTR)lpDisplayBuf); + MessageBox(NULL, (LPCTSTR)lpDisplayBuf, _T("GDB Host Error"), MB_OK); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); +} diff --git a/src_vs2012/GDBHost/Log.h b/src_vs2012/GDBHost/Log.h new file mode 100644 index 00000000..744c892e --- /dev/null +++ b/src_vs2012/GDBHost/Log.h @@ -0,0 +1,23 @@ +#pragma once + +#include "stdafx.h" + + +#define LOGS_ENABLED 0 + + +#if LOGS_ENABLED + void LogInitialize(); + void LogPrint(TCHAR *message); +#else +# define LogInitialize() // do nothing +# define LogPrint(message) // do nothing +#endif + +void DisableConsolePrinting(); + +// prints given message directly to console and log file +void PrintMessage(LPCTSTR format, ...); +// print predefined +void PrintError(LPCTSTR lpszFunctionName, DWORD lastError); +void ShowMessage(LPCTSTR lpszFunctionName, DWORD lastError, LPCTSTR arguments); diff --git a/src_vs2012/GDBHost/main.cpp b/src_vs2012/GDBHost/main.cpp new file mode 100644 index 00000000..726bcb07 --- /dev/null +++ b/src_vs2012/GDBHost/main.cpp @@ -0,0 +1,213 @@ +#include "stdafx.h" +#include "GDBWrapper.h" +#include "Log.h" + +#include + + +/// +/// This method concatenates arguments sent to GDB. +/// The executable is given at 'exeAt' index, and the rest args start at 'argsFrom'. +/// It will return NULL, if anything failed. +/// +static LPCTSTR ConcatGdbCommand(int argc, _TCHAR* argv[], LPCTSTR exePath, int argsFrom) +{ + size_t length = 1; // for NUL-terminator + + if (exePath != NULL) + { + length += _tcslen(exePath); + length += 2; // for apostrophs + } + + for (int i = argsFrom; i < argc; i++) + { + length += 3; // for space between args and apostrophs + length += _tcslen(argv[i]); + } + + if (length == 0) + return NULL; + + // alloc result: + TCHAR *result = new TCHAR[length]; + if (result == NULL) + return NULL; + + // concatenate result string: + if (exePath != NULL) + { + _tcscpy_s(result, length, _T("\"")); + _tcscat_s(result, length, exePath); + _tcscat_s(result, length, _T("\"")); + } + else + { + result[0] = '\0'; + } + + for (int i = argsFrom; i < argc; i++) + { + _tcscat_s(result, length, _T(" \"")); + _tcscat_s(result, length, argv[i]); + _tcscat_s(result, length, _T("\"")); + } + + return result; +} + +static BOOL FileExists(LPCTSTR lpszPath) +{ + DWORD attributes = GetFileAttributes(lpszPath); + + return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY)); +} + +/// +/// GDBWrapper Main function. +/// +/// Not used. +/// argv[0] -> Full path of the GDBWrapper executable file. +/// argv[1] -> String with full path and command to initialize GDB/MI +/// argv[2] -> Ctrl-C handler; +/// argv[3] -> Terminate handler. +/// 0 +int _tmain(int argc, _TCHAR* argv[]) +{ + SetConsoleTitle(_T("BlackBerry GDB Host Application")); + + LogInitialize(); + LogPrint(_T("Starting")); + + if (argc < 4) + { + PrintMessage(_T("Copyright (C) 2010-2014 Research in Motion Limited\r\n")); + PrintMessage(_T("This application runs GDB in console mode and helps it handle Ctrl+C signal.\r\n")); + PrintMessage(_T("Usage:\r\n")); + PrintMessage(_T(" BlackBerry.GDBHost.exe (host-options) ()*\r\n")); + PrintMessage(_T("Where:\r\n")); + PrintMessage(_T(" - name of the global event, firing it will cause sending Ctrl+C to GDB\r\n")); + PrintMessage(_T(" - name of the global event, firing it will cause this process to finish\r\n")); + PrintMessage(_T(" - path to GDB executable and its arguments\r\n")); + PrintMessage(_T(" - additional arguments passed directly to GDB\r\n")); + PrintMessage(_T(" (host-options) - single parameter starting with '-', which defines custom behavior of the host process itself\r\n")); + PrintMessage(_T("Host options:\r\n")); + PrintMessage(_T(" s - [silent] - disable all custom console logs\r\n")); + PrintMessage(_T(" c - skip checking GDB executable existance, before executing\r\n")); + PrintMessage(_T("\r\n\r\n")); + return 0; + } + + HANDLE handleCtrlC; + HANDLE handleTerminate; + LPCTSTR hostOptions = argv[3]; // it's not a mistake, the hostOptions and gdbExecutablePath should point to the same 'opitional' parameter + LPCTSTR gdbExecutablePath = argv[3]; + LPCTSTR eventNameCtrlC = argv[1]; + LPCTSTR eventNameTerminate = argv[2]; + int gdbArgsStartFrom = 4; + BOOL checkGdbExistence = TRUE; + + // check, if we passed some optional arguments for the host... + if (hostOptions[0] == '-') + { + gdbExecutablePath = argc >= 5 ? argv[4] : NULL; + gdbArgsStartFrom = 5; + + // and parse host options: + int optionsLength = _tcslen(hostOptions); + for (int i = 1; i < optionsLength; i++) + { + switch(hostOptions[i]) + { + case 's': + DisableConsolePrinting(); + break; + case 'c': + checkGdbExistence = FALSE; + break; + } + } + } + + handleCtrlC = OpenEventW(EVENT_ALL_ACCESS, TRUE, eventNameCtrlC); // Ctrl-C signal + handleTerminate = OpenEventW(EVENT_ALL_ACCESS, TRUE, eventNameTerminate); // Signal to terminate the wrapper process + + // If opening failed, create by itself events with the same names: + if (handleCtrlC == NULL) + { + PrintMessage(_T("Error: Unable to open Ctrl+C event (%s), creating new one\r\n"), eventNameCtrlC); + handleCtrlC = CreateEvent(NULL, FALSE, FALSE, eventNameCtrlC); + } + if (handleTerminate == NULL) + { + PrintMessage(_T("Error: Unable to open termination event (%s), creating new one\r\n"), eventNameTerminate); + handleTerminate = CreateEvent(NULL, FALSE, FALSE, eventNameTerminate); + } + + // Print status + PrintMessage(_T("STARTUP INFO:\r\n")); + PrintMessage(_T(" Args: %s %s %s %s\r\n"), argv[0], argv[1], argv[2], argv[3], argc >= 5 ? argv[4] : _T(""), argc >= 6 ? argv[5] : _T("")); + PrintMessage(_T(" Ctrl-C handler: name: \"%s\", handle: 0x%p\r\n"), eventNameCtrlC, handleCtrlC); + PrintMessage(_T(" Terminate handler: name: \"%s\", handle: 0x%p\r\n"), eventNameTerminate, handleTerminate); + + if (gdbExecutablePath == NULL || gdbExecutablePath[0] == '\0' || (checkGdbExistence && !FileExists(gdbExecutablePath))) + { + PrintMessage(_T("Error: Unable to find GDB executable (%s)\r\n"), gdbExecutablePath != NULL ? gdbExecutablePath : _T("-missing path-")); + return 1; + } + + // Initialize GDB + LPCTSTR gdbCommand = ConcatGdbCommand(argc, argv, gdbExecutablePath, gdbArgsStartFrom); + GDBWrapper* gdb = new GDBWrapper(gdbCommand, handleCtrlC, handleTerminate); + + PrintMessage(_T(" GDB command: %s\r\n"), gdbCommand); + PrintMessage(_T("\r\n\r\n")); + + delete[] gdbCommand; + + // Start GDB + if (!gdb->StartProcess()) + { + PrintMessage(_T("Error: Failed to start the GDB process (%s)\r\n"), gdbExecutablePath); + return 2; + } + + HANDLE handles[] = { handleCtrlC, handleTerminate, gdb->GetProcessHandle() }; + BOOL exitProc = FALSE; + + // Main loop + while (!exitProc) + { + // Wait for a CTRL-C event indicating GDB should be interrupted + LogPrint(_T("WaitForMultipleObjects")); + DWORD event = WaitForMultipleObjects(_countof(handles), handles, false, INFINITE); + switch (event) + { + case WAIT_OBJECT_0: + LogPrint(_T("WAIT_OBJECT_0 (Ctrl-C)")); + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + break; + case WAIT_OBJECT_0 + 1: + LogPrint(_T("WAIT_OBJECT_0 + 1 (Terminate)")); + exitProc = TRUE; + break; + case WAIT_OBJECT_0 + 2: + LogPrint(_T("WAIT_OBJECT_0 + 2 (GDB Terminated)")); + PrintMessage(_T("GDB process terminated!")); + exitProc = TRUE; + break; + case WAIT_FAILED: + PrintError(_T("WaitForSingleObject WAIT_FAILED"), GetLastError()); + exitProc = TRUE; + break; + default: + exitProc = TRUE; + break; + } + } + + // Clean-up + gdb->Shutdown(); + PrintMessage(_T("Finished")); + return 0; +} diff --git a/src_vs2012/GDBHost/stdafx.cpp b/src_vs2012/GDBHost/stdafx.cpp new file mode 100644 index 00000000..64dc4703 --- /dev/null +++ b/src_vs2012/GDBHost/stdafx.cpp @@ -0,0 +1,22 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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 +// GDBWrapper.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/src_vs2012/GDBHost/stdafx.h b/src_vs2012/GDBHost/stdafx.h new file mode 100644 index 00000000..263bd874 --- /dev/null +++ b/src_vs2012/GDBHost/stdafx.h @@ -0,0 +1,27 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#include diff --git a/src_vs2013/GDBWrapper/targetver.h b/src_vs2012/GDBHost/targetver.h similarity index 97% rename from src_vs2013/GDBWrapper/targetver.h rename to src_vs2012/GDBHost/targetver.h index f5841111..3ed12a71 100644 --- a/src_vs2013/GDBWrapper/targetver.h +++ b/src_vs2012/GDBHost/targetver.h @@ -12,11 +12,12 @@ //* See the License for the specific language governing permissions and //* limitations under the License. -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include + diff --git a/src_vs2012/GDBParser.UnitTests/GDBParser_UnitTests.csproj b/src_vs2012/GDBParser.UnitTests/GDBParser_UnitTests.csproj deleted file mode 100644 index e5408b1d..00000000 --- a/src_vs2012/GDBParser.UnitTests/GDBParser_UnitTests.csproj +++ /dev/null @@ -1,64 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {6451DFCD-1CCD-4796-A832-A45FB95D994F} - Library - Properties - GDBParser.UnitTests - GDBParser.UnitTests - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - {CC7B28E0-CB31-44F7-A380-E7072F670F38} - GDBParser - - - - - \ No newline at end of file diff --git a/src_vs2012/GDBParser.UnitTests/Properties/AssemblyInfo.cs b/src_vs2012/GDBParser.UnitTests/Properties/AssemblyInfo.cs deleted file mode 100644 index 7dfe25ba..00000000 --- a/src_vs2012/GDBParser.UnitTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GDBParser.UnitTests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("GDBParser.UnitTests")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("80f98dd4-ce03-42f3-b852-346148df4493")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src_vs2012/GDBParser.UnitTests/UnitTest.cs b/src_vs2012/GDBParser.UnitTests/UnitTest.cs deleted file mode 100644 index 42cc7323..00000000 --- a/src_vs2012/GDBParser.UnitTests/UnitTest.cs +++ /dev/null @@ -1,381 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using VSNDK.Parser; -using NUnit.Framework; - -namespace GDBParser_UnitTests -{ - public class UnitTests - { - [Test] - public void GetNextChar() - { - Assert.AreEqual(0, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('a'), "abcdefghij", 0), "Error: char 'a', string 'abcdefghij', int '0'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('a'), "abcdefghij", 1), "Error: char 'a', string 'abcdefghij', int '1'"); - Assert.AreEqual(3, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "abcdefghij", 0), "Error: char 'd', string 'abcdefghij', int '0'"); - Assert.AreEqual(3, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "abcdefghij", 1), "Error: char 'd', string 'abcdefghij', int '1'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('z'), "abcdefghij", 1), "Error: char 'z', string 'abcdefghij', int '1'"); - Assert.AreEqual(0, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "", 1), "Error: char 'd', string '', int '1'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte('d'), "abcdefghij", 12), "Error: char 'd', string 'abcdefghij', int '12'"); - Assert.AreEqual(10, GDBParserUnitTests.get_Next_Char(Convert.ToSByte(null), "abcdefghij", 1), "Error: char NULL, string 'abcdefghij', int '1'"); - } - - [Test] - public void findClosing() - { - Assert.AreEqual(1, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "()cdefghij", 0), "Error: char '(', char '), string '()cdefghij', int '0'"); - Assert.AreEqual(10, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(bcdefghij", 2), "Error: char '(', char '), string '(bcdefghij', int '2'"); - Assert.AreEqual(10, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(bcdefghij", 0), "Error: char '(', char '), string '(bcdefghij', int '0'"); - Assert.AreEqual(5, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()())ghij", 0), "Error: char '(', char '), string '(()())ghij', int '0'"); - Assert.AreEqual(7, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((\\()())hij", 0), "Error: char '(', char '), string '((\\()())hij', int '0'"); - Assert.AreEqual(2, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()())ghij", 1), "Error: char '(', char '), string '(()())ghij', int '1'"); - Assert.AreEqual(4, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((\\()())hij", 1), "Error: char '(', char '), string '((\\()())hij', int '1'"); - Assert.AreEqual(4, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()())ghij", 3), "Error: char '(', char '), string '(()())ghij', int '3'"); - Assert.AreEqual(6, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "(()(())hij", 3), "Error: char '(', char '), string '(()(())hij', int '3'"); - Assert.AreEqual(1, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "()())fghij", 0), "Error: char '(', char '), string '()())fghij', int '0'"); - Assert.AreEqual(3, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "()())fghij", 2), "Error: char '(', char '), string '()())fghij', int '2'"); - Assert.AreEqual(10, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((())fghij", 0), "Error: char '(', char '), string '(()())ghij', int '0'"); - Assert.AreEqual(4, GDBParserUnitTests.find_Closing(Convert.ToSByte('('), Convert.ToSByte(')'), "((())fghij", 1), "Error: char '(', char '), string '((())fghij', int '1'"); - } - - [Test] - public void searchResponse() - { - // Add the values you want to test. - Assert.AreEqual(3, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 1, true, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '1', bool 'TRUE', char '?'"); - Assert.AreEqual(1, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 1, true, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '1', bool 'TRUE', char '@'"); - Assert.AreEqual(14, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 3, true, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '3', bool 'TRUE', char '?'"); - Assert.AreEqual(12, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 0, 3, true, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '0', int '3', bool 'TRUE', char '@'"); - Assert.AreEqual(19, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 10, 3, true, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '10', int '3', bool 'TRUE', char '?'"); - Assert.AreEqual(17, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 10, 3, true, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '10', int '3', bool 'TRUE', char '@'"); - Assert.AreEqual(24, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 1, false, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '1', bool 'TRUE', char '?'"); - Assert.AreEqual(24, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 1, false, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '1', bool 'TRUE', char '@'"); - Assert.AreEqual(19, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 3, false, Convert.ToSByte('?')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '3', bool 'TRUE', char '?'"); - Assert.AreEqual(19, GDBParserUnitTests.search_Response("aabbbcaabaccabcababaababc", "ab", 24, 3, false, Convert.ToSByte('@')), "Error: string 'aabbbcaabaccabcababaababc', string 'ab', int '24', int '3', bool 'TRUE', char '@'"); - } - - [Test] - public void substituteVariables() - { - string[] v = new string[10]; - v[0] = "The"; - v[1] = "text"; - v[2] = ""; - v[3] = ""; - v[4] = ""; - v[5] = "the"; - v[6] = ""; - v[7] = ""; - v[8] = ""; - v[9] = "number"; - // Add the values you want to test. - StringAssert.AreEqualIgnoringCase("The number of the words in the following text is smaller than the number of the letters in the same text\r\n", GDBParserUnitTests.substitute_Variables("$0$ $9$ of $5$ words in $5$ following $1$ is smaller $3$than $5$ $9$ of $5$ letters in $5$ same $1$$EOL$", v), "Error: string '', Variables array not printed."); - } - - [Test] - public void insertingCommandCodes() - { - string[,] map = new string[48, 2]; // The value for the first column of this array corresponds to the value of NumberOfInstructions constant, in gdb-connect.h. - string[] v = new string[48]; // The size of this array corresponds to the value of NumberOfInstructions constant, in gdb-connect.h. - bool result = GDBParserUnitTests.inserting_Command_Codes(map, v); - Assert.AreEqual(true, result); - Assert.IsNotEmpty(map, "Hash table could not be empty!"); - Assert.IsNotEmpty(v, "Parsing instructions array could not be empty!"); - } - - [Test] - public void getInstructionCode() - { - // The instruction code returned from get_Instruction_Code() function depends on the position the associated parsing instruction - // was stored in the respective data structure. That's why the following unit tests just compares the instruction code with -1 - // (-1 means that the instruction was not found). - string param = ""; - // Add the values you want to test. - Assert.AreEqual(-1, GDBParserUnitTests.get_Instruction_Code("", out param), "Error: string '', string ''"); - StringAssert.AreEqualIgnoringCase("", param, "Param should be empty."); - - param = ""; - Assert.AreNotEqual(-1, GDBParserUnitTests.get_Instruction_Code("-exec-continue --thread-group i1", out param), "Error: string '-exec-continue --thread-group i1', string ''"); - StringAssert.AreEqualIgnoringCase("", param, "Param should be empty for command '-exec-continue --thread-group i1'."); - - param = ""; - Assert.AreNotEqual(-1, GDBParserUnitTests.get_Instruction_Code("-break-delete 3", out param), "Error: string '-break-delete 3', string ''"); - StringAssert.AreEqualIgnoringCase(";3", param, "Param should not be empty for command '-break-delete 3'."); - - param = ""; - Assert.AreNotEqual(-1, GDBParserUnitTests.get_Instruction_Code("-break-after 4 10", out param), "Error: string '-break-after 4 10', string ''"); - StringAssert.AreEqualIgnoringCase(";4;10", param, "Param should not be empty for command '-break-after 4 10'."); - } - - [Test] - public void get_SeqID() - { - // Add the values you want to test. - Assert.AreEqual(211, GDBParserUnitTests.get_Seq_ID("211^done,value=\"1\""), "Error: string '211^done,value=\"1\"'"); - Assert.AreEqual(111, GDBParserUnitTests.get_Seq_ID("111^running"), "Error: string '111^running'"); - Assert.AreEqual(-3, GDBParserUnitTests.get_Seq_ID("=breakpoint-modified,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0xf7fd8502\",func=\"pendfunc1\",file=\"gdb/testsuite/gdb.mi/pendshr1.c\",fullname=\"/unsafegdb/testsuite/gdb.mi/pendshr1.c\",line=\"21\",times=\"0\",original-location=\"pendfunc1\"}"), "Error: string '=breakpoint-modified,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0xf7fd8502\",func=\"pendfunc1\",file=\"gdb/testsuite/gdb.mi/pendshr1.c\",fullname=\"/unsafegdb/testsuite/gdb.mi/pendshr1.c\",line=\"21\",times=\"0\",original-location=\"pendfunc1\"}'"); - Assert.AreEqual(-2, GDBParserUnitTests.get_Seq_ID("*stopped,reason=\"breakpoint-hit\",disp=\"keep\",bkptno=\"2\",frame={func=\"foo\",args=[],file=\"hello.c\",fullname=\"/home/foo/bar/hello.c\",line=\"13\"}"), "Error: string '*stopped,reason=\"breakpoint-hit\",disp=\"keep\",bkptno=\"2\",frame={func=\"foo\",args=[],file=\"hello.c\",fullname=\"/home/foo/bar/hello.c\",line=\"13\"}'"); - Assert.AreEqual(-2, GDBParserUnitTests.get_Seq_ID("111*stopped,signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={addr=\"0x00010140\",func=\"foo\",args=[],file=\"try.c\",line=\"13\"}"), "Error: string '111*stopped,signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={addr=\"0x00010140\",func=\"foo\",args=[],file=\"try.c\",line=\"13\"}'"); - Assert.AreEqual(-1, GDBParserUnitTests.get_Seq_ID("abcde"), "Error: string 'abcde'"); - Assert.AreEqual(-1, GDBParserUnitTests.get_Seq_ID(""), "Error: string ''"); - } - - [Test] - public void parseGDB1() - { - string asyncInst = "??=thread-exited,id;{#51\\;;??\";@@\";#$EOL$;};??thread-created,id;{#40\\;;??\";@@\";#\\;;??pid ;@@ ;#$EOL$;};0;??*running;{#41\\;;??thread-id=\"all;{#0;}{??thread-id=\";@@\";};#$EOL$;};0;??*stopped;{??breakpoint-hit;{#27\\;;??bkptno=\";@@\";#\\;;??file=\";@@\";#\\;;??line=\";@@\";}{??end-stepping-range;{#45;??file=\";{#\\;;@@\";0;#\\;;??line=\";@@\";};}{??function-finished;{#46;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};}{??exited-normally;{#42;}{??exit-code;{#43\\;;??\";@@\";}{??signal-received;{??signal-meaning=\"Killed\";{#47;}{??signal-meaning=\"Segmentation fault\";{#54\\;;??addr=\";@@\";#\\;;??func=\";@@\";0;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};}{#44\\;;??addr=\";@@\";#\\;;??func=\";@@\";0;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};};};}{??exited-signalled;{#55\\;??signal-name=\";@@\";#\\;;??signal-meaning=\";@@\";}{#44\\;;??addr=\";@@\";#\\;;??func=\";@@\";0;??file=;{#\\;;??\";@@\";#\\;;??line=\";@@\";};};};};};};};};#\\;;??thread-id=;{??\";@@\";};#$EOL$;};0;??=breakpoint-modified,bkpt=\\{number=\";{0;($EOR$;$1=?HResult = hr; - } - - property HRESULT HResult - { - HRESULT get() - { - return Exception::HResult; - } - } -}; - -END_NAMESPACE diff --git a/src_vs2012/GDBParser/Constants.cpp b/src_vs2012/GDBParser/Constants.cpp deleted file mode 100644 index c21d40d8..00000000 --- a/src_vs2012/GDBParser/Constants.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#include "stdafx.h" - -#pragma managed(on) - -BEGIN_NAMESPACE - -public ref class Constants -{ -public: - #undef S_OK - static const int S_OK = 0; - - #undef S_FALSE - static const int S_FALSE = 1; - - #define __E_NOTIMPL E_NOTIMPL - #undef E_NOTIMPL - static const int E_NOTIMPL = __E_NOTIMPL; - - #define __E_FAIL E_FAIL - #undef E_FAIL - static const int E_FAIL = __E_FAIL; - - static const int E_WIN32_INVALID_NAME = HRESULT_FROM_WIN32(ERROR_INVALID_NAME); - - static const int E_WIN32_ALREADY_INITIALIZED = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED); - - #define __RPC_E_SERVERFAULT RPC_E_SERVERFAULT - #undef RPC_E_SERVERFAULT - static const int RPC_E_SERVERFAULT = __RPC_E_SERVERFAULT; -}; - -END_NAMESPACE \ No newline at end of file diff --git a/src_vs2012/GDBParser/GDBParser.def b/src_vs2012/GDBParser/GDBParser.def deleted file mode 100644 index dae61e7a..00000000 --- a/src_vs2012/GDBParser/GDBParser.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY "GDBParser" - -EXPORTS -DllRegisterServer PRIVATE -DllUnregisterServer PRIVATE \ No newline at end of file diff --git a/src_vs2012/GDBParser/GDBParser.rc b/src_vs2012/GDBParser/GDBParser.rc deleted file mode 100644 index 66dfd246..00000000 --- a/src_vs2012/GDBParser/GDBParser.rc +++ /dev/null @@ -1,67 +0,0 @@ -// 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 - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#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 ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -IDR_GDBPARSER REGISTRY "GDBParser.rgs" - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - -IDR_GDBPARSER REGISTRY "GDBParser.rgs" - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src_vs2012/GDBParser/GDBParser.rgs b/src_vs2012/GDBParser/GDBParser.rgs deleted file mode 100644 index aa6344f9..00000000 --- a/src_vs2012/GDBParser/GDBParser.rgs +++ /dev/null @@ -1,59 +0,0 @@ -HKLM -{ - NoRemove SOFTWARE - { - NoRemove Microsoft - { - NoRemove VisualStudio - { - NoRemove 10.0 - { - NoRemove AD7Metrics - { - NoRemove Engine - { - '{D951924A-4999-42a0-9217-1EB5233D1D5A}' = s 'guidDebuggingSampleEngine' - { - val 'CLSID' = s '{8355452D-6D2F-41b0-89B8-BB2AA2529E94}' - val 'ProgramProvider' = s '{FF3E23A2-DA7E-4fa7-AF47-6EDEDE4E922E}' - val 'Attach' = d '1' - val 'AddressBP' = d '0' - val 'AutoSelectPriority' = d '4' - val 'CallstackBP' = d '1' - val 'Name' = s 'Sample Debug Engine' - val 'PortSupplier' = s '{708C1ECA-FF48-11D2-904F-00C04FA302A1}' - - 'IncompatibleList' - { - val 'guidCOMPlusNativeEng' = s '{92EF0900-2251-11D2-B72E-0000F87572EF}' - val 'guidCOMPlusOnlyEng' = s '{449EC4CC-30D2-4032-9256-EE18EB41B62B}' - val 'guidNativeOnlyEng' = s '{449EC4CC-30D2-4032-9256-EE18EB41B62B}' - val 'guidScriptEng' = s '{F200A7E7-DEA5-11D0-B854-00A0244A1DE2}' - } - } - } - } - - NoRemove CLSID - { - '{8355452D-6D2F-41b0-89B8-BB2AA2529E94}' - { - val 'Assembly' = s 'Microsoft.VisualStudio.Debugger.SampleEngine' - val 'Class' = s 'Microsoft.VisualStudio.Debugger.SampleEngine.AD7Engine' - val 'InprocServer32' = s 'c:\windows\system32\mscoree.dll' - val 'CodeBase' = s '%GDBPARSERPATH%\Microsoft.VisualStudio.Debugger.SampleEngine.dll' - } - - '{FF3E23A2-DA7E-4fa7-AF47-6EDEDE4E922E}' - { - val 'Assembly' = s 'Microsoft.VisualStudio.Debugger.SampleEngine' - val 'Class' = s 'Microsoft.VisualStudio.Debugger.SampleEngine.AD7ProgramProvider' - val 'InprocServer32' = s 'c:\windows\system32\mscoree.dll' - val 'CodeBase' = s '%GDBPARSERPATH%\Microsoft.VisualStudio.Debugger.SampleEngine.dll' - } - } - } - } - } - } -} \ No newline at end of file diff --git a/src_vs2012/GDBParser/GDBParser.vcxproj b/src_vs2012/GDBParser/GDBParser.vcxproj deleted file mode 100644 index 7266d145..00000000 --- a/src_vs2012/GDBParser/GDBParser.vcxproj +++ /dev/null @@ -1,165 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {CC7B28E0-CB31-44F7-A380-E7072F670F38} - GDBParser - Win32Proj - GDBParser - - - - DynamicLibrary - Unicode - true - true - v110 - - - DynamicLibrary - Unicode - true - v110 - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30305.0 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - C:\Users\guarnold.RIMNET\vsplugin-ndk\src\gdb-connect;$(SourcePath) - C:\Users\guarnold.RIMNET\vsplugin-ndk\src\gdb-connect;$(IncludePath) - $(ReferencePath) - $(LibraryPath) - - - - Disabled - C:\VSPlugin-Git\vsplugin-ndk\src\gdb-connect;$(ProgramFiles)\Microsoft Visual Studio 10.0\DIA SDK\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;DEBUG;%(PreprocessorDefinitions) - false - Default - MultiThreadedDebugDLL - Use - Level3 - ProgramDatabase - - - $(IntDir);%(AdditionalIncludeDirectories) - $(IntDir)GDBParser.res - - - true - psapi.lib;$(ProgramFiles)\Microsoft Visual Studio 11.0\DIA SDK\lib\diaguids.lib;%(AdditionalDependencies) - GDBParser.def - true - true - Windows - false - - - MachineX86 - - - - - - - - - $(VSInstallDir)\DIA SDK\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - MultiThreadedDLL - Use - Level3 - ProgramDatabase - - - true - psapi.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;%(AdditionalDependencies) - GDBParser.def - true - Windows - true - true - false - - - MachineX86 - - - xcopy "$(ProjectDir)Instructions.txt" "$(OutputPath)" /d /y - Copying Instructions.txt to output directory. - - - - - true - true - - - - - - - - false - - - false - - - - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src_vs2012/GDBParser/GDBParser.vcxproj.filters b/src_vs2012/GDBParser/GDBParser.vcxproj.filters deleted file mode 100644 index 5c165339..00000000 --- a/src_vs2012/GDBParser/GDBParser.vcxproj.filters +++ /dev/null @@ -1,74 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - {3bb6314f-66c5-4c9f-b290-dfa7cf75aeea} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - Resource Files - - - - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Internal Header files - - - Source Files\GDBParser API Header files - - - - - Resource Files - - - \ No newline at end of file diff --git a/src_vs2012/GDBParser/GDBParser.vcxproj.user b/src_vs2012/GDBParser/GDBParser.vcxproj.user deleted file mode 100644 index ace9a86a..00000000 --- a/src_vs2012/GDBParser/GDBParser.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src_vs2012/GDBParser/GDBParserAPI.cpp b/src_vs2012/GDBParser/GDBParserAPI.cpp deleted file mode 100644 index a12853d9..00000000 --- a/src_vs2012/GDBParser/GDBParserAPI.cpp +++ /dev/null @@ -1,854 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#include "stdafx.h" - -#pragma managed(on) - -#include -#include < stdio.h > -#include < stdlib.h > -#include < vcclr.h > -using namespace System; -using namespace System::Text::RegularExpressions; -using namespace Microsoft::Win32; - -#include "ProjInclude.h" - -// GDBParser API header files (in alphabetical order) -#include "GDBParserAPI.h" - -#include "gdb-connect.h" - -using namespace std; - - -/// -/// Set an auto pointer given a String^. -/// -/// String. -/// Auto pointer. -CAutoPtr convertToAutoPtrFromString(String^ str) { - CAutoPtr ap; - - pin_ptr pkwc = PtrToStringChars(str); - char* pc = new char[(wcslen(pkwc) + 1) * sizeof(char)]; - ap.Attach(pc); - - // Convert wchar_t* to a char* - size_t origsize = wcslen(pkwc) + 1; - size_t convertedChars = 0; - wcstombs_s(&convertedChars, ap, origsize, pkwc, _TRUNCATE); - - return ap; -} - - -/// -/// Gets a parsed asynchronous GDB response from Output Buffer. Also can get a parsed GDB response for a non-synchronous GDB -/// COMMAND from Output buffer. This method is called by the Event Dispather of the Debug Engine. -/// -/// Parsed GDB response. -String^ GDBParser::removeGDBResponse() -{ - char output[ParsedMessageSize] = ""; - removeFromOutputBuffer(output); - String ^systemstring = gcnew String(output); - return systemstring; -} - - -/// -/// Sends a non-synchronous GDB command by adding it into the Input Buffer. This method is called by the Debug Engine whenever -/// it needs to send a GDB command without having to wait for the respective GDB response. -/// -/// Command to be sent to GDB. -/// True. -bool GDBParser::addGDBCommand(String^ GDBCommand) -{ - CAutoPtr apCmd = convertToAutoPtrFromString(GDBCommand); - while (!addIntoInputBuffer(apCmd)); // Keep trying until it is added into Input buffer - return(true); -} - - -/// -/// Exits GDB. This method is called to end the debug session by Event Dispatcher (Debug Engine) or directly by the debug engine -/// when it fails to launch a new debug session. -/// -void GDBParser::exitGDB() -{ - // Sends the command that exits GDB immediately. - // (http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html) - addGDBCommand("-gdb-exit"); - GDBConsole::shutdown(); - s_running = false; - if (m_BBConnectProcess) - TerminateProcess(m_BBConnectProcess, 0); -} - - -/// -/// Verify if Input buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool GDBParser::is_Input_Buffer_Empty() -{ - return(isInputBufferEmpty()); -} - - -/// -/// Sends a synchronous GDB command by adding it into the Input Buffer and waiting for the respective GDB response. This -/// method is called by the Debug Engine whenever it needs a GDB response for a given GDB command. -/// -/// Command to be sent to GDB. -/// Instruction ID. -/// Parsed GDB response. -String^ GDBParser::parseCommand(String^ GDBCommand, int ID) -{ - char output[ParsedMessageSize] = ""; - CAutoPtr apCmd; - if (ID < 10) - apCmd = convertToAutoPtrFromString("0" + ID + GDBCommand); - else - apCmd = convertToAutoPtrFromString(ID + GDBCommand); - - while (!addIntoInputBuffer(apCmd) && s_running) - Sleep(0); // keep trying to add into buffer - - while (strcmp(output,"") == 0 && s_running) - removeSyncFromOutputBuffer(output, ID); - if (strcmp(output,"$#@EMPTY@#$") == 0) // This string means that both GDB and the parser worked well and returned an empty string. - strcpy(output,""); - - String ^systemstring = gcnew String(output); - return systemstring; -} - - -/// -/// Sets the NDK variables. -/// -/// Boolean value that indicates which of the simulator/device is being used: -/// True -> simulator; -/// False -> Device. -void GDBParser::setNDKVars(bool isSimulator) { - String^ keyPath = "HKEY_CURRENT_USER\\Software\\BlackBerry\\BlackBerryVSPlugin"; - String^ ndkHostPath = (String^)Registry::GetValue(keyPath, "NDKHostPath", ""); - String^ ndkTargetPath = (String^)Registry::GetValue(keyPath, "NDKTargetPath", ""); - m_remotePath = (String^)Registry::GetValue(keyPath, "NDKRemotePath", ""); - - if (isSimulator) { - m_pcGDBCmd = ndkHostPath + "\\usr\\bin\\ntox86-gdb.exe --interpreter=mi2"; - m_libPaths[0] = ndkTargetPath + "\\x86\\lib"; - m_libPaths[1] = ndkTargetPath + "\\x86\\usr\\lib"; - } else { - m_pcGDBCmd = ndkHostPath + "\\usr\\bin\\ntoarm-gdb.exe --interpreter=mi2"; - m_libPaths[0] = ndkTargetPath + "\\armle-v7\\lib"; - m_libPaths[1] = ndkTargetPath + "\\armle-v7\\usr\\lib"; - } - - // Escape backslashes for strings that will be sent to GDB - String^ pattern = "\\\\"; // one backslash - String^ replacement = "\\\\\\\\"; // two backslashes - Regex^ r = gcnew Regex(pattern); - - String^ regexResult; - for (int i = 0; i < NUM_LIB_PATHS; i++) { - regexResult = r->Replace(m_libPaths[i], replacement); - m_libPaths[i] = regexResult; - } -} - - -/// -/// Run BlackBerryConnect to stablish a connection with the device/simulator. -/// -/// Device/Simulator IP. -/// NDK full path. -/// Public key full path. -/// Device/simulator password. -void GDBParser::BlackBerryConnect(String^ IPAddrStr, String^ toolsPath, String^ publicKeyPath, String^ password) -{ - CAutoPtr apDevice = convertToAutoPtrFromString(IPAddrStr); - CAutoPtr apTools = convertToAutoPtrFromString(toolsPath); - CAutoPtr apKey = convertToAutoPtrFromString(publicKeyPath); - - CAutoPtr apPass; - if (!String::IsNullOrEmpty(password)) - apPass = convertToAutoPtrFromString(password); - - LPCTSTR lpApplicationName = NULL; - PROCESS_INFORMATION pi; - STARTUPINFOA si; - DWORD flags = 0; - - memset(&pi, 0, sizeof(pi)); - - // Set up the start up info struct. - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); -#if !defined (SHOW_BB_CONNECT_WINDOW) - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; -#endif - - char args[256]; - if (!String::IsNullOrEmpty(password)) - sprintf(args, "java.exe -Xmx512M -jar \"%s\\..\\lib\\Connect.jar\" %s -password %s -sshPublicKey \"%s\"", apTools, apDevice, apPass, apKey); - else - sprintf(args, "java.exe -Xmx512M -jar \"%s\\..\\lib\\Connect.jar\" %s -sshPublicKey \"%s\"", apTools, apDevice, apKey); - - // Launch the process - if (!CreateProcessA(NULL, args, NULL, NULL, TRUE, - flags, NULL, NULL, &si, &pi)) - ErrorExit(_T("CreateProcess: BlackBerry-Connect")); - - m_BBConnectProcess = pi.hProcess; -} - - -/// -/// Execute GDB only to get the list of running processes in the Device/Simulator -/// -/// Device/Simulator IP. -/// Device/simulator password. -/// TRUE when using the Simulator, FALSE when using the Device. -/// NDK full path. -/// Public key full path. -/// How many seconds to wait for connecting to the device. -/// A string with the list of running processes. -String^ GDBParser::GetPIDsThroughGDB(String^ IP, String^ password, bool isSimulator, String^ toolsPath, String^ publicKeyPath, int timeout) -{ - string response; - string parsed; - m_BBConnectProcess = NULL; - char pcCmd[256]; - - // Run BlackBerryConnect - BlackBerryConnect(IP, toolsPath, publicKeyPath, password); - - // Get device (IP address) - CAutoPtr ip = convertToAutoPtrFromString(IP); - - // Set NDK Variables - setNDKVars(isSimulator); - - // Convert GDB command to wchar_t* since GDBWrapper.exe requires a Unicode argument - pin_ptr pkwcGDBCmd = PtrToStringChars(m_pcGDBCmd); - const size_t newsizew = (wcslen(pkwcGDBCmd) + 1) * sizeof(wchar_t); - wchar_t* pwcGDBCmd = new wchar_t[newsizew]; - wcscpy_s(pwcGDBCmd, newsizew, pkwcGDBCmd); - CAutoPtr apGDBCmd; - apGDBCmd.Attach(pwcGDBCmd); - - // Get GDB Console - GDBConsole::setGDBPath(apGDBCmd); - GDBConsole* console = GDBConsole::getInstance(); - - // Convert library paths - CAutoPtr libPaths[NUM_LIB_PATHS]; - for (int i = 0; i < NUM_LIB_PATHS; i++) { - libPaths[i] = convertToAutoPtrFromString(m_libPaths[i]); - } - - /// Send intialization commands to GDB - response = console->waitForPrompt(true); - if ((response == "") || (response[0] == '!')) //found an error - { - // ??? load output console window with the parsed message. - response = ""; - } - - if (response != "") - { -// sprintf(pcCmd, "set debug nto-debug 2\r\n"); -// console->sendCommand(pcCmd); -// response = console->waitForPrompt(true); - - sprintf(pcCmd, "1-target-select qnx %s:8000\r\n", ip); - console->sendCommand(pcCmd); - response = console->waitForPromptWithTimeout(timeout); - if ((response == "") || (response[0] == '!')) //found an error - { - // ??? load output console window with the parsed message. - response = ""; - } - - if ((response != "") && (response != "TIMEOUT!") && (response.find("1^error,msg=",0) == -1)) //there is no error from previous response - { - sprintf(pcCmd, "info pidlist\r\n"); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - if ((response == "") || (response[0] == '!')) //found an error - { - // ??? load output console window with the parsed message. - response = ""; - } - } - } - exitGDB(); - String ^systemString = gcnew String(response.c_str()); - return systemString; -} - - -/// -/// Launch the GDB Debug Process. -/// -/// ID of the running process to be debugged. -/// Full path of the executable file. -/// Device/Simulator IP. -/// TRUE when using the Simulator, FALSE when using the Device. -/// NDK full path. -/// Public key full path. -/// Device/simulator password. -/// True -> succeeded; -/// False -> failed. -bool GDBParser::LaunchProcess(String^ pidStr, String^ exeStr, String^ IPAddrStr, bool isSimulator, String^ toolsPath, String^ publicKeyPath, String^ password) -{ - string response; - string parsed; - s_running = true; - m_BBConnectProcess = NULL; - char pcCmd[256]; - - // Run BlackBerryConnect - BlackBerryConnect(IPAddrStr, toolsPath, publicKeyPath, password); - - // Get PID - CAutoPtr apPid = convertToAutoPtrFromString(pidStr); - long int pid = strtol(apPid, NULL, 10); - if (pid == 0) { - return false; - } - - // Get device (IP address) - CAutoPtr apDevice = convertToAutoPtrFromString(IPAddrStr); - - // Get binary file path - CAutoPtr apBinaryFile; - if (exeStr == "CannotAttachToRunningProcess") - apBinaryFile = convertToAutoPtrFromString(""); - else - apBinaryFile = convertToAutoPtrFromString(exeStr); - - // Set NDK Variables - setNDKVars(isSimulator); - - // Convert GDB command to wchar_t* since GDBWrapper.exe requires a Unicode argument - pin_ptr pkwcGDBCmd = PtrToStringChars(m_pcGDBCmd); - const size_t newsizew = (wcslen(pkwcGDBCmd) + 1) * sizeof(wchar_t); - wchar_t* pwcGDBCmd = new wchar_t[newsizew]; - wcscpy_s(pwcGDBCmd, newsizew, pkwcGDBCmd); - CAutoPtr apGDBCmd; - apGDBCmd.Attach(pwcGDBCmd); - - // Get GDB Console - GDBConsole::setGDBPath(apGDBCmd); - GDBConsole* console = GDBConsole::getInstance(); - - // Convert library paths - CAutoPtr libPaths[NUM_LIB_PATHS]; - for (int i = 0; i < NUM_LIB_PATHS; i++) { - libPaths[i] = convertToAutoPtrFromString(m_libPaths[i]); - } - - // initializing the parsing data structures, buffers and thread - HANDLE sendingThread; - unsigned threadID; - unordered_map commandCodesMap; - string parsingInstructions[NumberOfInstructions]; - - cleanBuffers(); - if(!insertingCommandCodes(&commandCodesMap, parsingInstructions)) - { - printf("Error initializing parsing data structures"); - return false; - } - - /// Send intialization commands to GDB - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[2]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - -// sprintf(pcCmd, "set debug nto-debug 2\r\n"); -// console->sendCommand(pcCmd); -// response = console->waitForPrompt(true); - - sprintf(pcCmd, "1-gdb-set breakpoint pending on\r\n"); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[8]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - - sprintf(pcCmd, "4-target-select qnx %s:8000\r\n", apDevice); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[3]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - - sprintf(pcCmd, "5-file-exec-and-symbols %s\r\n", apBinaryFile); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[7]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - - if (m_remotePath != "") - { - m_remotePath = m_remotePath + "\\lib;" + m_remotePath + "\\usr\\lib;" + m_remotePath + "\\usr\\lib\\qt4"; - CAutoPtr apPath = convertToAutoPtrFromString(m_remotePath); - sprintf(pcCmd, "6set solib-search-path %s\r\n", apPath); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[8]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - } - - sprintf(pcCmd, "7-target-attach %d\r\n", pid); - console->sendCommand(pcCmd); - response = console->waitForPrompt(true); - parsed = parseGDB(response, parsingInstructions[6]); - if ((parsed == "") || (parsed[0] == '!')) //found an error - { - // TODO: load output console window with the response. - return false; - } - -// start thread responsible for reading InputBuffer and sending commands to GDB. -// Thread must start after initializing GDB with the previous instructions because: -// - this thread will start another one (listening GDB) that will start consuming GDB responses. So, the above waitForPrompt would -// never get a result and this method would freeze. -// - the previous commands don't use the GDB Buffer, so the results wouldn't be parsed correctly. - sendingThread = (HANDLE)_beginthreadex( NULL, 0, &sendingCommands2GDB, (void *)console, 0, &threadID); - - return true; -} - - - - -// From this point on it is implemented the interface that allows creating unit tests for gdb-connect functions. Don't use these methods -// for something else because they need some resources that are allocated correctly when launching GDB the right way, i.e., by using the -// above GDBParser::LaunchProcess method. To be able to run the unit tests, it is needed to create mock resources or call -// GDBParser::LaunchProcess method first, because it will allocate the needed resources and will start GDB. - - -/// -/// Get the associated instruction ID from the command that would be sent to GDB. -/// -/// Command that would be sent to GDB. -/// When the instruction code stored in "map" is negative, it means that the commands parameters should be saved to -/// be used by the listeningGDB thread. When that happens, update and return variable "param". -/// Returns the instruction code for the command that would be sent to GDB or -1 in case of an error. It can also return the -/// command parameters, as it was described above. -int GDBParserUnitTests::get_Instruction_Code(String^ command, [Runtime::InteropServices::Out] String^ %param) -{ - CAutoPtr apCmd = convertToAutoPtrFromString(command); - string c = apCmd; - string p = ""; - - unordered_map map; - string v[NumberOfInstructions]; - - // First create the hash table map. - bool result = insertingCommandCodes(&map, v); - - int code = -2; - - if (result == 1) - { - code = getInstructionCode(c, map, &p); - param = gcnew String(p.c_str()); - } - return code; -} - - -/// -/// Get the sequential ID of the supposed response. -/// -/// The supposed GDB response. -/// If the supposed response is synchronous, this ID corresponds to the sequential ID of the command that should be sent to GDB -/// that generated such supposed response. If the supposed response is asynchronous, there is no sequential ID, so it returns: -/// -3 - when it shows that a supposed breakpoint was modified; -/// -2 - for any other supposed asynchronous response -/// -1 - when the supposed response is not completed or in case of an error. -int GDBParserUnitTests::get_Seq_ID(String^ response) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - return getSeqID(r); -} - - -/// -/// Initialize the hash map data structure "map" in which each entry contains a GDB command that is currently recognized by -/// the parser with its respective instruction ID. It loads these information from Instructions.txt file, in where each line has the -/// following format: -/// {$}gdb-command:->:parsing-instruction; -/// It must have the $ sign in front of the GDB command when it is needed to store the command parameters to be used later by the -/// listeningGDB thread. This usually happens whenever the GDB response for a given command does not contains enough information, like -/// only "^done" for example, when the parser needs something else. The ":->:" separates the GDB command from the parsing Instruction. -/// -/// Array that contains all the data from the Hash map created by insertingCommandCodes() function, that are the GDB -/// commands recognized by the parser and their respectives instructions IDs. -/// A string array with all of the currently recognized parsing instructions. The index position -/// correponds to the instruction ID used in "map" for the respective GDB command. -/// 1 in case of sucess; 0 if there is an error when opening the Instructions.txt file. -bool GDBParserUnitTests::inserting_Command_Codes(array^ map, array^ parsingInstructions) -{ - unordered_map m; - string v[NumberOfInstructions]; - - bool result = insertingCommandCodes(&m, v); - - for (int i = 0; i < NumberOfInstructions; i++) - { - parsingInstructions[i] = gcnew String(v[i].c_str()); - } - - int i = 0; - for (unordered_map::iterator it = m.begin(); it != m.end(); ++it) - { - map[i,0] = gcnew String(it->first.c_str()); - map[i,1] = Convert::ToString(it->second); - i++; - } - - return result; -} - - -/// -/// Function used to call the parser that will parse a supposed GDB response according to the supposed parsing instruction, returning -/// this parsed response. This function is called when starting GDB (this one doesn't use the OutputBuffer because it returns the supposed -/// parsed response). -/// -/// Supposed GDB response. -/// Instruction used to parse the supposed GDB response. -/// Returns the parsed GDB response. -String^ GDBParserUnitTests::parse_GDB(String^ response, String^ parsingInstruction) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - string output = parseGDB(r, p); - String ^systemstring = gcnew String(output.c_str()); - return systemstring; -} - - -/// -/// Function used to call the parser that will parse a supposed GDB response according to the supposed parsing instruction, storing -/// the parsed response in the respective position in the Output Buffer. Must be used together with the functions that create and handle -/// the Output Buffer. DON'T CALL THIS METHOD PASSING A POSITION OF OUTPUT BUFFER THAT IS ALREADY FILLED! parseGDB(string, string, int) is -/// used in an environment that has a different thread consuming items from Output Buffer. In this initial unit tests environment only -/// the current thread is running, which means that, if you try to add data to a non-empty position, this method will be busy-waiting till -/// that entry is empty, causing, in this scenario, a DEADLOCK. -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Position in the Output Buffer in which the parsed response will be stored. -void GDBParserUnitTests::parse_GDB(String^ response, String^ parsingInstruction, int position) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - parseGDB(r, p, position); -} - - -/// -/// Reponsible for parsing a supposed GDB response. Depending on the parsing instruction, the parser can get the first occurrence -/// from the supposed GDB response or get all of them that satisfies this parsing instruction. -/// -/// Supposed GDB response. -/// Instruction used to parse the supposed GDB response. -/// Current character to be read in the supposed GDB response. -/// If the parsing instruction specifies that it has to get all occurences from the supposed GDB response, this -/// value must be true. -/// A variable stores a string parsed from the supposed GDB response and can be used as many times as needed to -/// created the parsed response. Up to 10 variables can be created for a given parsing instruction. -/// If the parsing instruction allows the parser to get all occurrences from the supposed GDB response, this -/// separator will be used at the end of each occurence. The default one is '#' but it can be specified in the parsing instruction. -/// Returns the parsed GDB response. -String^ GDBParserUnitTests::parse_GDB(String^ response, String^ parsingInstruction, int respBegin, bool repeat, array^ variables, String^ separator) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - CAutoPtr apSep = convertToAutoPtrFromString(separator); - string s = apSep; - - char v[10][128]; - for (int i = 0; i< 10; i++) - { - CAutoPtr apAux = convertToAutoPtrFromString(variables[i]); - string aux = apAux; - - if (aux.length() > 128) - aux[127] = '\0'; - strcpy(v[i], aux.c_str()); - } - - string output = parseGDB(&r, p, respBegin, repeat, v, s); - String ^systemstring = gcnew String(output.c_str()); - return systemstring; -} - - -/// -/// Find the position of the associated closing bracket/parenthesis. -/// -/// The associated opening character ("(", "{" or "["). -/// The associated closing character (")", "}" or "]"). -/// The string where the search will be made. -/// Start position in the parsingInstruction string. This position normally corresponds to the position of the opening -/// character, but it could be smaller than that (never bigger!). However, if it is smaller, it cannot have the same character between -/// the 'ini' position and the corresponding one for the opening one. If need to have another one, precede it by the character '\'. -/// Returns the position of the associated closing bracket/parenthesis. If it is not found, returns the length of the string. -int GDBParserUnitTests::find_Closing(char opening, char closing, String^ parsingInstruction, int ini) -{ - CAutoPtr apPars = convertToAutoPtrFromString(parsingInstruction); - string p = apPars; - return findClosing(opening, closing, p, ini); -} - - -/// -/// Get the next position of a given character (token) in a string message (txt), starting from a given position (pos). -/// -/// Character to search for. -/// String message in which it will search for the given character. -/// Starting position in the string message. -/// An integer that corresponds to the next position of the character in the string. If the character is not found, returns -/// the length of the string. -int GDBParserUnitTests::get_Next_Char(char token, String^ txt, int pos) -{ - CAutoPtr apTxt = convertToAutoPtrFromString(txt); - string t = apTxt; - return getNextChar(token, t, pos); -} - - -/// -/// Get the position of a given string (txt) in the string "response", starting from a given position (begin). -/// -/// String response where the search will be performed. -/// String to search for in the response. -/// Starting position in the string response. -/// Search for that string "times" times. Ex: I want to find the third occurrence of word "qaqa" in the -/// response. -/// Direction: if true, search forwards; if not, search backwards -/// The kind of parsing instruction that called this method. '?', '@', or '~'. If searching forward and '?', the -/// function will return the next position after the found string. If not, will return the first position of the found string. -/// An integer that corresponds to the next position of the string txt in the response. -1 in case of an error. -int GDBParserUnitTests::search_Response(String^ response, String^ txt, int begin, int times, bool forward, char instruction) -{ - CAutoPtr apResp = convertToAutoPtrFromString(response); - string r = apResp; - CAutoPtr apTxt = convertToAutoPtrFromString(txt); - string t = apTxt; - return searchResponse(r, t, begin, times, forward, instruction); -} - - -/// -/// Substitute the existing variables in the string "txt" by their values, stored in the "variables" array. Each variable name -/// has this format: $9$, where $ characters are used to identify the variable while the number corresponds to the variable ID, that also -/// corresponds to the array index. There is a special variable "$EOL$" that is substituted by "\r\n". -/// -/// String to search for variables. -/// Array with the variable values. -/// Returns the new modified string. -String^ GDBParserUnitTests::substitute_Variables(String^ txt, array^ variables) -{ - CAutoPtr apTxt = convertToAutoPtrFromString(txt); - string t = apTxt; - char v[10][128]; - for (int i = 0; i< 10; i++) - { - CAutoPtr apAux = convertToAutoPtrFromString(variables[i]); - string aux = apAux; - - if (aux.length() > 128) - aux[127] = '\0'; - strcpy(v[i], aux.c_str()); - } - string output = substituteVariables(t, v); - String ^systemstring = gcnew String(output.c_str()); - return systemstring; -} - - -/// -/// This method stores a command that should be sent to GDB. Input buffer is a circular one. -/// -/// Command that should be sent to GDB. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool GDBParserUnitTests::add_Into_Input_Buffer(String^ command) -{ - CAutoPtr apCmd = convertToAutoPtrFromString(command); - char GDBCommand[GDBCommandSize]; - strcpy(GDBCommand, apCmd); - return addIntoInputBuffer(GDBCommand); -} - - -/// -/// Gets the next command that would be sent to GDB. Input buffer is a circular one. -/// -/// Returns the next command that would be sent to GDB. -String^ GDBParserUnitTests::remove_From_Input_Buffer() -{ - char command[GDBCommandSize] = ""; - removeFromInputBuffer(command); - string basicstring(command); - return(gcnew String(basicstring.c_str())); -} - - -/// -/// Verify if Input buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -//bool GDBParserUnitTests::is_Input_Buffer_Empty() -//{ -// return isInputBufferEmpty(); -//} - - -/// -/// For every command that should be to GDB, the following parameters should be added into GDBBuffer. -/// -/// Sequential ID of the command that would be sent to GDB. It is used to identify, when evaluating supposed GDB -/// responses, which command generated that given response. This ID is also used to specify the location in which this entry will be -/// stored in this buffer. -/// Each command that should be sent to GDB has an associated instruction code, that corresponds to the -/// parsing instruction that will be used to parse the supposed GDB response. -/// Used to store the GDB command parameters, so they could be used during the parsing task. There are some GDB -/// commands, like -break-delete for example, that results in a simple "^done" GDB response. The parser can identify which command -/// caused that response but cannot know what was affected by it (considering the -break-delete command, the parser will know that some -/// breakpoint was successfully deleted but won't know which of them was deleted). Using "param" helps the parser letting it knows -/// which parameters were sent together with a given GDB command. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool GDBParserUnitTests::add_Into_GDB_Buffer(int seq_id, int instructionCode, String^ param) -{ - CAutoPtr apParam = convertToAutoPtrFromString(param); - string p = apParam; - return addIntoGDBBuffer(seq_id, instructionCode, p); -} - - -/// -/// This method is called to find the right parsing instruction for the supposed GDB response. -/// -/// Sequential ID of the GDB response. -/// Returns the parameters sent together with the GDB command that generated this response, if there are some. -/// Returns the instruction code associated to the sequential id (seq). -int GDBParserUnitTests::remove_From_GDB_Buffer(int seq, [Runtime::InteropServices::Out] String^ %param) -{ - string p = ""; - int code = removeFromGDBBuffer(seq, &p); - param = gcnew String(p.c_str()); - return code; -} - - -/// -/// Verify if GDB buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool GDBParserUnitTests::is_GDB_Buffer_Empty() -{ - return isGDBBufferEmpty(); -} - - -/// -/// Store the supposed parsed GDB response in the "seq_stamp" position of the Output buffer. -/// -/// Position in the Output buffer to store the supposed parsed GDB response. -/// Supposed parsed GDB response. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool GDBParserUnitTests::add_Into_Output_Buffer(int seq_stamp, String^ message) -{ - CAutoPtr apResp = convertToAutoPtrFromString(message); - char parsedMessage[GDBCommandSize]; - strcpy(parsedMessage, apResp); - return addIntoOutputBuffer(seq_stamp, parsedMessage); -} - - -/// -/// This method returns the next supposed parsed GDB response (output) for a supposed asynchronous GDB RESPONSE or a supposed non -/// synchronous GDB COMMAND. This managed part of Output buffer is circular. -/// -/// Returns the supposed parsed GDB response. -String^ GDBParserUnitTests::remove_From_Output_Buffer() -{ - char response[GDBCommandSize] = ""; - removeFromOutputBuffer(response); - string basicstring(response); - return(gcnew String(basicstring.c_str())); -} - - -/// -/// This method returns the supposed parsed GDB response (output) for a supposed synchronous GDB COMMAND (ID). Each entry in this part -/// of Output buffer was previously reserved for each GDB command. -/// -/// Returns the supposed parsed GDB response. -/// ID of the supposed GDB command. -String^ GDBParserUnitTests::remove_Sync_From_Output_Buffer(int ID) -{ - char response[GDBCommandSize] = ""; - removeSyncFromOutputBuffer(response, ID); - string basicstring(response); - return(gcnew String(basicstring.c_str())); -} - - -/// -/// Initialize / clean all the existing buffers: inputBuffer, GDBBuffer, outputBuffer. -/// -void GDBParserUnitTests::clean_Buffers() -{ - cleanBuffers(); -} diff --git a/src_vs2012/GDBParser/GDBParserAPI.h b/src_vs2012/GDBParser/GDBParserAPI.h deleted file mode 100644 index 1dfcfc97..00000000 --- a/src_vs2012/GDBParser/GDBParserAPI.h +++ /dev/null @@ -1,83 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -#include - -#define NumberOfInstructions 48 -#define GDBCommandSize 256 - -using namespace std; - -BEGIN_NAMESPACE - -public ref class GDBParser abstract sealed -{ -public: - static String^ GetPIDsThroughGDB(String^, String^, bool, String^, String^, int); - static bool LaunchProcess(String^, String^, String^, bool, String^, String^, String^); - static void BlackBerryConnect(String^, String^, String^, String^); - - static String^ parseCommand(String^, int); - static String^ removeGDBResponse(); - static bool addGDBCommand(String^); - static bool is_Input_Buffer_Empty(); - static void exitGDB(); - - static bool s_running = false; - -private: - static void setNDKVars(bool); - - static DWORD s_mainThreadId; - static String^ m_pcGDBCmd; - static const int NUM_LIB_PATHS = 2; - static array^ m_libPaths = gcnew array(NUM_LIB_PATHS); - static HANDLE m_BBConnectProcess; - static String^ m_remotePath; -}; - -END_NAMESPACE - - -BEGIN_NAMESPACE - -public ref class GDBParserUnitTests abstract sealed -{ -public: - static int get_Instruction_Code(String^, [Runtime::InteropServices::Out] String^ %); - static int get_Seq_ID(String^); - static bool inserting_Command_Codes(array^, array^); - - static String^ parse_GDB(String^, String^); - static void parse_GDB(String^, String^, int); - static String^ parse_GDB(String^, String^, int, bool, array^, String^); - - static int find_Closing(char, char, String^, int); - static int get_Next_Char(char, String^, int); - static int search_Response(String^, String^, int, int, bool, char); - static String^ substitute_Variables(String^, array^); - - static bool add_Into_Input_Buffer(String^); - static String^ remove_From_Input_Buffer(); - static bool add_Into_GDB_Buffer(int, int, String^); - static int remove_From_GDB_Buffer(int, [Runtime::InteropServices::Out] String^ %); - static bool is_GDB_Buffer_Empty(); - static bool add_Into_Output_Buffer(int, String^); - static String^ remove_From_Output_Buffer(); - static String^ remove_Sync_From_Output_Buffer(int); - static void clean_Buffers(); -}; -END_NAMESPACE \ No newline at end of file diff --git a/src_vs2012/GDBParser/Instructions.txt b/src_vs2012/GDBParser/Instructions.txt deleted file mode 100644 index 1389d642..00000000 --- a/src_vs2012/GDBParser/Instructions.txt +++ /dev/null @@ -1,48 +0,0 @@ -asynchronous:->:??=thread-exited,id;{#51\;;??";@@";#$EOL$;};??thread-created,id;{#40\;;??";@@";#\;;??pid ;@@ ;#$EOL$;};0;??*running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};#$EOL$;};0;??*stopped;{??breakpoint-hit;{#27\;;??bkptno=";@@";#\;;??file=";@@";#\;;??line=";@@";}{??end-stepping-range;{#45;??file=";{#\;;@@";0;#\;;??line=";@@";};}{??function-finished;{#46;??file=;{#\;;??";@@";#\;;??line=";@@";};}{??exited-normally;{#42;}{??exit-code;{#43\;;??";@@";}{??signal-received;{??signal-meaning="Killed";{#47;}{??signal-meaning="Segmentation fault";{#54\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};}{??signal-meaning="Aborted";{#55\;;0;??signal-name=";@@";#\;;??signal-meaning=";@@";}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};}{??exited-signalled;{#55\;;0;??signal-name=";@@";#\;;??signal-meaning=";@@";}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};};};};};#\;;??thread-id=;{??";@@";};#$EOL$;};0;??=breakpoint-modified,bkpt=\{number=";{0;($EOR$;$1=?:($EOR$;$1=?:??(gdb);{0;#80\;";(??~";?:??^connected;{0;#80\;";(??~";?:??^done;{0;#80\;";(??~";?:??^done;#File uploaded!; --target-attach:->:??^done;{#state="stopped"\;processID=";0;??pid=";@@";#"\;thread-ID=";??thread-created,id=";@@";0;#"\;$EOL$80\;";(??~";?:??^done;#File and symbols loaded.; --gdb-set:->:??^done;{#done;}; -set:->:??^done;{#done;}; --exec-arguments:->:??^done;#Arguments loaded.; --exec-run:->:??^running;{0;#40\;;??thread-created,id=";@@";0;??pid=";#\;;@@";0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??=breakpoint-created;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{??^error;{#ERROR: ;??msg=";@@";#$EOL$;(??&";#80\;";?:??^done;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{#Function not found!;}; --break-watch:->:??^done;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{#Function not found!;}; -$-break-delete:->:??^done;{#25;@@$EOL$}; -$-break-disable:->:??^done;{#24;@@$EOL$}; -$-break-enable:->:??^done;{#23;@@$EOL$}; -$-break-after:->:??^done;{#26;@@$EOL$}; -$-break-condition:->:??^done;{#28;@@$EOL$}; --break-list:->:??^done;{(??number=";#21\;;@@";#\;;??enabled=";@@";#\;;??addr=";@@";#\;;??func=";@@";#\;;??file=";@@";#\;;??line=";@@";#\;;??times=";@@";):$EOL$;}; -kill:->:??^done;{#done;}; -generate-core-file:->:#NOT CREATED! -jump:->:#NOT CREATED! -handle:->:#NOT CREATED! -watch:->:#NOT CREATED! -interrupt:->:#NOT CREATED! -show:->:#NOT CREATED! --stack-info-depth:->:??^done,depth=";@@";$EOL$ --stack-list-frames:->:??^done;{(??level=;{??";@@";};~"\};#\;;??addr=;{??";@@";};#\;;??func=;{??";@@";};#\;;??file=;{??";@@";};#\;;??line=;{??";@@";};);}; --stack-select-frame:->:??^done;{#done;}; --stack-list-variables:->:??^done;{#70\;;(??name=;{??";@@";};~"\};#\;;??arg=;{??";@@";};#\;;??type=;{??";@@";};#\;;??value=;{??";@@";};);}{#ERROR;}; --var-create:->:??^done;{??numchild=";@@";}{#ERROR;}; --var-delete:->:??^done;{#DONE;}{#ERROR;}; --var-list-children:->:??^done;{#71\;;(??name=;{??";@@";};~"\};#\;;??numchild=;{??";@@";};#\;;??value=;{??";@@";};#\;;??type=;{??";@@";};);}{#ERROR;}; --data-evaluate-expression:->:??^done;{??=;#60\;;@@$EOL$;}{??^error;{??-data-evaluate-expression: Usage: -data-evaluate-expression expression;{#61\;Error in expression.;}{??A syntax error in expression, near `'.;{#61\;A syntax error at the end of the expression.;}{??=;#61\;;@@$EOL$;};};};}; -ptype:->:??type = ;{@@\\n";}{# ;}; -whatis:->:??type = ;{@@\\n";}{# ;}; --exec-interrupt:->:??^done;{??signal-received;{??signal-meaning="Killed";{#47;}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};#\;;??thread-id=;{??";@@";}; --target-detach:->:#NOT CREATED! --var-info-num-children:->:??numchild;{??";@@";}{#ERROR;}; -info:->:??Address;{??0x;?:??^done;{(??\{id=";@@";#\;;??state=;{??";@@";};#\;;~\};?:??^done;{#done;}; diff --git a/src_vs2012/GDBParser/ProjInclude.h b/src_vs2012/GDBParser/ProjInclude.h deleted file mode 100644 index 047d620a..00000000 --- a/src_vs2012/GDBParser/ProjInclude.h +++ /dev/null @@ -1,33 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -using namespace System; -using namespace System::Diagnostics; -#include -#pragma warning(push) -#pragma warning(disable:4091) -#include -#pragma warning(pop) - -#define ASSERT(cond) _ASSERT(cond) -#ifdef DEBUG - #define VERIFY(statement) Debug::Assert((statement) != 0, #statement) -#else - #define VERIFY(statement) statement -#endif - -#include "ComponentException.h" -#include "WorkerUtil.h" diff --git a/src_vs2012/GDBParser/WorkerThreadObject.h b/src_vs2012/GDBParser/WorkerThreadObject.h deleted file mode 100644 index bd158897..00000000 --- a/src_vs2012/GDBParser/WorkerThreadObject.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -BEGIN_NAMESPACE - -ref class WorkerThreadObject -{ -public: -#ifdef _DEBUG - const DWORD ThreadId; -#endif - - WorkerThreadObject() -#ifdef _DEBUG - : ThreadId(GetCurrentThreadId()) -#endif - { - } -}; - -END_NAMESPACE \ No newline at end of file diff --git a/src_vs2012/GDBParser/WorkerUtil.h b/src_vs2012/GDBParser/WorkerUtil.h deleted file mode 100644 index c070eed0..00000000 --- a/src_vs2012/GDBParser/WorkerUtil.h +++ /dev/null @@ -1,186 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -BEGIN_NAMESPACE - -#include - -inline HRESULT HRFromWin32Error(LONG lError) -{ - HRESULT hr = HRESULT_FROM_WIN32(lError); - if (SUCCEEDED(hr)) - hr = E_FAIL; - return hr; -} - -inline HRESULT HRLastError() -{ - return HRFromWin32Error(GetLastError()); -} - -inline HRESULT HRWin32BoolCall(BOOL rc) -{ - if (!rc) - return HRLastError(); - return S_OK; -} - -inline HRESULT HRWin32ErrorCall(LONG lError) -{ - if (lError != ERROR_SUCCESS) - return HRFromWin32Error(lError); - return S_OK; -} - -inline void __declspec(noreturn) ThrowHR(HRESULT hr) -{ - throw gcnew ComponentException(hr); -} - -inline void __declspec(noreturn) ThrowLastError() -{ - HRESULT hr = HRLastError(); - - ThrowHR(hr); -} - -inline void Win32BoolCall(BOOL fCondition) -{ - if (!fCondition) - { - ThrowLastError(); - } -} - -inline void Win32ErrorCall(DWORD err) -{ - if (err != 0) - { - ThrowHR(HRESULT_FROM_WIN32(err)); - } -} - -inline HANDLE Win32HandleCall(HANDLE h) -{ - if (h == NULL || h == INVALID_HANDLE_VALUE) - { - ThrowLastError(); - } - - return h; -} - -inline int StringLength(String^ s) -{ - if (s == nullptr) - { - return 0; - } - - return s->Length; -} - -inline String^ GetProcessName(HANDLE hProcess) -{ - WCHAR szProcessNameBuff[MAX_PATH+1]; - DWORD nChars = GetModuleFileNameEx( - hProcess, // process - NULL, // Module handle - szProcessNameBuff, - _countof(szProcessNameBuff) - ); - - Win32BoolCall(nChars > 0 && nChars <= _countof(szProcessNameBuff)); - - return gcnew String(szProcessNameBuff); -} - -inline LPWSTR wcsdup(String^ source) -{ - pin_ptr pSource = PtrToStringChars( source ); - int cch = (( source->Length+1) * 2); - LPWSTR pDest = new wchar_t[cch]; - memcpy(pDest, pSource, cch * sizeof(wchar_t)); - - return pDest; -} - -inline String^ StringPrefixReplace(int oldPrefixLen, String^ newPrefix, String^ s) -{ - int lengthNeeded = s->Length + newPrefix->Length - oldPrefixLen; - Text::StringBuilder^ sb = gcnew Text::StringBuilder(lengthNeeded, lengthNeeded); - - sb->Append(newPrefix); - sb->Append(s, oldPrefixLen, s->Length-oldPrefixLen); - - return sb->ToString(); -} - -inline String^ StringPrefixReplace(String^ oldPrefix, String^ newPrefix, String^ s) -{ - return StringPrefixReplace(oldPrefix->Length, newPrefix, s); -} - -// Note: return value does not include a trailing slash -inline int FindCommonPathSuffixLength(String^ path1, String^ path2) -{ - const int len1 = path1->Length; - const int len2 = path2->Length; - - int commonSuffixLength = 0; - - // scan backwards until we find a character that is different - for (; true; commonSuffixLength++) - { - int index1 = len1 - commonSuffixLength - 1; - int index2 = len2 - commonSuffixLength - 1; - - if (index2 < 0 || index1 < 0) - break; - - wchar_t char1 = path1[index1]; - wchar_t char2 = path2[index2]; - - // first compare the characters exsactly (fast). - if (char1 == char2) - continue; - - // if they aren't exsactly the same, see if they are canonicialy the same - char1 = (char1 == '/') ? '\\' : System::Char::ToUpperInvariant(char1); - char2 = (char2 == '/') ? '\\' : System::Char::ToUpperInvariant(char2); - - if (char1 == char2) - continue; - - break; - } - - // scan forward until we find a slash - for (; commonSuffixLength > 0; commonSuffixLength--) - { - wchar_t char1 = path1[len1 - commonSuffixLength]; - - if (char1 == '\\' || char1 == '/') - { - commonSuffixLength--; - break; - } - } - - return commonSuffixLength; -} - -END_NAMESPACE \ No newline at end of file diff --git a/src_vs2012/GDBParser/dllmain.cpp b/src_vs2012/GDBParser/dllmain.cpp deleted file mode 100644 index 3b65a7e6..00000000 --- a/src_vs2012/GDBParser/dllmain.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -// dllmain.cpp : Defines the entry point for the DLL application. -#include "stdafx.h" -#include "resource.h" - -#pragma managed(off) - - -/// -/// Use the ATL Registrar to register the engine. -/// -class CGDBParserModule : public CAtlDllModuleT< CGDBParserModule > -{ - -}; - -CGDBParserModule _GDBParserModule; -HMODULE _hModThis; - - -/// -/// Adds entries to the system registry. -/// -/// HRESULT -STDAPI DllRegisterServer(void) -{ - // Get this binaries full-path - WCHAR wszThisFile[MAX_PATH + 1]; - GetModuleFileName(_hModThis, wszThisFile, MAX_PATH + 1); - - // Cut off the FileName. GDBPARSERPATH should point to GDBParserAPI - WCHAR wszPath[MAX_PATH + 1]; - WCHAR* wszFileName; - GetFullPathName(wszThisFile, MAX_PATH + 1, wszPath, &wszFileName); - *wszFileName = L'\0'; - - // Register the sample engine in the Visual Studio registry hive. See GDBParser.rgs for what is added. - _ATL_REGMAP_ENTRY rgMap[] = - { - {L"GDBPARSERPATH", wszPath}, - {NULL, NULL} - }; - - HRESULT hr = _GDBParserModule.UpdateRegistryFromResourceS(IDR_GDBPARSER, true, rgMap); - return hr; -} - - -/// -/// Removes entries from the system registry. -/// -/// HRESULT -STDAPI DllUnregisterServer(void) -{ - // Get this binaries full-path - WCHAR wszThisFile[MAX_PATH + 1]; - GetModuleFileName(_hModThis, wszThisFile, MAX_PATH + 1); - - // Cut off the FileName. GDBPARSERPATH should point to GDBParserAPI - WCHAR wszPath[MAX_PATH + 1]; - WCHAR* wszFileName; - GetFullPathName(wszThisFile, MAX_PATH + 1, wszPath, &wszFileName); - *wszFileName = L'\0'; - - // Register the sample engine in the Visual Studio registry hive. See GDBParser.rgs for what is added. - _ATL_REGMAP_ENTRY rgMap[] = - { - {L"GDBPARSERPATH", wszPath}, - {NULL, NULL} - }; - - HRESULT hr = _GDBParserModule.UpdateRegistryFromResourceS(IDR_GDBPARSER, false, rgMap); - return hr; -} - - -/// -/// -/// -/// -/// TRUE. -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - _hModThis = hModule; - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} - diff --git a/src_vs2012/GDBParser/gdb-connect.cpp b/src_vs2012/GDBParser/gdb-connect.cpp deleted file mode 100644 index 0c2f3311..00000000 --- a/src_vs2012/GDBParser/gdb-connect.cpp +++ /dev/null @@ -1,2031 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -// gdb-connect.cpp : Defines the entry point for the console application. -// -// Based on code sample from http://support.microsoft.com/kb/190351 - -#include "stdafx.h" - -#include "gdb-connect.h" -#include -#include - -#include -#include -#include -#include -#include - -#include -#include < vcclr.h > - -using namespace std; -using namespace System; - - -/// -/// Used to send parameters for the listeningGDB thread (the one that is listening GDB responses). -/// -typedef struct ListeningThreadDataStruct -{ - GDBConsole *console; // Current instance of GDB debugger. - string *parsingInstructions; // Parsing instruction. -} ListeningThreadData; - - -/// -/// Used to send parameters for the parsing threads, when using multi-threaded parsing. -/// -typedef struct ParsingThreadDetailsStruct -{ - char* response; // GDB response. - char* parsingInstruction; // Parsing instruction. - int* seqStamp; // Output buffer index where the parsed response will be stored. -} ParsingThreadDetails; - - -/// -/// Used by sendingCommands2GDB thread to store data that listeningGDB thread will need while parsing the GDB response. -/// -typedef struct GDBBufferStruct -{ - int seqId; // The sequencial number (seqID) of the instruction that was sent to GDB. - int instructionCode; // The instruction ID. - string param; // Parameter sent by sendingCommands2GDB thread to the listeningGDB one. -} GDBBufferEntry; - - -/// -/// Mutex / Event objects -/// -HANDLE hInputBufferMutex; // Used to ensure that only one thread at a time will be manipulating the input buffer. -HANDLE hGDBBufferMutex; // Used to ensure that only one thread at a time will be manipulating the GDB (intermediate) buffer. -HANDLE hOutputBufferMutex; // Used to ensure that only one thread at a time will be manipulating the output buffer. -HANDLE inputEvent; // Used to avoid sendingCommands2GDB thread to be pooling while the input buffer is empty. -HANDLE asyncOutputEvent; // Used to avoid DebugEngine.EventDispatcher thread to be pooling while waiting for an asynchronous response from Output buffer - -extern HMODULE _hModThis; - - -/// -/// Output buffer. Each entry has a parsed GDB response. -/// -char outputBuffer[OutputBufferSize][ParsedMessageSize]; -int out_OutputBuffer = SyncInstructionsSize; // Remove element from this position (outputBuffer). Input depends on the - // seqStamp, i.e., ordered according to GDB responses. Positions 0 to 49 - // are reserved for synchronous commands. - - -/// -/// Input buffer (Circular). Each entry has a command to be sent to GDB. -/// -char inputBuffer[InputBufferSize][GDBCommandSize]; -int in_InputBuffer = 0; // Add element in this position (inputBuffer). -int out_InputBuffer = 0; // Remove element from this position (inputBuffer). - - -/// -/// An instance of GDB debugger. -/// -GDBConsole* GDBConsole::m_instance = NULL; -TCHAR* GDBConsole::m_pcGDBCmd = NULL; - - -/// -/// GDB buffer. Contains the GDBBufferEntries sent by sendingCommands2GDB therad to the listeningGDB one. -/// -struct GDBBufferMainStruct -{ - int quantity; // Contains the number of GDB entries currently filled. - GDBBufferEntry GDBBufferData[GDBBufferSize]; // See GDBBufferEntry definition above. -} GDBBuffer; - - -/// -/// Shared variable between SendingCommands2GDB and listeningGDB threads used to let the listeningGDB one know that it has -/// to terminate. SendingCommands2GDB thread sets this variable to true to terminate listeningGDB thread. -/// -bool exitGDB = false; - - -/// -/// Used to store the path to GDB output log, generated when GDB console is instantiated and needed in logPrint(). -/// -char path_log[_MAX_PATH]; - - -/// -/// Used to store the path to the parsed GDB responses output log, generated when the sendingCommands2GDB thread is started and needed in parsedLogPrint(). -/// -char parse_log[_MAX_PATH]; - - -/// /// Generic function to print to a log file. -/// -/// Message to be printed to a log file. -void GDBConsole::logPrint(char* buffer) { - if (LOG_GDB_RAW_IO) { - time_t tt = time(NULL); - struct tm tm; - char buf[32]; - - tm = *localtime(&tt); - - strftime(buf, 31, "%H:%M:%S", &tm); - - FILE* file = fopen((char *)path_log, "a"); - fprintf(file, "%s - %s", buf, buffer); - fclose(file); - } -} - - -/// -/// Constructor. -/// -GDBConsole::GDBConsole() : - m_hInputRead(NULL), m_hInputWrite(NULL), m_hOutputRead(NULL), - m_hOutputWrite(NULL), m_hErrorWrite(NULL), m_isClosed(FALSE), - m_hCleanupMutex(NULL) -{ - HANDLE hOutputReadTmp = NULL; - HANDLE hInputWriteTmp = NULL; - SECURITY_ATTRIBUTES sa; - - out_OutputBuffer = SyncInstructionsSize; - in_InputBuffer = 0; - out_InputBuffer = 0; - - m_hCleanupMutex = CreateMutex(NULL, FALSE, NULL); - - // Set up the security attributes struct used when creating the pipes. - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - // Create the child output pipe. - if (!CreatePipe(&hOutputReadTmp, &m_hOutputWrite, &sa, 0)) - DisplayError(_T("CreatePipe")); - - // Create a duplicate of the output write handle for the std error - // write handle. This is necessary in case the child application - // closes one of its std output handles. - if (!DuplicateHandle(GetCurrentProcess(), m_hOutputWrite, - GetCurrentProcess(), &m_hErrorWrite, 0, - TRUE, DUPLICATE_SAME_ACCESS)) - DisplayError(_T("DuplicateHandle")); - - // Create the child input pipe. - if (!CreatePipe(&m_hInputRead, &hInputWriteTmp, &sa, 0)) - DisplayError(_T("CreatePipe")); - - // Create new output read handle and the input write handles. Set - // the Properties to FALSE. Otherwise, the child inherits the - // properties and, as a result, non-closeable handles to the pipes are created. - if (!DuplicateHandle(GetCurrentProcess(), hOutputReadTmp, - GetCurrentProcess(), - &m_hOutputRead, // Address of new handle. - 0, FALSE, // Make it uninheritable. - DUPLICATE_SAME_ACCESS)) - DisplayError(_T("DuplicateHandle")); - - if (!DuplicateHandle(GetCurrentProcess(), hInputWriteTmp, - GetCurrentProcess(), - &m_hInputWrite, // Address of new handle. - 0, FALSE, // Make it uninheritable. - DUPLICATE_SAME_ACCESS)) - DisplayError(_T("DuplicateHandle")); - - // Close inheritable copies of the handles you do not want to be inherited. - if (!CloseHandle(hOutputReadTmp)) DisplayError(_T("CloseHandle")); - if (!CloseHandle(hInputWriteTmp)) DisplayError(_T("CloseHandle")); - - prepAndLaunchRedirectedChild(); - - // Close pipe handles (do not continue to modify the parent). - // You need to make sure that no handles to the write end of the - // output pipe are maintained in this process or else the pipe will - // not close when the child process exits and the ReadFile will hang. - if (!CloseHandle(m_hOutputWrite)) DisplayError(_T("CloseHandle")); - if (!CloseHandle(m_hInputRead )) DisplayError(_T("CloseHandle")); - if (!CloseHandle(m_hErrorWrite)) DisplayError(_T("CloseHandle")); - - String^ tempPath = Environment::GetEnvironmentVariable("APPDATA"); - tempPath += "\\BlackBerry\\gdb-output.log"; - pin_ptr path_buffer = PtrToStringChars(tempPath); - - int ret = wcstombs ( path_log, path_buffer, _MAX_PATH ); - - FILE* file = fopen(path_log, "w"); // Delete a possible existing file. - fclose(file); -} - - -/// -/// Get the current instance of GDB debugger, creating a new one if needed. -/// -/// Returns the current instance of GDB debugger. -GDBConsole* GDBConsole::getInstance() { - if (m_instance == NULL) { - // Initialize it. - m_instance = new GDBConsole; - } - return m_instance; -} - - -/// -/// Shut down GDB debugger. A command to exit GDB was already sent by GDBParser::exitGDB(): "-gdb-exit". However, still -/// needs to "clean up": Update variables and terminate GDBWrapper process. -/// -void GDBConsole::shutdown() { - if (m_instance != NULL) { - m_instance->cleanup(); - } -} - - -/// -/// Set m_pcGDBCmd variable with the path and command to initialize GDB/MI. It will be used to instantiate GDBConsole. -/// For example: C:/bbndk/host_10_0_10_536/win32/x86\usr\bin\ntoarm-gdb.exe --interpreter=mi2. -/// -/// String with full path and command to initialize GDB/MI. -void GDBConsole::setGDBPath(const TCHAR* pcGDBCmd) { - size_t numChars = _tcslen(pcGDBCmd) + 1; - - // The path length may have changed, so reallocate for this one. - if (m_pcGDBCmd) { - delete[] m_pcGDBCmd; - } - m_pcGDBCmd = new TCHAR[numChars * sizeof(TCHAR)]; - - _tcscpy_s(m_pcGDBCmd, numChars, pcGDBCmd); -} - - -/// -/// Check if GDB is closed. -/// -/// A boolean value: TRUE if GDB is closed; FALSE if not. -BOOL GDBConsole::isClosed() { - return m_isClosed; -} - - -/// -/// After exiting GDB, it is still needed to update some internal variables and terminate the GDBWrapper process. -/// -void GDBConsole::cleanup() { - WaitForSingleObject(m_hCleanupMutex, INFINITE); - // Check if cleanup required. - if (!m_isClosed) { - m_isClosed = TRUE; - - if (m_pcGDBCmd != NULL) { - delete[] m_pcGDBCmd; - m_pcGDBCmd = NULL; - } - - // Clean up and kill GDBWrapper process. - if (!SetEvent(m_eventTerminate)) { - // Force termination. - TerminateProcess(m_hProcess, 0); - } - - // Wait for process to terminate. - WaitForSingleObject(m_hProcess, INFINITE); - - if (!CloseHandle(m_hProcess)) DisplayError(_T("CloseHandle")); - - if (!CloseHandle(m_hOutputRead)) DisplayError(_T("CloseHandle")); - if (!CloseHandle(m_hInputWrite)) DisplayError(_T("CloseHandle")); - - m_instance = NULL; - } - ReleaseMutex(m_hCleanupMutex); -} - - -/// -/// Destructor. -/// -GDBConsole::~GDBConsole() { - cleanup(); -} - - -/// -/// Sets up STARTUPINFO structure and launches redirected child. -/// -void GDBConsole::prepAndLaunchRedirectedChild(void) -{ - HANDLE stdHandles[3]; - LPCTSTR lpApplicationName = NULL; - PROCESS_INFORMATION pi; - STARTUPINFO si; - DWORD flags = 0; - DWORD pid = GetCurrentProcessId(); - TCHAR eventCtrlCName[MAX_EVENT_NAME_LENGTH]; - TCHAR eventTerminateName[MAX_EVENT_NAME_LENGTH]; - - _stprintf(eventCtrlCName, _T("Ctrl-C-%i"), pid); - _stprintf(eventTerminateName, _T("Terminate-%i"), pid); - - // Create event for wrapper process to wait on for CTRL-C. - m_eventCtrlC = CreateEventW(NULL, FALSE, FALSE, eventCtrlCName); - - // Create event for wrapper process to wait on for termination. - m_eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName); - - // Set process information. - memset(&pi, 0, sizeof(pi)); - - // Set up the start up info struct. - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - si.hStdOutput = m_hOutputWrite; - si.hStdInput = m_hInputRead; - si.hStdError = m_hErrorWrite; - si.wShowWindow = SW_HIDE; - - flags = CREATE_NEW_CONSOLE; - - String^ StringFilePath = Environment::GetFolderPath(Environment::SpecialFolder::ProgramFilesX86) + "\\BlackBerry\\VSPlugin-NDK\\GDBWrapper.exe"; - pin_ptr FilePath = PtrToStringChars(StringFilePath); - - if (!m_pcGDBCmd) { - cleanup(); - ErrorExit(_T("m_pcGDBCmd is NULL")); - } - - /* CreateProcess can modify pCmdLine thus we allocate memory */ - size_t numChars = _tcslen(m_pcGDBCmd) + MAX_EVENT_NAME_LENGTH * 2 + 1; - TCHAR* pCmdLine = new TCHAR[numChars * sizeof(TCHAR)]; - - if (pCmdLine == 0) { - DisplayError(_T("prepAndLaunchRedirectedChild: failed to allocate memory for pCmdLine")); - } - - _stprintf(pCmdLine, _T("\"%s\" \"%s\" \"%s\" \"%s\""), FilePath, m_pcGDBCmd, eventCtrlCName, eventTerminateName); - - // Launch the process (create a new console). - if (!CreateProcess(NULL, /* executable name */ - pCmdLine, /* command line */ - NULL, /* process security attribute */ - NULL, /* thread security attribute */ - TRUE, /* inherits system handles */ - flags, /* normal attached process */ - NULL, /* environment block */ - NULL, /* change to the new current directory */ - &si, /* (in) startup information */ - &pi)) /* (out) process information */ - ErrorExit(_T("CreateProcess")); - - if(NULL != pCmdLine) { - delete[] pCmdLine; - pCmdLine = NULL; - } - - m_hProcess = pi.hProcess; - - // Close unneeded handles. - if (!CloseHandle(pi.hThread)) DisplayError(_T("CloseHandle")); -} - - -/// -/// Read the stdout of the GDB console process. -/// -/// Buffer to store output. -/// Size of buffer in bytes (leave space for the null char). -/// Returns the number of characters that was read. -/// One of these integer values: 0 - Error; 1 - Success; 2 - Read everything from buffer but the message was not written -/// completed, maybe because the message is bigger than the buffer, maybe because GDB didn't finish writing the message. Call it -/// again to keep reading. -int GDBConsole::readOutput(CHAR* lpBuffer, int bufSize, int* nCharsRead) -{ - DWORD nBytesRead; - - if (isClosed()) { - DisplayError(_T("readOutput: GDBConsole is closed")); - return 0; - } - - if (lpBuffer == NULL) { - DisplayError(_T("readOutput: null buffer pointer")); - return 0; - } - - if (bufSize < 1) { - DisplayError(_T("readOutput: needs bufSize > 1")); - return 0; - } - - if (!ReadFile(m_hOutputRead, lpBuffer, bufSize, - &nBytesRead, NULL) || !nBytesRead) - { - if (GetLastError() == ERROR_BROKEN_PIPE) { - // Pipe done - normal exit path. - cleanup(); - return 0; - } else { - ErrorExit(_T("ReadFile")); - } - } - - *nCharsRead = nBytesRead / sizeof(CHAR); - - const char* pLastChar = lpBuffer + nBytesRead; - pLastChar -= 2; - - logPrint((char*) lpBuffer); - - if (strcmp("\r\n", pLastChar)) { - // Didn't get end of line. - return 2; - } - - return 1; -} - - -/// -/// Send a GDB command to the stdin of the GDB console process. -/// -/// null-terminated string ending in \r\n -/// 0 - Error; 1 - Success -int GDBConsole::sendCommand(const CHAR* lpCmd) -{ - DWORD nBytesWrote; - int nCmdChars = strlen(lpCmd); - - if (isClosed()) { - DisplayError(_T("readOutput: GDBConsole is closed")); - return 0; - } - - // Input validation - if (nCmdChars < 2) { - DisplayError(_T("SendCommand: nCmdChars < 2")); - } else { - const char* pLastChar = strchr(lpCmd, '\0'); - pLastChar -= 2; - if (strcmp("\r\n", pLastChar)) { - DisplayError(_T("SendCommand: lpCmd doesn't end in \\r\\n")); - } - } - - if (!WriteFile(m_hInputWrite, lpCmd, nCmdChars * sizeof(CHAR), &nBytesWrote, NULL)) - { - if (GetLastError() == ERROR_NO_DATA) { - // Pipe was closed (normal exit path). - cleanup(); - return 0; - } else { - DisplayError(_T("WriteFile")); - return 0; - } - } else { - printf("Sending [%s] (%d chars)\n", lpCmd, nBytesWrote / sizeof(CHAR)); - } - - logPrint((char*) lpCmd); - - return 1; -} - - -/// -/// Get handle m_hOutputRead. -/// -/// Returns handle m_hOutputRead. -HANDLE GDBConsole::getStdOutHandle() { - return m_hOutputRead; -} - - -/// -/// Send a CtrlC event that will interrupt GDB execution. -/// -void GDBConsole::sendCtrlC() { - if (!SetEvent(m_eventCtrlC)) { - DisplayError(_T("SetEvent")); - } -} - - -/// -/// Check if there is more data to be read from GDB's stdout without removing it from the pipe's buffer. -/// -/// Instance of GDB debugger. -/// Returns TRUE (there is data to be read) or FALSE (there isn't). -BOOL GDBConsole::isMoreOutputAvailable () { - DWORD totalBytesAvail; - - if (!PeekNamedPipe(getStdOutHandle(), NULL, NULL, NULL, &totalBytesAvail, NULL)) { - TCHAR lpError[256]; - _tprintf(lpError, _T("isMoreOutputAvailable: %s"), GetLastError()); - DisplayError(lpError); - return false; - } - - return (totalBytesAvail > 0); -} - - -/// -/// Waits and returns the output received from GDB, with a timeout. In case it finishes because of a timeout while waiting for a -/// GDB response, be aware that this GDB response must be available in a later time and you must be able to handle it. -/// -/// Timeout. -/// Returns output received from GDB or "" if there is no GDB output. -string GDBConsole::waitForPromptWithTimeout(int seconds) { - char lpBuffer [1024]; - int nCharsRead = 0; - int rc = 0; - BOOL isPromptReady = FALSE; - const char* promptString = "(gdb) \r\n"; - const char* lpTmp; - clock_t start, current; - - start = clock(); - - string message = ""; - - do { - - current = clock(); - if ((message == "") && (((current - start) / CLOCKS_PER_SEC ) > seconds)) - { - message = "TIMEOUT!"; - break; - } - - memset(lpBuffer, 0, sizeof(lpBuffer)); - - if (isClosed()) { - break; - } - - if (isMoreOutputAvailable()) - { - rc = readOutput(lpBuffer, sizeof(lpBuffer) - 1, &nCharsRead); - if (rc) { - // Terminate the buffer. - - lpBuffer[nCharsRead] = '\0'; - - message += lpBuffer; - - if (nCharsRead >= strlen(promptString)) { - lpTmp = lpBuffer + nCharsRead - strlen(promptString); - if (!strcmp(lpTmp, promptString)) { - isPromptReady = TRUE; - } - } - } else { - DisplayError(_T("waitForPrompt: readOutput got error")); - message += "\n\nwaitForPrompt: readOutput got error\n\n"; - break; - } - } - } while (!isPromptReady && !isClosed()); - - return message; -} - - -/// -/// Returns the output received from GDB. -/// -/// If TRUE, this method waits for the entire GDB output, i.e., until the GDB prompt is ready. It is TRUE when -/// initializing GDB. If FALSE, that is the default behavior, returns the current GDB output or "" if there is no GDB output. -/// Returns output received from GDB or "" if there is no GDB output. -string GDBConsole::waitForPrompt(bool sync) { - char lpBuffer [1024]; - int nCharsRead = 0; - int rc = 0; - BOOL isPromptReady = FALSE; - const char* promptString = "(gdb) \r\n"; - const char* lpTmp; - - string message = ""; - - do { - memset(lpBuffer, 0, sizeof(lpBuffer)); - - if (isClosed()) { - break; - } - - if (isMoreOutputAvailable()) - { - rc = readOutput(lpBuffer, sizeof(lpBuffer) - 1, &nCharsRead); - if (rc) { - // Terminate the buffer. - - lpBuffer[nCharsRead] = '\0'; - - message += lpBuffer; - - if (nCharsRead >= strlen(promptString)) { - lpTmp = lpBuffer + nCharsRead - strlen(promptString); - if (!strcmp(lpTmp, promptString)) { - isPromptReady = TRUE; - } - } - } else { - DisplayError(_T("waitForPrompt: readOutput got error")); - message += "\n\nwaitForPrompt: readOutput got error\n\n"; - break; - } - } - else if (!sync) - break; - } while (!isPromptReady && !isClosed()); - - return message; -} - - -/// -/// Displays the error number and corresponding message. -/// -/// Error message. -void DisplayError(LPCTSTR pszAPI) -{ - LPVOID lpvMessageBuffer; - TCHAR szPrintBuffer[512]; - DWORD bufSize = 512 * sizeof(TCHAR); - DWORD nCharsWritten; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpvMessageBuffer, 0, NULL); - - StringCbPrintf(szPrintBuffer, bufSize, - _T("ERROR: API = %s.\n error code = %d.\n message = %s.\n"), - pszAPI, GetLastError(), (char *)lpvMessageBuffer); - - _tprintf(_T("%s\n"), szPrintBuffer); - - LocalFree(lpvMessageBuffer); - ExitProcess(GetLastError()); -} - - -/// -/// Retrieve the system error message for the last-error code. -/// -/// Error message. -void ErrorExit(LPTSTR lpszFunction) -{ - LPVOID lpMsgBuf; - LPVOID lpDisplayBuf; - DWORD dw = GetLastError(); - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL ); - - // Display the error message and exit the process. - - lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, - (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); - StringCchPrintf((LPTSTR)lpDisplayBuf, - LocalSize(lpDisplayBuf) / sizeof(TCHAR), - TEXT("%s failed with error %d: %s"), - lpszFunction, dw, lpMsgBuf); - MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); - - LocalFree(lpMsgBuf); - LocalFree(lpDisplayBuf); - ExitProcess(dw); -} - - -/// -/// Initialize / clean all the existing buffers: inputBuffer, GDBBuffer, outputBuffer. -/// -void cleanBuffers() -{ - for (int i = 0; i < InputBufferSize; i++) - { - strcpy(inputBuffer[i],""); - } - in_InputBuffer = 0; - out_InputBuffer = 0; - for (int i = 0; i < GDBBufferSize; i++) - { - GDBBuffer.GDBBufferData[i].seqId = -1; - GDBBuffer.GDBBufferData[i].param = ""; - } - GDBBuffer.quantity = 0; - for (int i = 0; i < OutputBufferSize; i++) - { - strcpy(outputBuffer[i], ""); - } - out_OutputBuffer = SyncInstructionsSize; -} - - -/// -/// Verify if GDB buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool isGDBBufferEmpty() -{ - bool empty = true; - WaitForSingleObject( hGDBBufferMutex, INFINITE ); - if (GDBBuffer.quantity == 0) - empty = true; - else - empty = false; - ReleaseMutex( hGDBBufferMutex); - return empty; -} - - -/// -/// For every command sent to GDB, the following parameters must be added into GDBBuffer. -/// -/// Sequential ID of the command sent to GDB. It is used to identify, when evaluating GDB responses, which command -/// generated a given response. This ID is also used to specify the location in which this entry will be stored in this buffer. -/// Each command sent to GDB has an associated instruction code, that corresponds to the parsing -/// instruction that will be used to parse the GDB response. -/// Used to store the GDB command parameters, so they could be used during the parsing task. There are some GDB -/// commands, like -break-delete for example, that results in a simple "^done" GDB response. The parser can identify which command -/// caused that response but cannot know what was affected by it (considering the -break-delete command, the parser will know that some -/// breakpoint was successfully deleted but won't know which of them was deleted). Using "param" helps the parser letting it knows -/// which parameters were sent together with a given GDB command. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool addIntoGDBBuffer(int seq_id, int instructionCode, string param) -{ - if (seq_id < 0) - return false; - bool got = false; - int pos = seq_id % GDBBufferSize; - WaitForSingleObject( hGDBBufferMutex, INFINITE ); - if (GDBBuffer.GDBBufferData[pos].seqId == -1) // -1 means that the [pos] entry is "empty" or "not used". - { - GDBBuffer.GDBBufferData[pos].seqId = seq_id; - GDBBuffer.GDBBufferData[pos].instructionCode = instructionCode; - GDBBuffer.GDBBufferData[pos].param = param; - GDBBuffer.quantity += 1; - got = true; - } - ReleaseMutex( hGDBBufferMutex); - return (got); -} - - -/// -/// This method is called to find the right parsing instruction for a given GDB response. -/// -/// Sequential ID of the GDB response. -/// Returns the parameters sent together with the GDB command that generated this response, if there are some. -/// Returns the instruction code associated to the sequential id (seq). -int removeFromGDBBuffer(int seq, string *param) -{ - int output = -1; - if (seq < 0) // Means that: the GDB response is asynchronous or the response is not completed yet (GDB is still writing it) - if (seq == -2) // Means the GDB response is asynchronous and is not related to a GDB command. - return 0; // 0 is the instruction code for asynchronous responses. - else if (seq == -3) // Means that a breakpoint was modified. It is one of the GDB asynchronous messages. - return 1; // 1 is the instruction code for modified breakpoints responses. - else - return seq; // GDB response is incomplete. - - if (seq >= SyncInstructionsSize) // Means it was not a synchronous COMMAND. This number starts with SyncInstructionsSize - // and is increased for each new non synchronous COMMAND that is sent to GDB. - seq = (seq % SyncInstructionsSize) + SyncInstructionsSize; // seq must stay between SyncInstructionsSize and the buffer size. - - WaitForSingleObject( hGDBBufferMutex, INFINITE ); - if (GDBBuffer.GDBBufferData[seq].seqId != -1) - { - output = GDBBuffer.GDBBufferData[seq].instructionCode; - *param = GDBBuffer.GDBBufferData[seq].param; - GDBBuffer.GDBBufferData[seq].seqId = -1; // Marking this entry as "empty" or "not used". - GDBBuffer.quantity -= 1; - } - ReleaseMutex( hGDBBufferMutex); - return output; -} - - -/// -/// Store the parsed GDB response in the "seq_stamp" position of the Output buffer. -/// -/// Position in the Output buffer to store the parsed GDB response. -/// Parsed GDB response. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool addIntoOutputBuffer(int seq_stamp, char *parsedMessage) -{ - if (seq_stamp < 0) - return false; - bool got = false; - int pos = seq_stamp % OutputBufferSize; - WaitForSingleObject( hOutputBufferMutex, INFINITE ); - if (strcmp(outputBuffer[pos], "") == 0) // "" means that the [pos] entry is "empty" or "not used". - { - strcpy(outputBuffer[pos], parsedMessage); - got = true; - if (pos >= SyncInstructionsSize) - SetEvent(asyncOutputEvent); // Wake up "removeFromOutputBuffer", if needed. - } - ReleaseMutex( hOutputBufferMutex); - return (got); -} - - -/// -/// This method is called to send back to the debug engine the next parsed GDB response (output) for an -/// asynchronous GDB RESPONSE or a non synchronous GDB COMMAND. This managed part of Output buffer is circular. -/// -/// Returns the parsed GDB response. -void removeFromOutputBuffer(char * output) -{ - WaitForSingleObject( hOutputBufferMutex, INFINITE ); - if (strcmp(outputBuffer[out_OutputBuffer], "") != 0) - { - strcpy(output, outputBuffer[out_OutputBuffer]); - strcpy(outputBuffer[out_OutputBuffer], ""); - out_OutputBuffer += 1; - if (out_OutputBuffer == OutputBufferSize) - out_OutputBuffer = SyncInstructionsSize; // Positions 0 to "SyncInstructionsSize - 1" are reserved for synchronous commands. - } - ReleaseMutex( hOutputBufferMutex); - if (strcmp(output, "") == 0) // Means that the asynchronous part of output buffer is empty. - WaitForSingleObject(asyncOutputEvent, WAIT_TIME); - if (strcmp(output, "$#@EMPTY@#$") == 0) // This string means that both GDB and the parser worked well and returned an empty string. - output = ""; -} - - -/// -/// This method is called to send back to the debug engine the expected parsed GDB response (output) for a given synchronous -/// GDB COMMAND (ID). Each entry in this part of Output buffer was previously reserved for each GDB command. There are some free entries -/// that can be used by other GDB commands in the future. -/// -/// Returns the parsed GDB response. -/// ID of the GDB command. -void removeSyncFromOutputBuffer(char * output, int ID) -{ - if ((ID < 0) || (ID >= SyncInstructionsSize)) - return; - WaitForSingleObject( hOutputBufferMutex, INFINITE ); - if (strcmp(outputBuffer[ID], "") != 0) - { - strcpy(output, outputBuffer[ID]); - strcpy(outputBuffer[ID], ""); - } - ReleaseMutex( hOutputBufferMutex); -} - - -/// -/// Verify if Input buffer is empty. -/// -/// Returns TRUE if empty; FALSE if not. -bool isInputBufferEmpty() -{ - bool empty; - WaitForSingleObject( hInputBufferMutex, INFINITE ); - if (in_InputBuffer == out_InputBuffer) - empty = true; - else - empty = false; - ReleaseMutex( hInputBufferMutex); - return empty; -} - - -/// -/// This method is called by the debug engine to store each command that must be sent to GDB. Input buffer is a circular one. -/// -/// Command to be sent to GDB. -/// Returns TRUE - successfully added; or FALSE - failed to add. -bool addIntoInputBuffer(char GDBCommand[GDBCommandSize]) -{ - bool got = false; - bool fireEvent = false; - WaitForSingleObject( hInputBufferMutex, INFINITE ); - if (!((in_InputBuffer == (InputBufferSize - 1) && out_InputBuffer == 0) || ((in_InputBuffer + 1) == out_InputBuffer))) - { - if (in_InputBuffer == out_InputBuffer) - fireEvent = true; - strcpy(inputBuffer[in_InputBuffer], GDBCommand); - in_InputBuffer += 1; - if (in_InputBuffer == InputBufferSize) - in_InputBuffer = 0; - got = true; - } - if (fireEvent) - SetEvent(inputEvent); // Wake up "sendingCommands2GDB", if needed. - ReleaseMutex( hInputBufferMutex); - return (got); -} - - -/// -/// Used by sendingCommands2GDB thread to get the next command to be sent to GDB. Input buffer is a circular one. -/// -/// Returns the next command to be sent to GDB. -void removeFromInputBuffer(char * input) -{ - WaitForSingleObject( hInputBufferMutex, INFINITE ); - if (in_InputBuffer != out_InputBuffer) - { - strcpy(input, inputBuffer[out_InputBuffer]); - strcpy(inputBuffer[out_InputBuffer],""); - out_InputBuffer += 1; - if (out_InputBuffer == InputBufferSize) - out_InputBuffer = 0; - } - ReleaseMutex( hInputBufferMutex); -} - - -/// -/// Get the sequential ID of the response. -/// -/// The GDB response. -/// If the response is synchronous, this ID corresponds to the sequential ID of the command sent to GDB that generated such -/// response. If the response is asynchronous, there is no sequential ID in the response, so it returns: -/// -3 - when it shows that a breakpoint was modified; -/// -2 - for any other asynchronous response -/// -1 - when the response is not completed or in case of an error. -int getSeqID(string response) -{ - int end; - int begin; - char seqIDstr[11] = ""; - int seqID = -1; - - end = response.find("^done", 0); - if (end == -1) - { - end = response.find("^running", 0); - if (end == -1) - { - end = response.find("^error", 0); - if (end == -1) - { - end = response.find("^connected", 0); - if (end == -1) - { - end = response.find("*running", 0); - if (end != -1) - return -2; // Means the GDB response is asynchronous. - else - { - end = response.find("*stopped", 0); - if (end != -1) - { - return -2; // Means the GDB response is asynchronous. - } - else - { - if (response.substr(0, 20) == "=breakpoint-modified") - { - return -3; // Means that a breakpoint was modified. - } - else - { - return -1; // Error / message incomplete. - } - } - } - } - } - } - } - if (end < 15) // SeqID is the first data in the string - begin = 0; - else - { - begin = end - 1; - while ((response[begin] != '"') && (response[begin] != '}')) - begin--; - begin++; - } - response.copy(seqIDstr, end - begin, begin); - seqID = atoi(seqIDstr); - return(seqID); -} - - -/// -/// Get the next position of a given character (token) in a string message (txt), starting from a given position (pos). -/// -/// Character to search for. -/// String message in which it will search for the given character. -/// Starting position in the string message. -/// An integer that corresponds to the next position of the character in the string. If the character is not found, returns -/// the length of the string. -int getNextChar(char token, string txt, int pos) -{ - int end = pos; - int slash, aux; - do - { - slash = 0; - end = txt.find(token, pos); - if (end == -1) - end = txt.length(); - aux = end - 1; - while ((aux >= 0) && (txt[aux] == '\\')) - { - slash++; - aux--; - } - pos = end + 1; - } while ((slash % 2) != 0); - return end; -} - - -/// -/// Get the position of a given string (txt) in the string GDB response (response), starting from a given position (begin). -/// -/// GDB string response where the search will be performed. -/// String to search for in the GDB response. -/// Starting position in the GDB string response. -/// Search for that string "times" times. Ex: I want to find the third occurrence of word "qaqa" in the GDB -/// response. -/// Direction: if true, search forwards; if not, search backwards. Only '?' instruction can search backwards. -/// The kind of parsing instruction that called this method. '?', '@', or '~'. Only '?' instruction can -/// search backwards. -/// An integer that corresponds to the next position of the string in the GDB response. -1 in case of an error. -int searchResponse(string response, string txt, int begin, int times, bool forward, char instruction) -{ - for (; times > 0; times--) - { - if ((begin >= response.length()) || (begin == -1)) - break; - if (forward) - { - if (begin == 0) - { - if ((txt[0] == '\r') && (txt[1] == '\n')) - { - string check = txt.substr(2, txt.length() - 2); - if (response.substr(0, check.length()) == check) - continue; - } - } - begin = response.find(txt, begin); - if ((begin != -1) && ((times != 1) || (instruction == '?'))) - begin += txt.length(); - } - else - { - begin = response.rfind(txt, begin); - if (begin != -1) - { - if (times == 1) - begin += txt.length(); - else - begin--; - } - if ((begin == -1) && ((txt[0] == '\r') && (txt[1] == '\n'))) - begin = 2; // 2 is the size of "\r\n". - } - } - if (times == 0) - return begin; - return -1; -} - - -/// -/// Substitute the existing variables in the string "txt" by their values, stored in the "variables" array. Each variable name -/// has this format: $9$, where $ characters are used to identify the variable while the number corresponds to the variable ID, that also -/// corresponds to the array index. There is a special variable "$EOL$" that is substituted by "\r\n". -/// -/// String to search for variables. -/// Array with the variable values. -/// Returns the new modified string. -string substituteVariables(string txt, char variables[10][128]) -{ - do - { - int aux = getNextChar('$', txt, 0); - if (aux < txt.length()) - { - aux++; - int aux2 = getNextChar('$', txt, aux); - string index = txt.substr(aux, aux2 - aux); - if (index == "EOL") - { - txt = txt.substr(0, aux - 1) + '\r' + '\n' + txt.substr(aux2 + 1, txt.length()); - } - else - txt = txt.substr(0, aux - 1) + variables[atoi(index.c_str())] + txt.substr(aux2 + 1, txt.length()); - } - else - break; - } while (true); - return txt; -} - - -/// -/// Find the position of the associated closing bracket/parenthesis. -/// -/// The associated opening character ("(", "{" or "["). -/// The associated closing character (")", "}" or "]"). -/// The string where the search will be made. -/// Start position in the parsingInstruction string. This position normally corresponds to the position of the opening -/// character, but it could be smaller than that (never bigger!). However, if it is smaller, it cannot have the same character between -/// the 'ini' position and the corresponding one for the opening one. If need to have another one, precede it by the character '\'. -/// Returns the position of the associated closing bracket/parenthesis. If it is not found, returns the length of the string. -int findClosing(char opening, char closing, string parsingInstruction, int ini) -{ - int end = getNextChar(closing, parsingInstruction, ini); - int other = ini; - bool found = true; - do - { - other = getNextChar(opening, parsingInstruction, other + 1); - if (other < end) - { - end = getNextChar(closing, parsingInstruction, end + 1); - } - else - found = false; - } while (found); - return end; -} - - -/// -/// Reponsible for parsing each GDB response. Depending on the parsing instruction, the parser can get the first occurrence -/// from GDB response or get all of them that satisfies this parsing instruction. -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Current character to be read in GDB response. -/// If the parsing instruction specifies that it has to get all occurences from a GDB response, this value must -/// be true. -/// A variable stores a string parsed from GDB response and can be used as many times as needed to create the -/// parsed response. Up to 10 variables can be created for a given parsing instruction. -/// If the parsing instruction allows the parser to get all occurrences from GDB response, this separator will -/// be used at the end of each occurence. The default one is '#' but it can be specified in the parsing instruction. -/// Returns the parsed GDB response. -string parseGDB(string *response, string parsingInstruction, int respBegin, bool repeat, char variables[10][128], string separator) -{ - string result = ""; // This variable will be the parsed GDB response. - string originalParsingInstruction = parsingInstruction; // Backup of parsing instruction. - int parsePos = 0; // Current character to be read in parsing instruction. - int home = respBegin; // Save the current position in GDB response. - int respEnd = 0; - int limit = (*response).length(); - bool found = false; - - bool removeSelection = false; - int removeFromHere = -2; // -2 - not set; -1 - indicates that it will be set in the first '?' instruction; >=0 - already set. - - if (separator == "$EOL$") - separator = "\r\n"; - - while ((parsePos < parsingInstruction.length()) || repeat) - { - if ((repeat) && (parsePos >= parsingInstruction.length())) // repeat instructions till the end of the response - { - if (found) - { - if (result != "") - result += separator; - parsePos = 0; - parsingInstruction = originalParsingInstruction; - limit = (*response).length(); - found = false; - } - else - repeat = false; - continue; - } - - if (parsingInstruction[parsePos] == '(') // repeat instructions till the end of the response - { - int end = parsePos; - string repeatInstruction; - - end = findClosing('(', ')', parsingInstruction, parsePos); - - repeatInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)); - - end++; - if (parsingInstruction[end] == ':') - { - parsePos = end + 1; - end = getNextChar(';', parsingInstruction, parsePos); - separator = parsingInstruction.substr(parsePos, end - parsePos); - int aux = separator.find("\\;"); - if (aux != -1) - separator.erase(aux,1); - } - parsePos = end + 1; - - result += parseGDB(response, repeatInstruction, respBegin, true, variables, separator); - - continue; - } - - if (parsingInstruction[parsePos] == '?') // search and set the beginning of the searched string. - { - int times = 1; - bool forward = true; - int end; - int aux; - string txt; - - parsePos++; - if (parsingInstruction[parsePos] == '%') // consider this position to extract and use the data and them remove this - // one from the GDB response string. - { - removeFromHere = -1; - parsePos++; - } - - if (parsingInstruction[parsePos] == '<') // means to search backwards. - { - forward = false; - parsePos++; - } - - if (parsingInstruction[parsePos] != '?') // the number of times to search for a given string. - { - end = getNextChar('?', parsingInstruction, parsePos); - times = atoi(parsingInstruction.substr(parsePos, end - parsePos).c_str()); - parsePos = end; - } - parsePos++; - - end = getNextChar(';', parsingInstruction, parsePos); - - txt = substituteVariables(parsingInstruction.substr(parsePos, end - parsePos), variables); - - aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - int previousRespBegin = respBegin; - respBegin = searchResponse(*response, txt, respBegin, times, forward, '?'); - -// check if it was defined a set of instructions to be executed if the search is NOT valid, i.e., there is a '{' after the ';'. -// If the search is not valid, go to the '}' and keep going. If there is no '{}' and the search is not valid, just end evaluating -// these instructions. Normally, there is '{}' to allow handling gdb errors. - if (parsingInstruction[end + 1] == '{') - { - parsePos = end + 1; - - end = findClosing('{', '}', parsingInstruction, parsePos); - - if ((respBegin != -1) && (respBegin <= limit)) - { - found = true; - // the following instructions to be evaluated are between '{' and '}'. - if (((end + 1) < parsingInstruction.length()) && (parsingInstruction[end+1] != '{')) - { - parsingInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.substr(end + 2, parsingInstruction.length()); - } - else - { - // if there is '{' after a '}', it means that there is an 'else' sentence. - int else_end; - else_end = findClosing('{', '}', parsingInstruction, end + 1); - parsingInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.substr(else_end + 2, parsingInstruction.length()); - } - - parsePos = 0; - if (removeFromHere == -1) - removeFromHere = respBegin - txt.length(); - } - else - { - respBegin = previousRespBegin; - removeFromHere = -2; - if (((end + 1) < parsingInstruction.length()) && (parsingInstruction[end+1] != '{')) - { - parsePos = end + 2; // move it to the next instruction, after the "};" - } - else - { - parsePos = end + 1; - end = findClosing('{', '}', parsingInstruction, parsePos); - parsingInstruction = parsingInstruction.substr(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.substr(end + 2, parsingInstruction.length()); - parsePos = 0; - } - } - } - else - { - if ((respBegin == -1) || (respBegin > limit)) - { - if (respBegin > limit) - respBegin = previousRespBegin; - - parsePos = parsingInstruction.length(); - removeFromHere = -2; - removeSelection = false; - } - else - { - found = true; - parsePos = end + 1; - if (removeFromHere == -1) - removeFromHere = respBegin - txt.length(); - } - } - - continue; - } - - if (parsingInstruction[parsePos] == '@') // till here: search and set the end of the searched string. Return the string - // between the last ? and this "till here" position - { - int times = 1; - int end; - string txt; - int aux; - - parsePos++; - - if (parsingInstruction[parsePos] != '@') // get the number of times to search for a given string. - { - end = getNextChar('@', parsingInstruction, parsePos); - times = atoi(parsingInstruction.substr(parsePos, end - parsePos).c_str()); - parsePos = end; - } - parsePos++; - - end = getNextChar(';', parsingInstruction, parsePos); - - txt = substituteVariables(parsingInstruction.substr(parsePos, end - parsePos), variables); - - aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - respEnd = searchResponse(*response, txt, respBegin, times, true, '@'); - if ((respEnd == -1) || (respEnd > limit)) - { - result = ""; - break; - } - if (!removeSelection) - result += (*response).substr(respBegin, respEnd - respBegin); - - respBegin = respEnd; - - if (removeFromHere >= 0) - { - (*response).erase(removeFromHere, respEnd + txt.length() - removeFromHere); - respBegin = removeFromHere; - removeFromHere = -2; - removeSelection = false; - } - - parsePos = end + 1; - continue; - } - - if (parsingInstruction[parsePos] == '#') // insert the following string into the result - { - int end = getNextChar(';', parsingInstruction, parsePos); - parsePos++; - - string txt = parsingInstruction.substr(parsePos, end - parsePos); - int aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - result += substituteVariables(txt, variables); - - parsePos = end + 1; - continue; - } - - if (parsingInstruction[parsePos] == '~') // specify a limit, so the search instructions will search till this position. - { - int end = getNextChar(';', parsingInstruction, parsePos); - parsePos++; - - string txt = parsingInstruction.substr(parsePos, end - parsePos); - int aux = txt.find('\\'); - while (aux != -1) - { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed - txt = txt.substr(0, aux) + txt.substr(aux + 1, txt.length()); - aux = txt.find('\\', aux + 1); - }; - - limit = searchResponse(*response, txt, respBegin, 1, true, '~'); - if (limit == -1) - { - limit = (*response).length(); - } - - parsePos = end + 1; - continue; - } - - if (parsingInstruction[parsePos] == '0') // set the response cursor position to home_pos (normally 0, but '(' can set a different - // value for home_pos) - { - respBegin = home; - parsePos += 2; // jump the '0' and ';' characters - continue; - } - - if (parsingInstruction[parsePos] == '%') // delete the string (between ? and @) from response - { - removeSelection = true; - removeFromHere = -1; - parsePos++; - continue; - } - - if (parsingInstruction[parsePos] == '$') // create a variable to store a value from response string. This value is defined by - // the instructions between the '=' and the @ symbol (till here) - { - int end, varNumber, aux; - - parsePos++; - end = getNextChar('=', parsingInstruction, parsePos); - aux = getNextChar('$', parsingInstruction, parsePos); - if ((aux > 0) && (aux < end)) - end = parsingInstruction.length(); - if (end < parsingInstruction.length()) // variable assignment - { - varNumber = atoi(parsingInstruction.substr(parsePos, end - parsePos).c_str()); - - parsePos = end + 1; - end = parsingInstruction.find("$$", parsePos); - string r = parseGDB(response, parsingInstruction.substr(parsePos, end - parsePos), respBegin, false, variables, "#"); - if (r == "") - break; - strcpy(variables[varNumber], r.c_str()); - - parsePos = end + 3; // jump $$; - } - else // pre-defined variable: Finish the parsing task or move to the end of the GDB response. - { - end = parsingInstruction.find('$', parsePos); - if (parsingInstruction.substr(parsePos, end - parsePos) == "END") - break; - if (parsingInstruction.substr(parsePos, end - parsePos) == "EOR") // move respBegin to the end of the response, probably - // to start looking from the end to the begin. - respBegin = response->length() - 1; - parsePos = end + 2; - } - continue; - } - - } - return(result); -} - - -/// -/// Function used to call the parser that will parse a GDB response according to the parsing instruction, returning this parsed -/// response. Call this function when starting GDB (this one doesn't use the OutputBuffer because it returns the parsed response). -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Returns the parsed GDB response. -string parseGDB(string response, string parsingInstruction) -{ - char variables[10][128]; - char result[ParsedMessageSize] = ""; - - strcpy(result, parseGDB(&response, parsingInstruction, 0, false, variables, "#").substr(0, ParsedMessageSize - 1).c_str()); - - return (result); -} - - -/// -/// Function used to call the parser that will parse a GDB response according to the parsing instruction, storing the parsed -/// response in the Output Buffer. Call this function if NOT USING multithreaded parsing -/// -/// GDB response. -/// Instruction used to parse the respective GDB response. -/// Position in the Output Buffer in which the parsed response will be stored. -void parseGDB(string response, string parsingInstruction, int seqStamp) -{ - char variables[10][128]; - char result[ParsedMessageSize] = ""; - string parsed = ""; - - char print[16384] = ""; - strcpy(print, ("GDB - " + response).c_str()); - parsedLogPrint(print); - - parsed = parseGDB(&response, parsingInstruction, 0, false, variables, "#").substr(0, ParsedMessageSize - 1); - strcpy(result, parsed.c_str()); - - strcpy(print, ("Parsed - " + parsed).c_str()); - parsedLogPrint(print); - - if (strcmp(result,"") == 0) - { - // TODO? Unexpected response. Must handle it. - strcpy(result, "$#@EMPTY@#$"); // Sending this string to be sure that the parser worked well and returned an empty string. - } - - while (!addIntoOutputBuffer(seqStamp, result)) - Sleep(0); -} - - -/// -/// Thread used to call the parser that will parse a GDB response according to the parsing instruction, storing the parsed -/// response in the Output Buffer. Call this function if USING multithreaded parsing. One thread per each GDB response. -/// -/// A ParsingThreadDetails data structure that stores the following data: -/// - response (GDB response); -/// - parsingInstruction (Parsing instruction); and -/// - seqStamp (Output buffer index where the parsed response will be stored). -/// 0 -unsigned __stdcall parseGDBResponseThread(void *arg) -{ - ParsingThreadDetails *d = (ParsingThreadDetails *)arg; - string response = d->response; - string parsingInstruction = d->parsingInstruction; - int seqStamp = *(d->seqStamp); - - char result[ParsedMessageSize] = ""; - char variables[10][128]; - string parsed = ""; - - char print[4096] = ""; - strcpy(print, ("GDB - " + response).c_str()); - parsedLogPrint(print); - - parsed = parseGDB(&response, parsingInstruction, 0, false, variables, "#").substr(0, ParsedMessageSize - 1); - strcpy(result, parsed.c_str()); - - strcpy(print, ("Parsed - " + parsed).c_str()); - parsedLogPrint(print); - - if (strcmp(result,"") == 0) - { - // TODO? Unexpected response. Must handle it. - strcpy(result, "$#@EMPTY@#$"); // Sending this string to be sure that parsed worked well and returned an empty string. - } - - while (!addIntoOutputBuffer(seqStamp, result)) - Sleep(0); - - return 0; -} - -/// -/// Generic function to print the GDB response and the parsed one to a log file. -/// -/// Message to be printed to a log file. -void parsedLogPrint(char* buffer) { - if (LOG_GDB_RAW_IO) { - time_t tt = time(NULL); - struct tm tm; - char buf[32]; - - tm = *localtime(&tt); - - strftime(buf, 31, "%H:%M:%S", &tm); - - FILE* file = fopen((char *)parse_log, "a"); - if (buffer[0] == 'P') - fprintf(file, "%s - %s\n\n", buf, buffer); - else - fprintf(file, "%s - %s", buf, buffer); - fclose(file); - } -} - -/// -/// Thread responsible for listening for GDB outputs. Thread sendingCommands2GDB start this one, that stays alive till the -/// end of the debugging session. -/// -/// A ListeningThreadData data structure that stores the following data: -/// - console (Current instance of GDB debugger); and -/// - parsingInstructions (Parsing instruction). -/// 0 -unsigned __stdcall listeningGDB(void *arg) -{ - ListeningThreadData *listen = (ListeningThreadData *)arg; - - int seqStamp = SyncInstructionsSize; // Positions 0 to 49 are reserved for synchronous commands - - string response = ""; - int getMoreData = 10; // used when the GDB output does not have a complete response. - - while(!exitGDB) // exitGDB is set to true by sendingCommands2GDB thread, when the debugging sessiong ends. - { - int instructionCode; - int gdbPos; - - response += listen->console->waitForPrompt(false); - - gdbPos = response.find("(gdb)"); - - while (gdbPos == 0) - { - response.erase(0,5); - gdbPos = response.find("(gdb)"); - } - - if ((gdbPos == -1) && (response.length() > 3)) - gdbPos = response.length(); - - while (gdbPos != -1) // Just in case gdb was faster than our debugger. If that happens, there will be two or more responses - // in the buffer, so we have to parse each of them individually. - { - int asyncRunning = -1; - int asyncStopped = -1; - int seqId; - string param = ""; - string oneResponse; - - oneResponse = response.substr(0, gdbPos); - - asyncRunning = oneResponse.find("*running"); - asyncStopped = oneResponse.find("*stopped"); - if ((asyncRunning != -1) && (asyncStopped != -1)) - { - if (asyncRunning > asyncStopped) - gdbPos = asyncRunning; - else - gdbPos = asyncStopped; - oneResponse = oneResponse.substr(0, gdbPos); - } - - seqId = getSeqID(oneResponse); - instructionCode = removeFromGDBBuffer(seqId, ¶m); - - if (param != "") - { - oneResponse = oneResponse.erase(oneResponse.length() - 2, 2); - oneResponse = oneResponse + param + '\r' + '\n'; - } - - if (instructionCode == -1) - { - getMoreData -= 1; // get more data from buffer to try to identify the type of the response - if (getMoreData == 0) - instructionCode = 0; // it was not possible to identify the type of the response after reading buffer 10 times. - // Consider it an asynchronous one. - else - break; // don't erase the response... Trying to get more data. - } - - getMoreData = 10; - - if (instructionCode != -1) - { - // Create a thread to parse the response with parsingInstructions[instructionCode]. Send also a sequencial number, - // so VS can sort the results. Can use multiple parsing threads or not, depending on the const value MultipleThreads - // defined in gdb-connect.h - if (MultipleThreads) - { - HANDLE ParsingThread = new(HANDLE); - unsigned ParsingThreadID; - - ParsingThreadDetails *details = new(ParsingThreadDetails); - - details->parsingInstruction = new(char[listen->parsingInstructions[instructionCode].length()]); - strcpy(details->parsingInstruction, listen->parsingInstructions[instructionCode].c_str()); - details->response = new(char[oneResponse.length()]); - strcpy(details->response, oneResponse.c_str()); - details->seqStamp = new(int); - if ((seqId >= 0) && (seqId < SyncInstructionsSize)) - *(details->seqStamp) = seqId; - else - *(details->seqStamp) = seqStamp; - - ParsingThread = (HANDLE)_beginthreadex( NULL, 0, &parseGDBResponseThread, (void *)details, 0, &ParsingThreadID); - } - else // Without multiple parsing threads - { - if ((seqId >= 0) && (seqId < SyncInstructionsSize)) - parseGDB(oneResponse.c_str(), listen->parsingInstructions[instructionCode].c_str(), seqId); - else - parseGDB(oneResponse.c_str(), listen->parsingInstructions[instructionCode].c_str(), seqStamp); - } - - if ((seqId < 0) || (seqId >= SyncInstructionsSize)) - { - seqStamp++; - seqStamp = (seqStamp % SyncInstructionsSize) + SyncInstructionsSize; - } - } - if ((asyncRunning == -1) || (asyncStopped == -1)) - gdbPos += 5; - response.erase(0, gdbPos); - gdbPos = response.find("(gdb)"); - - if (gdbPos == -1) - if (response.length() > 3) - gdbPos = response.length(); - else - response = ""; - }; - } - - exitGDB = false; - - return 0; -} - - -/// -/// Get the associated instruction ID from the command to be sent to GDB. -/// -/// Command to be sent to GDB. -/// Hash map data structure that contains the GDB commands recognized by the parser and their respectives -/// instructions IDs. -/// When the instruction code stored in "map" is negative, it means that the commands parameters must be saved to -/// be used by the listeningGDB thread. When that happens, update and return variable "param". -/// Returns the instruction code for the command to be sent to GDB or -1 in case of an error. It can also return the command -/// parameters, as it was described above. -int getInstructionCode(string command, unordered_map map, string *param) -{ - int pos = command.find(" "); - if (pos != -1) - { - *param = command.substr(pos, (command.length() -pos)); - (*param)[0] = ';'; - int i = (*param).find(" "); - while (i != -1) - { - (*param)[i] = ';'; - i = (*param).find(" "); - } - command = command.substr(0, pos); - } - unordered_map::iterator it = map.find(command); - if (it != map.end()) - { - if (it->second > 0) - { - *param = ""; - return (it->second); - } - else - { - return ((it->second) * -1); - } - } - printf("Command code not found."); - return -1; -} - - -/// -/// Initialize the hash map data structure "map" in which each entry contains a GDB command that is currently recognized by -/// the parser with its respective instruction ID. It loads these information from Instructions.txt file, in where each line has the -/// following format: -/// {$}gdb-command:->:parsing-instruction; -/// It must have the $ sign in front of the GDB command when it is needed to store the command parameters to be used later by the -/// listeningGDB thread. This usually happens whenever the GDB response for a given command does not contains enough information, like -/// only "^done" for example, when the parser needs something else. The ":->:" separates the GDB command from the parsing Instruction. -/// -/// Hash map data structure that contains the GDB commands recognized by the parser and their respectives -/// instructions IDs. -/// A string array with all of the currently recognized parsing instructions. The index position -/// correponds to the instruction ID used in "map" for the respective GDB command. -/// 1 in case of sucess; 0 if there is an error when opening the Instructions.txt file. -bool insertingCommandCodes(unordered_map *map, string parsingInstructions[NumberOfInstructions]) -{ - String^ StringFilePath = Environment::GetFolderPath(Environment::SpecialFolder::ProgramFilesX86) + "\\BlackBerry\\VSPlugin-NDK\\Instructions.txt"; - pin_ptr FilePath = PtrToStringChars(StringFilePath); - - ifstream inputs; - inputs.open (FilePath); - - if (!inputs.is_open()) - { - cout << "\nCouldn't open Instructions.txt.\n"; - return 0; - } - int count = 0; - while(true) - { - string instruction; - int pos; - getline(inputs, instruction); - if (inputs.eof()) - { - break; - } - - pos = instruction.find(":->:"); - if (instruction[0] != '$') - { - (*map).insert(unordered_map::value_type(instruction.substr(0, pos), count)); - } - else // need to get the parameters from the GDB command and insert them into the GDB response. Count will be negative so sending and listening threads will know about that. - { - (*map).insert(unordered_map::value_type(instruction.substr(1, pos - 1), count * -1)); - } - instruction.erase(0, pos + 4); - parsingInstructions[count] = instruction; - count++; - } - - inputs.close(); - return (1); -} - - -/// -/// Thread responsible for sending commands to GDB. The GDBParserAPI LaunchProcess start this one, that stays alive until it receives -/// a -gdb-exit instruction. This thread initializes the main data structures that are needed by teh parser and the listeningGDB thread. -/// -/// A reference to the GDB console (Current instance of GDB debugger). -/// 0 -unsigned __stdcall sendingCommands2GDB(void *arg) -{ - GDBConsole *console = (GDBConsole *)arg; - - String^ tempPath = Environment::GetEnvironmentVariable("APPDATA"); - tempPath += "\\BlackBerry\\parsedGDBResponse-output.log"; - pin_ptr path_buffer = PtrToStringChars(tempPath); - - int ret = wcstombs(parse_log, path_buffer, _MAX_PATH); - - FILE* file = fopen(parse_log, "w"); // Delete a possible existing file. - fclose(file); - - // Initializing listeningGDB thread data. - HANDLE listeningThread; - unsigned threadID; - ListeningThreadData listeningThreadData; - void *listen = &listeningThreadData; - - int seq_id = SyncInstructionsSize; // Positions 0 to 49 are reserved for synchronous commands. - int countExecInterrupt = 0; - - // Initializing mutex and event objects. - hGDBBufferMutex = CreateMutex (NULL, FALSE, NULL); - hOutputBufferMutex = CreateMutex (NULL, FALSE, NULL); - hInputBufferMutex = CreateMutex (NULL, FALSE, NULL); - inputEvent = CreateEventW(NULL, FALSE, FALSE, _T("inputEvent")); - asyncOutputEvent = CreateEventW(NULL, FALSE, FALSE, _T("asyncOutputEvent")); - - GDBBuffer.quantity = 0; - - unordered_map commandCodesMap; - string parsingInstructions[NumberOfInstructions]; - - if(!insertingCommandCodes(&commandCodesMap, parsingInstructions)) - { - printf("Error initializing parsing data structures"); - } - - // Starting listeningGDB thread. - listeningThreadData.console = console; - listeningThreadData.parsingInstructions = parsingInstructions; - listeningThread = (HANDLE)_beginthreadex( NULL, 0, &listeningGDB, (void *)listen, 0, &threadID); - - char lastCommandSend[GDBCommandSize] = ""; - - while (true) - { - char inputCommandSend[GDBCommandSize] = ""; - char commandSend[GDBCommandSize] = ""; - int instructionCodeSend; - string param = ""; - bool sync = false; - int previousSeqId; - char print[256] = "Command - "; - - removeFromInputBuffer(inputCommandSend); - while (strcmp(inputCommandSend,"") == 0) - { - if (in_InputBuffer == out_InputBuffer) // if true, input buffer is empty. - WaitForSingleObject(inputEvent, WAIT_TIME); - removeFromInputBuffer(inputCommandSend); - } - - if ((inputCommandSend[0] >= '0') && (inputCommandSend[0] <= '4')) // Means that it is a synchronous command and the instruction - // already has the ID. - { - sync = true; - previousSeqId = seq_id; - seq_id = ((inputCommandSend[0] - '0') * 10) + (inputCommandSend[1] - '0'); - char *aux_str = inputCommandSend + 2; - strcpy(inputCommandSend, aux_str); - } - - if (strcmp(inputCommandSend, "-exec-interrupt") == 0) - { - if ((strcmp(lastCommandSend, "-exec-interrupt") == 0) && (countExecInterrupt < 5)) - { - countExecInterrupt++; - console->sendCtrlC(); - continue; - } - countExecInterrupt = 0; - // Wait for existing commands to finish - while (!isGDBBufferEmpty()) - Sleep(0); - - console->sendCtrlC(); - } - - if (strcmp(inputCommandSend, "-gdb-exit") == 0) - { - break; - } - - if ((strcmp(inputCommandSend, "-exec-continue") == 0) || (strcmp(inputCommandSend, "-exec-continue --thread 1") == 0)) - // GDB some times lose the commands that were sent while it was running an -exec-continue, what can cause a deadlock. So, - // waiting for the previous commands to finish. - { - while (!isGDBBufferEmpty()) - Sleep(0); - } - - itoa(seq_id, commandSend, 10); - - strcat(commandSend, inputCommandSend); - strcat(commandSend, "\r\n"); - - instructionCodeSend = getInstructionCode(inputCommandSend, commandCodesMap, ¶m); - if (instructionCodeSend == -1) - break; - - int bufferPos = seq_id; // Calculate GDB buffer position. Had to do now because I know if the instruction is synchronous or not. - if (bufferPos >= SyncInstructionsSize) - { // Avoid writing in the first 50 positions that are reserved for synchronous instructions. - bufferPos = (bufferPos % SyncInstructionsSize) + SyncInstructionsSize; - } - - while (!addIntoGDBBuffer(bufferPos, instructionCodeSend, param)) - { - printf("Position in GDB buffer is full!"); - Sleep(0); - } - - console->sendCommand(commandSend); - - strcat(print, commandSend); - parsedLogPrint(print); - - if ((strcmp(inputCommandSend, "-exec-continue") == 0) || (strcmp(inputCommandSend, "-exec-continue --thread 1") == 0)) - { - while (!isGDBBufferEmpty()) - Sleep(0); - } - strcpy(lastCommandSend, inputCommandSend); - - if (!sync) - seq_id++; - else - seq_id = previousSeqId; - }; - - exitGDB = true; - WaitForSingleObject(listeningThread, INFINITE); - - // Once GDB exits, further attempts to read or write to the GDB console will result in errors - if (console != NULL) { - delete console; - console = NULL; - } - - return 0; -} \ No newline at end of file diff --git a/src_vs2012/GDBParser/gdb-connect.h b/src_vs2012/GDBParser/gdb-connect.h deleted file mode 100644 index 3397bc66..00000000 --- a/src_vs2012/GDBParser/gdb-connect.h +++ /dev/null @@ -1,112 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -#include - -#include "stdafx.h" -#include -#include -#include -#include - -using namespace std; - -#define NumberOfInstructions 48 // Number of parsing instructions in Instructios.txt file. -#define InputBufferSize 50 // Input buffer is used by the debug engine to send GDB commands. -#define GDBBufferSize 100 // Intermediate buffer is used as a communication channel between - // sendingCommands2GDB and listeningGDB threads. -#define OutputBufferSize 100 // Output buffer is used to send the parsed GDB responses to the debug engine. -#define SyncInstructionsSize 50 // This number is used to separate the Output buffer in two parts: first part - // for synchronous commands; and second for asynchronous ones. -#define GDBCommandSize 256 // Maximum size for a GDB command. -#define ParsedMessageSize 8192 // Maximum size for a parsed GDB response. -#define MultipleThreads 0 // 1 - use multiple parsing threads, 0 - single parsing thread. -#define MAX_EVENT_NAME_LENGTH 256 -#define WAIT_TIME 1000L // max amount of time to wait for single events. - -#define LOG_GDB_RAW_IO 1 // 1 - generate GDB output log file; 0 - do not generate. - -class GDBConsole { - -private: - static GDBConsole* m_instance; // represents an instance of GDB debugger. - HANDLE m_hInputRead, m_hInputWrite, m_hOutputRead, m_hOutputWrite, m_hErrorWrite; - BOOL m_isClosed; - static TCHAR* m_pcGDBCmd; - DWORD m_pid; - HANDLE m_hProcess; - HANDLE m_eventCtrlC; - HANDLE m_eventTerminate; - HANDLE m_hCleanupMutex; - - GDBConsole(); - void cleanup(); - HANDLE getStdOutHandle(); - BOOL isClosed(); - BOOL isMoreOutputAvailable (); - void logPrint(char*); - void prepAndLaunchRedirectedChild(); - int readOutput(CHAR*, int, int*); - -public: - ~GDBConsole(); - static GDBConsole* getInstance(); - int sendCommand(const CHAR*); - void sendCtrlC(); - static void setGDBPath(const TCHAR*); - static void shutdown(); - string waitForPrompt(bool); - string waitForPromptWithTimeout(int); -}; - -void DisplayError(LPCTSTR); -void ErrorExit(LPTSTR); - -void parsedLogPrint(char*); - -// Threads responsible for calling the right GDBConsole methods to send commands to GDB and to get responses from GDB. They are also -// responsible for handling the messages that are sent to/received from GDB. -unsigned __stdcall listeningGDB(void *); -unsigned __stdcall sendingCommands2GDB(void *); - -// Functions that perform some specific tasks to the above threads responsible for sending GDB commands and receiving GDB responses. -int getInstructionCode(string, unordered_map, string*); -int getSeqID(string); -bool insertingCommandCodes(unordered_map *, string [NumberOfInstructions]); - -// Functions/thread responsible for parsing GDB responses. -unsigned __stdcall parseGDBResponseThread(void *); // Call this function if using multithreaded parsing or (see below). -void parseGDB(string, string, int); // call this function if not using multithreaded parsing. -string parseGDB(string, string); // Call this function when starting GDB (this one doesn't use the OutputBuffer). -string parseGDB(string*, string, int, bool, char[10][128], string); // The above functions will call this one that is the one responsible for parsing the GDB response. - -// Functions that perform some specific tasks to the one responsible for parsing GDB responses. -int findClosing(char, char, string, int); -int getNextChar(char, string, int); -int searchResponse(string, string, int, int, bool, char); -string substituteVariables(string, char[10][128]); - -// The following methods are responsible for manipulating the buffers (Input, GDB and Output). -void cleanBuffers(); -bool addIntoInputBuffer(char [GDBCommandSize]); -void removeFromInputBuffer(char *); -bool isInputBufferEmpty(); -bool addIntoGDBBuffer(int, int, string); -int removeFromGDBBuffer(int, string*); -bool isGDBBufferEmpty(); -bool addIntoOutputBuffer(int, char *); -void removeFromOutputBuffer(char *); -void removeSyncFromOutputBuffer(char *, int); \ No newline at end of file diff --git a/src_vs2012/GDBParser/resource.h b/src_vs2012/GDBParser/resource.h deleted file mode 100644 index b5cbeb73..00000000 --- a/src_vs2012/GDBParser/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - - -#define IDR_GDBPARSER 101 diff --git a/src_vs2012/GDBParser/stdafx.cpp b/src_vs2012/GDBParser/stdafx.cpp deleted file mode 100644 index 94616139..00000000 --- a/src_vs2012/GDBParser/stdafx.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#include "stdafx.h" - diff --git a/src_vs2012/GDBParser/stdafx.h b/src_vs2012/GDBParser/stdafx.h deleted file mode 100644 index 09d97b98..00000000 --- a/src_vs2012/GDBParser/stdafx.h +++ /dev/null @@ -1,54 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -// 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 XP or later. -#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. -#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. -#endif - -#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. -#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. -#endif - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include -#include -//#include - -#include - -#define BEGIN_NAMESPACE namespace VSNDK { namespace Parser { -#define END_NAMESPACE }; }; - -BEGIN_NAMESPACE -END_NAMESPACE - -using namespace VSNDK::Parser; diff --git a/src_vs2012/GDBWrapper/GDBWrapper.cpp b/src_vs2012/GDBWrapper/GDBWrapper.cpp deleted file mode 100644 index 8acc8736..00000000 --- a/src_vs2012/GDBWrapper/GDBWrapper.cpp +++ /dev/null @@ -1,324 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - - -// GDBWrapper.cpp : Utility to run GDB in console mode so that CTRL-C works. -// - -#include "stdafx.h" - -#include -#include - -#include -#include -#include -#include - -#include - -#include "GDBWrapper.h" -#include < vcclr.h > - -// ******************************************************************* -// TODO: Put the following functions in a library that both GDBWrapper -// and GDBConsole can use - -using namespace std; -using namespace System; - -char path_log[_MAX_PATH]; // contains the path to the Wrapper output log, needed in logPrint() - - -/// -/// Displays the error number and corresponding message. -/// -/// Error message. -void DisplayError(LPCTSTR pszAPI) -{ - LPVOID lpvMessageBuffer; - TCHAR szPrintBuffer[512]; - DWORD bufSize = 512 * sizeof(TCHAR); - DWORD nCharsWritten; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpvMessageBuffer, 0, NULL); - - StringCbPrintf(szPrintBuffer, bufSize, - _T("ERROR: API = %s.\n error code = %d.\n message = %s.\n"), - pszAPI, GetLastError(), (char *)lpvMessageBuffer); - - _tprintf(_T("%s\n"), szPrintBuffer); - - LocalFree(lpvMessageBuffer); - ExitProcess(GetLastError()); -} - - -/// -/// Retrieve the system error message for the last-error code. -/// -/// Error message. -void ErrorExit(LPTSTR lpszFunction) -{ - LPVOID lpMsgBuf; - LPVOID lpDisplayBuf; - DWORD dw = GetLastError(); - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL ); - - // Display the error message and exit the process - - lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, - (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); - StringCchPrintf((LPTSTR)lpDisplayBuf, - LocalSize(lpDisplayBuf) / sizeof(TCHAR), - TEXT("%s failed with error %d: %s"), - lpszFunction, dw, lpMsgBuf); - MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); - - LocalFree(lpMsgBuf); - LocalFree(lpDisplayBuf); - ExitProcess(dw); -} - - -/// -/// Generic function to print to a log file. -/// -/// Message to be printed to a log file. -void logPrint(TCHAR* buffer) { - if (LOG_GDB_RAW_IO) { - FILE* file = fopen(path_log, "a"); - _ftprintf(file, _T("%s\r\n"), buffer); - fclose(file); - } -} - -// End region that needs to go into a library -// ******************************************************************* - - -/// -/// CTRL-C handler. -/// -/// CTRL type. -/// True; False. -BOOL WINAPI ctrlHandler(DWORD dwCtrlType) -{ - logPrint(_T("ctrlHandler")); - if (dwCtrlType == CTRL_C_EVENT) { - logPrint(_T("ctrlHandler got CTRL_C_EVENT")); - return true; - } - logPrint(_T("ctrlHandler returns false")); - return false; -} - - -/// -/// Constructor. -/// -/// String with full path and command to initialize GDB/MI. -/// Ctrl-C handler; -/// Terminate handler; -GDBWrapper::GDBWrapper(TCHAR* pcGDBCmd, HANDLE eventCtrlC, HANDLE eventTerminate) : - m_eventCtrlC(eventCtrlC), m_eventTerminate(eventTerminate), m_isClosed(FALSE) -{ - SECURITY_ATTRIBUTES sa; - - // Copy path to GDB - size_t numChars = _tcslen(pcGDBCmd) + 1; - m_pcGDBCmd = new TCHAR[numChars * sizeof(TCHAR)]; - _tcscpy_s(m_pcGDBCmd, numChars, pcGDBCmd); - - // Register CTRL-C handler - if (!SetConsoleCtrlHandler(ctrlHandler, TRUE)) { - DisplayError(_T("SetConsoleCtrlHandler")); - } - - // Set up the security attributes struct used when creating the pipes - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - prepAndLaunchRedirectedChild(); -} - - -/// -/// Shut down GDB Wrapper: Update variables and terminate GDBWrapper process. -/// -void GDBWrapper::shutdown() { - logPrint(_T("+shutdown")); - m_isClosed = TRUE; - - if (m_pcGDBCmd != NULL) { - delete[] m_pcGDBCmd; - m_pcGDBCmd = NULL; - } - - // Kill GDB process - TerminateProcess(m_hProcess, 0); - - if (!CloseHandle(m_hProcess)) DisplayError(_T("CloseHandle")); - logPrint(_T("-shutdown")); -} - - -/// -/// Destructor. -/// -GDBWrapper::~GDBWrapper() { - logPrint(_T("+~GDBWrapper")); - if (!m_isClosed) { - shutdown(); - } - logPrint(_T("-~GDBWrapper")); -} - - -/// -/// Sets up STARTUPINFO structure and launches redirected child. -/// -void GDBWrapper::prepAndLaunchRedirectedChild(void) -{ - LPCTSTR lpApplicationName = NULL; - PROCESS_INFORMATION pi; - STARTUPINFO si; - DWORD flags = 0; - - memset(&pi, 0, sizeof(pi)); - - // Set up the start up info struct. - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES; - - // Pass the redirected handles - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - - // Use this if you want to hide the child: - // si.wShowWindow = SW_HIDE; - // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to - // use the wShowWindow flags. - - /* CreateProcessW can modify pCmdLine thus we allocate memory */ - int pCmdSz = _tcslen(m_pcGDBCmd) + 1; - LPTSTR pCmdLine = new TCHAR[pCmdSz]; - if (pCmdLine == 0) { - DisplayError(_T("GDBWrapper::launch: failed to allocate memory for pCmdLine")); - } - _tcscpy_s(pCmdLine, pCmdSz, m_pcGDBCmd); - - // Launch the process - if (!CreateProcess(NULL, pCmdLine, NULL, NULL, TRUE, - flags, NULL, NULL, &si, &pi)) - ErrorExit(_T("CreateProcess")); - - m_hProcess = pi.hProcess; - - if (!CloseHandle(pi.hThread)) DisplayError(_T("CloseHandle")); -} - - -/// -/// GDBWrapper Main function. -/// -/// Not used. -/// argv[0] -> Full path of the GDBWrapper executable file. -/// argv[1] -> String with full path and command to initialize GDB/MI -/// argv[2] -> Ctrl-C handler; -/// argv[3] -> Terminate handler. -/// 0 -int _tmain(int argc, _TCHAR* argv[]) -{ - TCHAR msg[1024]; - memset(msg, 0, 1024); - - WCHAR wszThisFile[MAX_PATH + 1]; - GetModuleFileName(NULL, wszThisFile, MAX_PATH + 1); - - String^ tempPath = Environment::GetEnvironmentVariable("APPDATA"); - tempPath += "\\BlackBerry\\wrapper.log"; - pin_ptr path_buffer = PtrToStringChars(tempPath); - - int ret = wcstombs ( path_log, path_buffer, _MAX_PATH ); - - FILE* file = fopen(path_log, "w"); // just to delete a possible existing file - fclose(file); - - logPrint(_T("Starting")); - - HANDLE handles[2]; - handles[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[2]); // Ctrl-C signal - handles[1] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]); // Signal to terminate the wrapper process - - _stprintf(msg, _T("args: %s %s %s %s\r\n"), argv[0], argv[1], argv[2], argv[3]); - _tprintf(msg); - logPrint(msg); - - _stprintf(msg, _T("Ctrl-C handler: name: %s handle: %p\r\n"), argv[2], handles[0]); - _tprintf(msg); - logPrint(msg); - - _stprintf(msg, _T("Terminate handler: name: %s handle: %p\r\n"), argv[3], handles[1]); - _tprintf(msg); - logPrint(msg); - - GDBWrapper* g = new GDBWrapper(argv[1], handles[0], handles[1]); - - BOOL exitProc = FALSE; - while(!exitProc) - { - // Wait for a CTRL-C event indicating GDB should be interrupted - logPrint(_T("WaitForMultipleObjects")); - DWORD event = WaitForMultipleObjects(2, handles, false, INFINITE); - switch (event) - { - case WAIT_OBJECT_0: - logPrint(_T("WAIT_OBJECT_0 (Ctrl-C)")); - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); - break; - case WAIT_OBJECT_0 + 1: - logPrint(_T("WAIT_OBJECT_0 + 1 (Terminate)")); - exitProc = TRUE; - break; - case WAIT_FAILED: - DisplayError(_T("WaitForSingleObject WAIT_FAILED")); - exitProc = TRUE; - break; - default: - exitProc = TRUE; - break; - } - } - - g->shutdown(); - - return 0; -} diff --git a/src_vs2012/GDBWrapper/GDBWrapper.h b/src_vs2012/GDBWrapper/GDBWrapper.h deleted file mode 100644 index 6568e359..00000000 --- a/src_vs2012/GDBWrapper/GDBWrapper.h +++ /dev/null @@ -1,47 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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. - -#pragma once - -#include -#include - -#include "stdafx.h" -#include -#include -#include - -using namespace std; - -#define LOG_GDB_RAW_IO 1 - -class GDBWrapper { - -private: - BOOL m_isClosed; - HANDLE m_hProcess; - HANDLE m_eventCtrlC; - HANDLE m_eventTerminate; - TCHAR* m_pcGDBCmd; - - void prepAndLaunchRedirectedChild(); - -public: - GDBWrapper(TCHAR*, HANDLE, HANDLE); - ~GDBWrapper(); - void shutdown(); -}; - -void ErrorExit(LPTSTR); -void DisplayError(LPCTSTR); \ No newline at end of file diff --git a/src_vs2012/GDBWrapper/GDBWrapper.vcxproj b/src_vs2012/GDBWrapper/GDBWrapper.vcxproj deleted file mode 100644 index 13d4d783..00000000 --- a/src_vs2012/GDBWrapper/GDBWrapper.vcxproj +++ /dev/null @@ -1,102 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {9A560339-44DB-413F-868C-403962C2CF01} - Win32Proj - GDBWrapper - - - - Application - true - Unicode - true - v110 - - - Application - false - true - Unicode - true - v110 - - - - - - - - - - - - - true - - - false - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - false - - - xcopy "$(OutDir)GDBWrapper.*" "$(OutputPath)" /d /y - Copying Executable to output directory. - - - - - - - - - - - Create - Create - - - - - - \ No newline at end of file diff --git a/src_vs2012/GDBWrapper/GDBWrapper.vcxproj.filters b/src_vs2012/GDBWrapper/GDBWrapper.vcxproj.filters deleted file mode 100644 index 58ea2b2e..00000000 --- a/src_vs2012/GDBWrapper/GDBWrapper.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/src_vs2012/GDBWrapper/GDBWrapper.vcxproj.user b/src_vs2012/GDBWrapper/GDBWrapper.vcxproj.user deleted file mode 100644 index 79ff5bc5..00000000 --- a/src_vs2012/GDBWrapper/GDBWrapper.vcxproj.user +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - WindowsLocalDebugger - - \ No newline at end of file diff --git a/src_vs2012/GDBWrapper/ReadMe.txt b/src_vs2012/GDBWrapper/ReadMe.txt deleted file mode 100644 index 051b81d3..00000000 --- a/src_vs2012/GDBWrapper/ReadMe.txt +++ /dev/null @@ -1,40 +0,0 @@ -======================================================================== - CONSOLE APPLICATION : GDBWrapper Project Overview -======================================================================== - -AppWizard has created this GDBWrapper application for you. - -This file contains a summary of what you will find in each of the files that -make up your GDBWrapper application. - - -GDBWrapper.vcxproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -GDBWrapper.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -GDBWrapper.cpp - This is the main application source file. - -///////////////////////////////////////////////////////////////////////////// -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named GDBWrapper.pch and a precompiled types file named StdAfx.obj. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" comments to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/src_vs2012/GDBWrapper/stdafx.h b/src_vs2012/GDBWrapper/stdafx.h deleted file mode 100644 index ee239709..00000000 --- a/src_vs2012/GDBWrapper/stdafx.h +++ /dev/null @@ -1,29 +0,0 @@ -//* Copyright 2010-2011 Research In Motion Limited. -//* -//* 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.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" - -#include -#include - - - -// TODO: reference additional headers your program requires here diff --git a/src_vs2012/NativeCore/BlackBerry.NativeCore.csproj b/src_vs2012/NativeCore/BlackBerry.NativeCore.csproj new file mode 100644 index 00000000..6ce91059 --- /dev/null +++ b/src_vs2012/NativeCore/BlackBerry.NativeCore.csproj @@ -0,0 +1,215 @@ + + + + + Debug + AnyCPU + {FADDD789-6CB5-4F9D-8481-1C0C72E5F19F} + Library + Properties + BlackBerry.NativeCore + BlackBerry.NativeCore + v4.5 + 512 + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2012;MAKE_CONFIG_DEFAULTS_PUBLIC + prompt + 4 + false + false + + + pdbonly + true + bin\Release\ + TRACE;CODE_ANALYSIS;PLATFORM_VS2012;MAKE_CONFIG_DEFAULTS_PUBLIC + prompt + 4 + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/NativeCore/Components/TargetConnectionEventArgs.cs b/src_vs2012/NativeCore/Components/TargetConnectionEventArgs.cs new file mode 100644 index 00000000..327c2f81 --- /dev/null +++ b/src_vs2012/NativeCore/Components/TargetConnectionEventArgs.cs @@ -0,0 +1,54 @@ +using System; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.QConn; + +namespace BlackBerry.NativeCore.Components +{ + /// + /// Arguments passed along with Targets class events. + /// + public sealed class TargetConnectionEventArgs : EventArgs + { + /// + /// Init constructor. + /// + public TargetConnectionEventArgs(DeviceDefinition device, QConnClient client, TargetStatus status, string message) + { + if (device == null) + throw new ArgumentNullException("device"); + + Device = device; + Client = client; + Status = status; + Message = message; + } + + #region Properties + + public DeviceDefinition Device + { + get; + private set; + } + + public QConnClient Client + { + get; + private set; + } + + public TargetStatus Status + { + get; + private set; + } + + public string Message + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Components/TargetStatus.cs b/src_vs2012/NativeCore/Components/TargetStatus.cs new file mode 100644 index 00000000..48eaaeec --- /dev/null +++ b/src_vs2012/NativeCore/Components/TargetStatus.cs @@ -0,0 +1,11 @@ +namespace BlackBerry.NativeCore.Components +{ + public enum TargetStatus + { + Initialized, + Connecting, + Connected, + Disconnected, + Failed + } +} diff --git a/src_vs2012/NativeCore/Components/Targets.cs b/src_vs2012/NativeCore/Components/Targets.cs new file mode 100644 index 00000000..f0060d5d --- /dev/null +++ b/src_vs2012/NativeCore/Components/Targets.cs @@ -0,0 +1,1188 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using BlackBerry.NativeCore.Debugger; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.QConn; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.Components +{ + /// + /// Tracker of already connected and disconnected devices. + /// + public static class Targets + { + #region Internal Classes + + /// + /// Method to verify, if specified log entry should be populated to the developer according to current settings. + /// + private delegate bool LogPredicate(TargetServiceConsoleLog service, TargetLogEntry log); + + /// + /// Method to format the output of the log message populated to all registered outputs. + /// + private delegate string LogFormatter(TargetLogEntry log); + + /// + /// Class providing help information about connection parameters with the target device. + /// + private sealed class TargetInfo : IDisposable + { + private AutoResetEvent _hasStatusEvent; + private readonly string _sshPublicKeyPath; + private readonly string _sshPrivateKeyPath; + private volatile bool _startingSLog2; + + public event EventHandler StatusChanged; + + public TargetInfo(DeviceDefinition device, string sshPublicKeyPath, string sshPrivateKeyPath) + { + if (device == null) + throw new ArgumentNullException("device"); + if (string.IsNullOrEmpty(sshPublicKeyPath)) + throw new ArgumentNullException("sshPublicKeyPath"); + if (string.IsNullOrEmpty(sshPrivateKeyPath)) + throw new ArgumentNullException("sshPrivateKeyPath"); + + Status = TargetStatus.Initialized; + Device = device; + _hasStatusEvent = new AutoResetEvent(false); + _sshPublicKeyPath = sshPublicKeyPath; + _sshPrivateKeyPath = sshPrivateKeyPath; + + Client = new QConnClient(); + Door = new QConnDoor(); + Door.Authenticated += QConnDoorAuthenticationChanged; + } + + ~TargetInfo() + { + Dispose(false); + } + + #region Properties + + public DeviceDefinition Device + { + get; + private set; + } + + public QConnDoor Door + { + get; + private set; + } + + public QConnClient Client + { + get; + private set; + } + + public TargetProcessSLog2Info SLog2Info + { + get; + private set; + } + + public TargetStatus Status + { + get; + private set; + } + + #endregion + + #region IDisposable Implementation + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + if (_hasStatusEvent != null) + { + _hasStatusEvent.Dispose(); + _hasStatusEvent = null; + } + + StopLogServices(); + + if (Client != null) + { + Client.Dispose(); + Client = null; + } + + if (Door != null) + { + Door.Dispose(); + Door = null; + } + + StatusChanged = null; + } + } + + #endregion + + public bool HasIdenticalIP(string ip) + { + if (ip == null) + return false; + + return string.CompareOrdinal(Device.IP, ip) == 0; + } + + public bool Wait(int millisecondsTimeout) + { + if (_hasStatusEvent == null) + throw new ObjectDisposedException("TargetInfo"); + + return _hasStatusEvent.WaitOne(millisecondsTimeout); + } + + public void Start() + { + NotifyStatusChange(TargetStatus.Connecting, null); + + ///////////////////////////////////// + // Verify, if we are able to connect at all, where the public key is required: + if (!File.Exists(_sshPublicKeyPath)) + { + var ndk = NdkDefinition.Load(); + if (ndk == null || !Directory.Exists(ndk.HostPath)) + { + NotifyStatusChange(TargetStatus.Failed, "Unable to create public SSH key to establish connection. Download BlackBerry Native SDK first."); + return; + } + + // generate SSH public key blocking current thread till completed: + var tool = new SshCreateKeyRunner(Path.Combine(ndk.HostPath, "usr", "bin", "ssh-keygen.exe"), _sshPublicKeyPath, _sshPrivateKeyPath, 4096); + if (!tool.Execute()) + { + NotifyStatusChange(TargetStatus.Failed, "Public SSH key creation failed."); + return; + } + } + + ///////////////////////////////////// + // Trick of the day: there can be only one QConnDoor connection setup to the device + // so it might happen, we already opened one in Visual Studio, Momentics or on + // another machine; so let's try, if it's possible to communicate with device services. + try + { + Client.Load(Device.IP, QConnClient.DefaultPort, 1000); + InitializeLogServices(); + + // all is fine, connection established, no need to have own QConnDoor + NotifyStatusChange(TargetStatus.Connected, null); + return; + } + catch + { + // invalid device nor QConnDoor not yet opened by others... + } + + Door.OpenAsync(Device.IP, Device.Password, _sshPublicKeyPath); + } + + private void QConnDoorAuthenticationChanged(object sender, QConnAuthenticationEventArgs e) + { + TraceLog.WriteLine("Target status changed to: {0} for: {1}", e.IsAuthenticated ? "authenticated" : "disconnected", Device); + + if (e.IsAuthenticated) + { + // load info about services: + try + { + Client.Load(Device.IP); + InitializeLogServices(); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Failed to load info about target's services"); + NotifyStatusChange(TargetStatus.Failed, "Failed to load info about services on target"); + } + + // start keeping-alive the connection: + try + { + Door.KeepAlive(QConnDoor.DefaultKeepAliveInterval); // this will continuously asynchronously send the keep-alive request + NotifyStatusChange(TargetStatus.Connected, null); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Failed to start keeping the connection alive"); + NotifyStatusChange(TargetStatus.Failed, "Lost connection to the device"); + } + + } + else + { + if (Status == TargetStatus.Connected) + { + NotifyStatusChange(TargetStatus.Disconnected, "Device has been disconnected"); + } + else + { + NotifyStatusChange(TargetStatus.Failed, "Failed to connect to the device"); + } + } + + // then notify Targets class, so it updates the internal state: + OnChildConnectionStatusChanged(this, Status); + } + + public bool StopLogServices() + { + bool disposed = false; + + var slog2 = SLog2Info; + SLog2Info = null; + + if (slog2 != null) + { + if (Client != null && Client.ControlService != null) + { + try + { + Client.ControlService.Terminate(slog2); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to terminate slog2info"); + } + } + + slog2.Dispose(); + disposed = true; + } + + if (Client != null) + { + if (Client.ConsoleLogService != null) + { + Client.ConsoleLogService.Captured -= OnRemoteLogsCaptured; + disposed = true; + } + } + + return disposed; + } + + private void InitializeLogServices() + { + // setup console logging: + if (Client != null && Client.ConsoleLogService != null) + { + Client.ConsoleLogService.Captured -= OnRemoteLogsCaptured; + Client.ConsoleLogService.Captured += OnRemoteLogsCaptured; + } + + // setup slog2info monitor to grab all the logs from the device: + if (_startingSLog2) + { + return; + } + + try + { + _startingSLog2 = true; + if (Client != null && Client.LauncherService != null && SLog2Info == null) + { + try + { + SLog2Info = Client.LauncherService.Start("/bin/slog2info", new[] { "-n", "-W", "-s" }); + TraceLog.WriteLine("Started slog2info with PID: {0}", SLog2Info.PID); + } + catch (Exception ex) + { + SLog2Info = null; + + // probably PlayBook... + TraceLog.WriteException(ex, "Failed to start slog2info remotely"); + } + + if (SLog2Info != null) + { + SLog2Info.Captured += OnRemoteLogsCaptured; + SLog2Info.Finished += OnSLog2InfoFinished; + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to launch slog2info to monitor all activities on the device"); + } + finally + { + _startingSLog2 = false; + } + } + + private void OnSLog2InfoFinished(object sender, EventArgs e) + { + TraceLog.WriteLine("Terminated slog2info"); + + var slog2 = SLog2Info; + SLog2Info = null; + + if (slog2 != null) + { + slog2.Captured -= OnRemoteLogsCaptured; + slog2.Finished -= OnSLog2InfoFinished; + } + } + + private void OnRemoteLogsCaptured(object sender, CapturedLogsEventArgs e) + { + foreach (var log in e.Entries) + { + // print each console log and slog2 which matches current settings: + if (log.Type == TargetLogEntry.LogType.Console || _optionSLog2Filter(Client.ConsoleLogService, log)) + { + PrintLog(log); + } + } + } + + private void NotifyStatusChange(TargetStatus status, string message) + { + if (status != Status) + { + Status = status; + + var handler = StatusChanged; + if (handler != null) + { + handler(this, new TargetConnectionEventArgs(Device, Client, status, message)); + } + } + + // and wake up waiters, if needed... + if (status != TargetStatus.Connecting) + { + if (_hasStatusEvent != null) + { + _hasStatusEvent.Set(); + } + } + } + + public TargetConnectionEventArgs ToEventArgs() + { + return new TargetConnectionEventArgs(Device, Client, Status, null); + } + + /// + /// Method to verify internal state, when another connection is supposed to be opened to this target. + /// + public void NewConnectionRequested() + { + InitializeLogServices(); + } + } + + #endregion + + private static readonly List _activeTargets; + private static readonly object _sync; + + private static bool _optionInjectLogs; + private static bool _optionAcceptTracingDebuggedOnly; + private static uint _optionLogInterval; + private static LogPredicate _optionSLog2Filter; + private static LogFormatter _optionSLog2Formatter; + private static string[] _optionSLog2BufferSets; + private static string _optionCategoryInject; + + static Targets() + { + _activeTargets = new List(); + _sync = new object(); + + _optionInjectLogs = true; + _optionAcceptTracingDebuggedOnly = false; + _optionLogInterval = 0; + _optionSLog2Filter = SLog2FilterDefault; + _optionSLog2Formatter = SLog2FormatterDefault; + _optionCategoryInject = TraceLog.CategoryDevice; + } + + private static TargetInfo NoSyncFind(string ip) + { + foreach (var target in _activeTargets) + if (target.HasIdenticalIP(ip)) + return target; + + return null; + } + + /// + /// Finds info about connection to the device with specified IP. + /// + private static TargetInfo Find(string ip) + { + lock (_sync) + { + return NoSyncFind(ip); + } + } + + /// + /// Gets an indication, if there is already a valid connection to the device with given IP. + /// + public static bool IsConnected(string ip) + { + var connection = Find(ip); + return connection != null && connection.Status == TargetStatus.Connected; + } + + /// + /// Gets an indication, if there is already a valid connection to the device. + /// + public static bool IsConnected(DeviceDefinition device) + { + return device != null && IsConnected(device.IP); + } + + /// + /// Gets an indication, if there is trying to connect to the device with given IP. + /// + public static bool IsConnecting(string ip) + { + var connection = Find(ip); + return connection != null && connection.Status == TargetStatus.Connecting; + } + + /// + /// Gets an indication, if there is trying to connect to the device. + /// + public static bool IsConnecting(DeviceDefinition device) + { + return device != null && IsConnecting(device.IP); + } + + /// + /// Gets the manager of the device for advanced services. + /// + public static QConnClient Get(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + return Get(device.IP); + } + + /// + /// Gets the manager of the device for advanced services. + /// + public static QConnClient Get(string ip) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + + var existingTarget = Find(ip); + if (existingTarget != null && existingTarget.Status == TargetStatus.Connected) + { + return existingTarget.Client; + } + + return null; + } + + /// + /// Gets the manager of the device for advanced services. + /// It will try to automatically connect to the device, if needed and might block current thread for that time. + /// + public static QConnClient Get(DeviceDefinition device, string sshPublicKeyPath, string sshPrivateKeyPath) + { + if (device == null) + throw new ArgumentNullException("device"); + if (string.IsNullOrEmpty(sshPublicKeyPath)) + throw new ArgumentNullException("sshPublicKeyPath"); + if (string.IsNullOrEmpty(sshPrivateKeyPath)) + throw new ArgumentNullException("sshPrivateKeyPath"); + + var qClient = Get(device.IP); + + // need to connect first: + if (qClient == null) + { + Connect(device, sshPublicKeyPath, sshPrivateKeyPath, null); + + // wait until link established or error: + if (Wait(device.IP)) + { + qClient = Get(device.IP); + } + } + + return qClient; + } + + /// + /// Requests secure connection setup to given device. + /// + public static void Connect(string ip, string password, DeviceDefinitionType type, string sshPublicKeyPath, string sshPrivateKeyPath, EventHandler resultHandler) + { + Connect(new DeviceDefinition("Ad-hoc device", ip, password, type), sshPublicKeyPath, sshPrivateKeyPath, resultHandler); + } + + /// + /// Requests secure connection setup to given device. + /// + public static void Connect(DeviceDefinition device, EventHandler resultHandler) + { + if (device == null) + throw new ArgumentNullException("device"); + + Connect(device, ConfigDefaults.SshPublicKeyPath, ConfigDefaults.SshPrivateKeyPath, resultHandler); + } + + /// + /// Requests secure connection setup to given device. + /// + public static void Connect(DeviceDefinition device, string sshPublicKeyPath, string sshPrivateKeyPath, EventHandler resultHandler) + { + if (device == null) + throw new ArgumentNullException("device"); + if (string.IsNullOrEmpty(sshPublicKeyPath)) + throw new ArgumentNullException("sshPublicKeyPath"); + if (string.IsNullOrEmpty(sshPrivateKeyPath)) + throw new ArgumentNullException("sshPrivateKeyPath"); + + TargetInfo existingTarget; + lock (_sync) + { + existingTarget = NoSyncFind(device.IP); + + // this trick will let only one thread add new connection-info, if both blocked on the sync above: + if (existingTarget == null) + { + var newTarget = new TargetInfo(device, sshPublicKeyPath, sshPrivateKeyPath); + if (resultHandler != null) + { + newTarget.StatusChanged += resultHandler; + } + _activeTargets.Add(newTarget); + + // until we open the QConnDoor, it might report 'disconnected' state, that's why it's inside lock + newTarget.Start(); + } + else + { + existingTarget.NewConnectionRequested(); + + if (resultHandler != null) + { + existingTarget.StatusChanged += resultHandler; + } + } + } + + // check if already connected: + if (existingTarget != null) + { + // and notify the caller (it was already mounted to monitor the future status changes): + if (resultHandler != null) + { + resultHandler.BeginInvoke(null, existingTarget.ToEventArgs(), StatusHandlerAsyncCleanup, resultHandler); + } + } + } + + private static void StatusHandlerAsyncCleanup(IAsyncResult ar) + { + var resultHandler = (EventHandler) ar.AsyncState; + + try + { + resultHandler.EndInvoke(ar); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Targets status-change notification failed"); + } + } + + private static void OnChildConnectionStatusChanged(TargetInfo target, TargetStatus status) + { + if (target == null) + throw new ArgumentNullException("target"); + + bool dispose = false; + + if (status == TargetStatus.Disconnected || status == TargetStatus.Failed) + { + lock (_sync) + { + dispose = _activeTargets.Remove(target); + } + } + + // only release the object, when it belong to the list + // (to avoid double-releases, in case external handlers manipulated the list): + if (dispose) + { + // and release resources: + target.Dispose(); + } + } + + /// + /// Stops receiving more events related to the connection state to the target device. + /// + public static bool Unsubscribe(DeviceDefinition device, EventHandler resultHandler) + { + if (device == null) + throw new ArgumentNullException("device"); + if (resultHandler == null) + throw new ArgumentNullException("resultHandler"); + return Unsubscribe(device.IP, resultHandler); + } + + /// + /// Stops receiving more events related to the connection state to the target device. + /// + public static bool Unsubscribe(string ip, EventHandler resultHandler) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (resultHandler == null) + throw new ArgumentNullException("resultHandler"); + + TargetInfo existingTarget; + + lock (_sync) + { + existingTarget = NoSyncFind(ip); + if (existingTarget != null) + { + existingTarget.StatusChanged -= resultHandler; + } + } + + return existingTarget != null; + } + + /// + /// Requests closing secure connection to given device. + /// + public static bool Disconnect(string ip) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + + TargetInfo existingTarget; + bool result = false; + + lock (_sync) + { + existingTarget = NoSyncFind(ip); + if (existingTarget != null) + { + result = _activeTargets.Remove(existingTarget); + } + } + + // and release resources: + if (existingTarget != null) + { + existingTarget.Dispose(); + } + + return result; + } + + /// + /// Requests closing secure connection to given device. + /// + public static bool Disconnect(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + return Disconnect(device.IP); + } + + /// + /// Waits until connection status changes to connected or failed for a given device. + /// + public static void Wait(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + Wait(device.IP); + } + + /// + /// Waits until connection status changes to connected or failed for a given device. + /// + public static bool Wait(string ip) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + + return Wait(GdbProcessor.ShortInfinite, ip); + } + + /// + /// Waits until connection status changes to connected or failed for a given device. + /// + public static bool Wait(int millisecondsTimeout, DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + return Wait(millisecondsTimeout, device.IP); + } + + /// + /// Waits until connection status changes to connected or failed for a given device. + /// + public static bool Wait(int millisecondsTimeout, string ip) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + + var existingTarget = Find(ip); + if (existingTarget != null) + { + return existingTarget.Wait(millisecondsTimeout); + } + + return false; + } + + /// + /// Forces disconnection for all kwnon devices that are *outside* of this list. + /// + public static void DisconnectIfOutside(DeviceDefinition[] devices) + { + if (devices != null) + { + var toDisconnect = new List(); + lock (_sync) + { + foreach (var target in _activeTargets) + { + if (!DeviceDefinition.ContainsWithIP(devices, target.Device.IP)) + { + toDisconnect.Add(target); + } + } + } + + // and now... disconnect them: + foreach (var target in toDisconnect) + { + Disconnect(target.Device); + } + } + } + + /// + /// Starts tracing console output for specified process on a target device. + /// It will fail, if not connected to that device before. + /// + public static bool Trace(string ip, ProcessInfo process, bool isDebugging) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (process == null) + throw new ArgumentNullException("process"); + + var qClient = Get(ip); + if (qClient == null || qClient.FileService == null || qClient.ConsoleLogService == null) + { + TraceLog.WarnLine("Unable to start tracing console outputs for: {0}:\"{1}\"", process.ID, process.ExecutablePath); + return false; + } + + if (_optionAcceptTracingDebuggedOnly && !isDebugging) + { + TraceLog.WarnLine("Tracing console outputs for non-debugged applications is disabled, change it in Options or manually start capturing logs in Target Navigator ({0}:\"{1}\")", + process.ID, process.ExecutablePath); + return false; + } + + // start monitoring for console logs: + return qClient.ConsoleLogService.Start(process, _optionLogInterval, isDebugging); + } + + /// + /// Starts tracing console output for specified process on a target device. + /// It will fail, if not connected to that device before. + /// + public static bool Trace(DeviceDefinition device, ProcessInfo process, bool isDebugging) + { + if (device == null) + throw new ArgumentNullException("device"); + if (process == null) + throw new ArgumentNullException("process"); + + return Trace(device.IP, process, isDebugging); + } + + /// + /// Stops all tracing. + /// + public static int TraceStop() + { + TargetInfo[] activeTargets; + + lock (_sync) + { + activeTargets = _activeTargets.ToArray(); + } + + int result = 0; + + if (activeTargets.Length > 0) + { + foreach (var target in activeTargets) + { + if (target.StopLogServices()) + { + result++; + } + } + } + + return result; + } + + /// + /// Stops tracing console output from all processes on a given target device. + /// + public static bool TraceStop(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + return TraceStop(device.IP); + } + + /// + /// Stops tracing console output from specified process on a given target device. + /// + public static bool TraceStop(DeviceDefinition device, ProcessInfo process) + { + if (device == null) + throw new ArgumentNullException("device"); + if (process == null) + throw new ArgumentNullException("process"); + + return TraceStop(device.IP, process); + } + + /// + /// Stops tracing console output from all processes on a given target device. + /// + public static bool TraceStop(string ip) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + + var qClient = Get(ip); + if (qClient != null && qClient.ConsoleLogService != null) + { + try + { + qClient.ConsoleLogService.StopAll(); + return true; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to stop console log monitors for: {0}", qClient.Name); + return false; + } + } + + return false; + } + + /// + /// Stops tracing console outputs from specified process on a given target device. + /// + public static bool TraceStop(string ip, ProcessInfo process) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (process == null) + throw new ArgumentNullException("process"); + + var qClient = Get(ip); + if (qClient != null && qClient.ConsoleLogService != null) + { + try + { + return qClient.ConsoleLogService.Stop(process); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to stop console log monitors for: {0}", qClient.Name); + return false; + } + } + + return false; + } + + /// + /// Checks, whether specified process' console output is traced. + /// + public static bool TraceIs(DeviceDefinition device, ProcessInfo process) + { + if (device == null) + throw new ArgumentNullException("device"); + if (process == null) + throw new ArgumentNullException("process"); + + return TraceIs(device.IP, process); + } + + /// + /// Checks, whether specified process' console output is traced. + /// + public static bool TraceIs(string ip, ProcessInfo process) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (process == null) + throw new ArgumentNullException("process"); + + var qClient = Get(ip); + if (qClient != null && qClient.ConsoleLogService != null) + { + return qClient.ConsoleLogService.IsMonitoring(process); + } + + return false; + } + + /// + /// Sets the logging options. + /// + public static void TraceOptions(bool debuggedOnly, uint logsInterval, int slog2Level, int slog2FormatterLevel, string[] slog2BufferSets, bool injectLogs, string injectCategory) + { + _optionInjectLogs = injectLogs; + _optionAcceptTracingDebuggedOnly = debuggedOnly; + _optionLogInterval = logsInterval; + _optionSLog2BufferSets = slog2BufferSets; + + if (!string.IsNullOrEmpty(injectCategory)) + { + _optionCategoryInject = injectCategory; + } + + switch (slog2Level) + { + case 0: // nothing should be monitored + _optionSLog2Filter = SLog2FilterNone; + break; + case 1: // only developed applications + if (slog2BufferSets == null || slog2BufferSets.Length == 0) + { + _optionSLog2Filter = SLog2FilterApps; + } + else + { + _optionSLog2Filter = SLog2FilterAppsWithBufferSet; + } + break; + case 2: // whole system + _optionSLog2Filter = SLog2FilterSystem; + break; + default: // restore default, if out-of-range + _optionSLog2Filter = SLog2FilterDefault; + break; + } + + switch (slog2FormatterLevel) + { + case 0: // default: + _optionSLog2Formatter = SLog2FormatterDefault; + break; + case 1: // prefixed with title: + _optionSLog2Formatter = SLog2FormatterTildeMessage; + break; + case 2: // prefixed with hash: + _optionSLog2Formatter = SLog2FormatterHashMessage; + break; + case 3: // prefixed with PID: + _optionSLog2Formatter = SLog2FormatterPidMessage; + break; + case 4: // prefixed with appID: + _optionSLog2Formatter = SLog2FormatterAppIdMessage; + break; + case 5: // prefixed with buffer-set: + _optionSLog2Formatter = SLog2FormatterBufferSetMessage; + break; + case 6: // prefixed with appID and buffer-set: + _optionSLog2Formatter = SLog2FormatterAppIdBufferSetMessage; + break; + case 7: // prefixed with PID and buffer-set: + _optionSLog2Formatter = SLog2FormatterPidBufferSetMessage; + break; + case 8: // prefixed with PID and appID: + _optionSLog2Formatter = SLog2FormatterPidAppIdMessage; + break; + default: // restore default, if out-of-range + _optionSLog2Formatter = SLog2FormatterDefault; + break; + } + + // and update the console log interval for already running loggers: + lock (_sync) + { + foreach (var target in _activeTargets) + { + if (target.Client != null && target.Client.ConsoleLogService != null) + { + target.Client.ConsoleLogService.Interval = logsInterval; + } + } + } + } + + /// + /// Writes the log with current formatting settings into the output. + /// + private static void PrintLog(TargetLogEntry log) + { + if (log.Type == TargetLogEntry.LogType.SLog2) + { + PrintLogMessage(_optionSLog2Formatter(log)); + } + else + { + PrintLogMessage(log.Message); + } + } + + private static void PrintLogMessage(string message) + { + TraceLog.WriteLine(message); + + // print logs on default 'Debug' output window, if allowed: + if (_optionInjectLogs) + { + System.Diagnostics.Trace.WriteLine(message, _optionCategoryInject); + } + } + + #region slog2 Formatter + + private static string SLog2FormatterDefault(TargetLogEntry log) + { + return log.Message; + } + + private static string SLog2FormatterTildeMessage(TargetLogEntry log) + { + return string.Concat("~ ", log.Message); + } + + private static string SLog2FormatterHashMessage(TargetLogEntry log) + { + return string.Concat("# ", log.Message); + } + + private static string SLog2FormatterPidMessage(TargetLogEntry log) + { + return string.Concat(log.PID, ": ", log.Message); + } + + private static string SLog2FormatterAppIdMessage(TargetLogEntry log) + { + return string.Concat(log.AppID, ": ", log.Message); + } + + private static string SLog2FormatterBufferSetMessage(TargetLogEntry log) + { + return string.Concat(log.BufferSet, ": ", log.Message); + } + + private static string SLog2FormatterAppIdBufferSetMessage(TargetLogEntry log) + { + return string.Concat(log.AppID, "::", log.BufferSet, ": ", log.Message); + } + + private static string SLog2FormatterPidBufferSetMessage(TargetLogEntry log) + { + return string.Concat(log.PID, "::", log.BufferSet, ": ", log.Message); + } + + private static string SLog2FormatterPidAppIdMessage(TargetLogEntry log) + { + return string.Concat(log.PID, "::", log.AppID, ": ", log.Message); + } + + #endregion + + #region slog2 Filters + + private static bool IsMonitoring(TargetServiceConsoleLog service, uint pid) + { + return !service.IsMonitoringAnything || service.IsMonitoring(pid); + } + + private static bool SLog2FilterDefault(TargetServiceConsoleLog service, TargetLogEntry log) + { + return log.PID == 0 || string.IsNullOrEmpty(log.BufferSet) || (IsMonitoring(service, log.PID) && log.BufferSet == "default"); + } + + private static bool SLog2FilterNone(TargetServiceConsoleLog service, TargetLogEntry log) + { + return false; + } + + private static bool SLog2FilterSystem(TargetServiceConsoleLog service, TargetLogEntry log) + { + return true; + } + + private static bool SLog2FilterApps(TargetServiceConsoleLog service, TargetLogEntry log) + { + return log.PID == 0 || IsMonitoring(service, log.PID); + } + + private static bool SLog2FilterAppsWithBufferSet(TargetServiceConsoleLog service, TargetLogEntry log) + { + return log.PID == 0 || (IsMonitoring(service, log.PID) && InBufferSet(log.BufferSet)); + } + + private static bool InBufferSet(string name) + { + if (_optionSLog2BufferSets == null || string.IsNullOrEmpty(name)) + return true; + + foreach (var bufferName in _optionSLog2BufferSets) + { + if (string.Compare(bufferName, name, StringComparison.Ordinal) == 0) + return true; + } + + return false; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Components/TokenProcessor.cs b/src_vs2012/NativeCore/Components/TokenProcessor.cs new file mode 100644 index 00000000..10f519e8 --- /dev/null +++ b/src_vs2012/NativeCore/Components/TokenProcessor.cs @@ -0,0 +1,479 @@ +/*************************************************************************** + +Copyright (c) Microsoft Corporation. All rights reserved. +This code is licensed under the Visual Studio SDK license terms. +THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. + +***************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; + +namespace BlackBerry.NativeCore.Components +{ + /// + /// Contain a number of functions that handle token replacement + /// + public sealed class TokenProcessor + { + #region Token Classes + + private abstract class ActionToken + { + public abstract int ID + { + get; + } + + public abstract void UpdateBuffer(StringBuilder buffer); + } + + /// + /// Storage classes for replacement tokens + /// + [DebuggerDisplay("{ID}: {Token} -> {Replacement}")] + private class ReplacePairToken : ActionToken + { + private readonly int _id; + + /// + /// Constructor + /// + /// Identifier of the action + /// replaceable token + /// replacement string + public ReplacePairToken(int id, string token, string replacement) + { + _id = id; + Token = token; + Replacement = replacement; + } + + /// + /// Identifier of the action. + /// + public override int ID + { + get { return _id; } + } + + /// + /// Token that needs to be replaced + /// + public string Token + { + get; + private set; + } + + /// + /// String to replace the token with + /// + public string Replacement + { + get; + private set; + } + + /// + /// Replaces the tokens in a buffer with the replacement string + /// + public override void UpdateBuffer(StringBuilder buffer) + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + buffer.Replace(Token, Replacement); + } + } + + /// + /// Storage classes for token to be deleted + /// + [DebuggerDisplay("{ID}: {StringToDelete} -> \"\"")] + private class DeleteToken : ActionToken + { + private readonly int _id; + + /// + /// Constructor + /// + /// Identifier of the action + /// Element to delete + public DeleteToken(int id, string toDelete) + { + _id = id; + StringToDelete = toDelete; + } + + /// + /// Identifier of the action. + /// + public override int ID + { + get { return _id; } + } + + /// + /// Token marking the end of the block to delete + /// + public string StringToDelete + { + get; + private set; + } + + /// + /// Deletes the token from the buffer + /// + public override void UpdateBuffer(StringBuilder buffer) + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + buffer.Replace(StringToDelete, string.Empty); + } + } + + /// + /// Storage classes for string to be deleted between tokens to be deleted + /// + [DebuggerDisplay("{ID}: {TokenStart}...{TokenEnd} -> {TokenReplacement}")] + private class ReplaceBetweenPairToken : ActionToken + { + private readonly int _id; + + /// + /// Constructor + /// + /// Identifier of the action + /// Identifier + /// Start token + /// End Token + /// Replacement string. + public ReplaceBetweenPairToken(int id, string tokenIdentifier, string blockStart, string blockEnd, string replacement) + { + _id = id; + TokenIdentifier = tokenIdentifier; + TokenStart = blockStart; + TokenEnd = blockEnd; + TokenReplacement = replacement; + } + + /// + /// Identifier of the action. + /// + public override int ID + { + get { return _id; } + } + + /// + /// Token marking the beginning of the block to delete + /// + public string TokenStart + { + get; + private set; + } + + /// + /// Token marking the end of the block to delete + /// + public string TokenEnd + { + get; + private set; + } + + /// + /// Token marking the end of the block to delete + /// + public string TokenReplacement + { + get; + private set; + } + + /// + /// Token Identifier + /// + public string TokenIdentifier + { + get; + private set; + } + + /// + /// Replaces the token from the buffer between the provided tokens + /// + public override void UpdateBuffer(StringBuilder buffer) + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + // PH: do we really need regexp here?... don't care for now, as this code looks like not used anywhere... + string regularExp = TokenStart + "[^" + TokenIdentifier + "]*" + TokenEnd; + string text = buffer.ToString(); + buffer.Clear(); + buffer.Append(Regex.Replace(text, regularExp, TokenReplacement)); + } + } + + #endregion + + private readonly List _tokens; + private int _globalID; + + /// + /// Default constructor. + /// + public TokenProcessor() + { + _tokens = new List(); + } + + private int GetNextID() + { + return Interlocked.Increment(ref _globalID); + } + + /// + /// Reset the list of replacer entries. + /// + public void Reset() + { + _tokens.Clear(); + } + + /// + /// Remove action with specified id. + /// + /// Unique identifier of an action to remove + public bool Remove(int id) + { + for(int i = 0; i < _tokens.Count; i++) + { + if (_tokens[i].ID == id) + { + _tokens.RemoveAt(i); + return true; + } + } + + return false; + } + + /// + /// Remove all actions with specified identifiers. + /// + /// Collection of unique identifiers of actions to remove + public void Remove(IEnumerable identifiers) + { + if (identifiers == null) + throw new ArgumentNullException("identifiers"); + + foreach(var id in identifiers) + { + Remove(id); + } + } + + /// + /// Add a replacement type entry. + /// + /// Token to replace + /// Replacement string + public int AddReplace(string token, string replacement) + { + var id = GetNextID(); + _tokens.Add(new ReplacePairToken(id, token, replacement)); + return id; + } + + /// + /// Add replacement between entry. + /// + /// Identifier + /// Start token + /// End token + /// Replacement for found entry + public int AddReplaceBetween(string tokenIdentifier, string tokenStart, string tokenEnd, string replacement) + { + var id = GetNextID(); + _tokens.Add(new ReplaceBetweenPairToken(id, tokenIdentifier, tokenStart, tokenEnd, replacement)); + return id; + } + + /// + /// Add a deletion entry. + /// + /// Token to delete + public int AddDelete(string tokenToDelete) + { + var id = GetNextID(); + _tokens.Add(new DeleteToken(id, tokenToDelete)); + return id; + } + + #region TokenProcessing + + /// + /// For all known tokens, replace them with correct values inside given string. + /// + public string Untoken(string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + var buffer = new StringBuilder(text); + Untoken(buffer); + return buffer.ToString(); + } + + /// + /// For all known tokens, replace them with correct values + /// + /// Full path of the source file + /// Full path of the destination file + public string UntokenFile(string source, string destination) + { + if (string.IsNullOrEmpty(source)) + throw new ArgumentNullException("source"); + if (string.IsNullOrEmpty(destination)) + throw new ArgumentNullException("destination"); + + // make sure that the destination folder exists: + string destinationFolder = Path.GetDirectoryName(destination); + if (string.IsNullOrEmpty(destinationFolder)) + throw new ArgumentOutOfRangeException("destination"); + + if (!Directory.Exists(destinationFolder)) + Directory.CreateDirectory(destinationFolder); + + // Open the file. Check to see if the File is binary or text. + // NOTE: This is not correct because GetBinaryType will return true + // only if the file is executable, not if it is a dll, a library or + // any other type of binary file. + + // PH: FIXME: No idea, why someone checks for exe/dll binary kind here (x86/x64/DOS/...)... + uint binaryType; + if (!NativeMethods.GetBinaryType(source, out binaryType)) + { + Encoding encoding; + StringBuilder buffer; + + // Create the reader to get the text. Note that we will default to ASCII as + // encoding if the file does not contains a different signature. + using (StreamReader reader = new StreamReader(source, Encoding.ASCII, true)) + { + // Get the content of the file. + buffer = new StringBuilder(reader.ReadToEnd()); + + // Detect the encoding of the source file. Note that we + // can get the encoding only after a read operation is + // performed on the file. + encoding = reader.CurrentEncoding; + } + + Untoken(buffer); + File.WriteAllText(destination, buffer.ToString(), encoding); + } + else + File.Copy(source, destination); + + return destination; + } + + private void Untoken(StringBuilder buffer) + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + foreach (var token in _tokens) + { + token.UpdateBuffer(buffer); + } + } + + #endregion + + #region Guid generators + + /// + /// Generates a string representation of a guid with the following format: + /// 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 + /// + /// Guid to be generated + /// The guid as string + public static string GuidToForm(Guid value) + { + var guidBytes = value.ToByteArray(); + var result = new StringBuilder(80); + + // first 4 bytes + uint number = 0; + int i; + for (i = 0; i < 4; ++i) + { + number <<= 8; + number += guidBytes[i]; + } + result.Append("0x").Append(number.ToString("X8", CultureInfo.InvariantCulture)); + + // 2 chunks of 2 bytes + for (int j = 0; j < 2; ++j) + { + number = guidBytes[i++]; + number <<= 8; + number += guidBytes[i++]; + result.Append(", 0x").Append(number.ToString("X4", CultureInfo.InvariantCulture)); + } + + // 8 chunks of 1 bytes + for (int j = 0; j < 8; ++j) + { + result.Append(", 0x").Append(guidBytes[i++].ToString("X2", CultureInfo.InvariantCulture)); + } + + return result.ToString(); + } + + #endregion + + #region Helper Methods + + /// + /// This function will accept a subset of the characters that can create an + /// identifier name: there are other unicode char that can be inside the name, but + /// this function will not allow. + /// + /// Character to validate + /// true if successful false otherwise + public static bool IsValidIdentifierChar(char c) + { + return char.IsLetterOrDigit(c) || c == '_'; + } + + /// + /// Verifies if the start character is valid + /// + /// Start character + /// true if successful false otherwise + public static bool IsValidIdentifierStartChar(char c) + { + return IsValidIdentifierChar(c) && !char.IsDigit(c); + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Components/UpdateManager.cs b/src_vs2012/NativeCore/Components/UpdateManager.cs new file mode 100644 index 00000000..79c58394 --- /dev/null +++ b/src_vs2012/NativeCore/Components/UpdateManager.cs @@ -0,0 +1,548 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Forms; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.Components +{ + public sealed class UpdateManager : IDisposable + { + #region Internal Classes + + /// + /// Description of actions scheduled to execution by UpdateManager. + /// + public sealed class ActionData : IDisposable + { + private readonly string _description; + private ApiLevelUpdateRunner _runner; + + #region Properties + + internal ActionData(UpdateManager manager, ApiLevelAction action, ApiLevelTarget target, string name, Version version) + { + if (manager == null) + throw new ArgumentNullException("manager"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (version == null) + throw new ArgumentNullException("version"); + + UpdateManager = manager; + Action = action; + Target = target; + Name = name; + Version = version; + + _description = Name.Contains(Version.ToString()) + ? string.Concat(GetActionName(Action), " ", Name) + : string.Concat(GetActionName(Action), " ", Name, " (", Version, ")"); + } + + ~ActionData() + { + Dispose(false); + } + + private static string GetActionName(ApiLevelAction action) + { + switch (action) + { + case ApiLevelAction.Install: + return "Install"; + case ApiLevelAction.Uninstall: + return "Remove"; + default: + throw new ArgumentOutOfRangeException("action"); + } + } + + private UpdateManager UpdateManager + { + get; + set; + } + + public bool IsRunning + { + get { return _runner != null; } + } + + public bool CanAbort + { + get; + private set; + } + + public ApiLevelAction Action + { + get; + private set; + } + + public ApiLevelTarget Target + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public Version Version + { + get; + private set; + } + + #endregion + + public override string ToString() + { + return _description; + } + + public void Abort() + { + bool aborted = false; + + lock (UpdateManager.SyncObject) + { + if (_runner != null && CanAbort) + { + aborted = _runner.Abort(); + } + } + + if (aborted) + { + UpdateManager.Finished(this); + } + } + + public void Start() + { + lock (UpdateManager.SyncObject) + { + // do nothing if already running + if (IsRunning) + return; + + _runner = new ApiLevelUpdateRunner(ConfigDefaults.NdkDirectory, Action, Target, Version); + _runner.Finished += OnFinished; + _runner.Log += OnLog; + _runner.ExecuteAsync(); + } + } + + private void OnLog(object sender, ApiLevelUpdateLogEventArgs e) + { + if (e != null) + { + CanAbort = e.CanAbort; + } + + UpdateManager.NotifyLog(e); + } + + private void OnFinished(object sender, ToolRunnerEventArgs e) + { + lock (UpdateManager.SyncObject) + { + _runner.Finished -= OnFinished; + _runner.Log -= OnLog; + _runner = null; + } + + UpdateManager.Finished(this); + } + + public void Delete() + { + // don't allow deletion, if already running: + if (IsRunning) + return; + + UpdateManager.Remove(this); + } + + #region IDisposable Implementation + + public void Dispose() + { + GC.SuppressFinalize(this); + Dispose(true); + } + + private void Dispose(bool dispose) + { + if (dispose) + { + if (_runner != null) + { + _runner.Dispose(); + _runner = null; + } + } + } + + #endregion + } + + #endregion + + private event EventHandler HiddenLog; + + public event EventHandler Log + { + add + { + HiddenLog += value; + + // send again the last log message... + if (value != null && _lastLog != null) + { + value(this, _lastLog); + } + } + remove { HiddenLog -= value; } + } + + private const int DelayInterval = 30000; // in milisec + + public event EventHandler Started; + public event EventHandler Completed; + + private readonly object _sync; + private readonly string _syncPath; + private ApiLevelUpdateLogEventArgs _lastLog; + private readonly List _actions; + private Timer _timer; + + /// + /// Init constructor. + /// + public UpdateManager(string folder) + { + _sync = new object(); + _syncPath = string.IsNullOrEmpty(folder) || !Directory.Exists(folder) ? null : Path.Combine(folder, "vsplugin.lock"); + _actions = new List(); + Actions = new ActionData[0]; + } + + ~UpdateManager() + { + Dispose(false); + } + + #region Properties + + /// + /// Gets the currently running action. + /// + public ActionData CurrentAction + { + get; + private set; + } + + /// + /// Thread-safe read-only collection of performed actions. + /// + public ActionData[] Actions + { + get; + private set; + } + + private StreamWriter SyncFile + { + get; + set; + } + + private object SyncObject + { + get { return _sync; } + } + + private string SyncFilePath + { + get { return _syncPath; } + } + + /// + /// Gets and indication, if anything is currently being processed or scheduled. + /// + public bool IsRunning + { + get { return CurrentAction != null || Actions.Length > 0; } + } + + #endregion + + /// + /// Requests installation or removal over specified item and version. + /// + public void Request(ApiLevelAction action, ApiLevelTarget target, string name, Version version) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (version == null) + throw new ArgumentNullException("version"); + + Schedule(new ActionData(this, action, target, name, version)); + } + + private void Schedule(ActionData action) + { + if (action == null) + throw new ArgumentNullException("action"); + + lock (_sync) + { + TraceLog.WriteLine("Scheduled: {0}", action); + + // add action to execution: + _actions.Add(action); + Actions = _actions.ToArray(); + } + + // and try to start it: + Start(); + } + + private void Remove(ActionData action) + { + if (action == null) + throw new ArgumentNullException("action"); + + lock (_sync) + { + TraceLog.WarnLine("Removed: {0}", action); + + // remove from execution: + action.Abort(); + if (_actions.Remove(action)) + { + Actions = _actions.ToArray(); + } + } + } + + /// + /// Checks, if there exists scheduled action for specified item. + /// + public bool IsProcessing(ApiLevelTarget target, Version version) + { + if (version == null) + return false; + + var current = CurrentAction; + if (current != null && current.Target == target && current.Version == version) + return true; + + foreach (var action in Actions) + { + if (action.Target == target && action.Version == version) + return true; + } + + return false; + } + + private void Start() + { + // already started... + if (SyncFile != null) + return; + if (CurrentAction != null) + return; + // no NdkDirectory folder found + if (string.IsNullOrEmpty(SyncFilePath)) + return; + + lock (_sync) + { + if (_actions.Count == 0) + return; + if (SyncFile != null) + return; + + try + { + SyncFile = new StreamWriter(File.Open(SyncFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None)); + SyncFile.Write(System.Diagnostics.Process.GetCurrentProcess().Id); + } + catch (Exception) + { + // ok, probably occupied by another instance of Visual Studio... retry in some time... + StartLater(); + return; + } + + CurrentAction = _actions[0]; + _actions.RemoveAt(0); + Actions = _actions.ToArray(); + + // go-go-go: + NotifyLog(new ApiLevelUpdateLogEventArgs("Starting...")); + CurrentAction.Start(); + } + + NotifyStarted(); + } + + private void StartLater() + { + if (_timer == null) + { + NotifyLog(new ApiLevelUpdateLogEventArgs("Another instance of Visual Studio is already performing an update. Waiting...", 0, true)); + TraceLog.WriteLine("Another instance of Visual Studio occupies the UpdateManager. Waiting for own time slot..."); + + _timer = new Timer(); + _timer.Interval = DelayInterval; // in milisec + _timer.Tick += TimerOnTick; + _timer.Start(); + } + } + + private void TimerOnTick(object sender, EventArgs e) + { + _timer.Dispose(); + _timer = null; + + Start(); + } + + private void Finished(ActionData action) + { + if (SyncFile == null) + return; + + bool completed = false; + + lock (_sync) + { + if (CurrentAction == action) + { + CurrentAction = null; + _lastLog = null; + + completed = true; + + SyncFile.Close(); + SyncFile = null; + } + } + + if (completed) + { + NotifyCompleted(action); + } + + // and start the next action from the queue: + Start(); + } + + private void UpdateLastLog(ApiLevelUpdateLogEventArgs e) + { + if (e == null) + return; + + // this method is a bit complex, as logger sends partial data, + // and here we want to maintain the 'full picture': + if (string.IsNullOrEmpty(e.Message) || e.Progress < 0) + { + _lastLog = new ApiLevelUpdateLogEventArgs(string.IsNullOrEmpty(e.Message) ? (_lastLog != null ? _lastLog.Message : null) + : e.Message, + e.Progress < 0 ? (_lastLog != null ? _lastLog.Progress : 0) + : e.Progress, e.CanAbort); + } + else + { + _lastLog = e; + } + } + + private void NotifyLog(ApiLevelUpdateLogEventArgs e) + { + var handler = HiddenLog; + UpdateLastLog(e); + + if (handler != null) + handler(this, e); + } + + private void NotifyStarted() + { + var handler = Started; + + if (handler != null) + handler(this, EventArgs.Empty); + } + + private void NotifyCompleted(ActionData action) + { + var handler = Completed; + + if (handler != null) + handler(this, new UpdateManagerCompletedEventArgs(action.Target)); + } + + #region IDisposable Implementation + + public void Dispose() + { + GC.SuppressFinalize(this); + Dispose(true); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + CancelAll(); + } + } + + #endregion + + public void CancelAll() + { + lock (_sync) + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + + lock (_sync) + { + if (SyncFile != null) + { + SyncFile.Dispose(); + SyncFile = null; + } + + ActionData[] copiedActions = Actions; + Actions = new ActionData[0]; + _actions.Clear(); + + // and abort all actions: + foreach (var action in copiedActions) + { + action.Abort(); + } + } + } + } + } +} diff --git a/src_vs2012/NativeCore/Components/UpdateManagerCompletedEventArgs.cs b/src_vs2012/NativeCore/Components/UpdateManagerCompletedEventArgs.cs new file mode 100644 index 00000000..f5904797 --- /dev/null +++ b/src_vs2012/NativeCore/Components/UpdateManagerCompletedEventArgs.cs @@ -0,0 +1,26 @@ +using System; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Components +{ + /// + /// Arguments passed along with Completed event of UpdateManager. + /// + public sealed class UpdateManagerCompletedEventArgs : EventArgs + { + internal UpdateManagerCompletedEventArgs(ApiLevelTarget target) + { + Target = target; + } + + #region Properties + + public ApiLevelTarget Target + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/ConfigDefaults.cs b/src_vs2012/NativeCore/ConfigDefaults.cs new file mode 100644 index 00000000..6d6b31d1 --- /dev/null +++ b/src_vs2012/NativeCore/ConfigDefaults.cs @@ -0,0 +1,454 @@ +using System; +using System.IO; +using Microsoft.Win32; + +namespace BlackBerry.NativeCore +{ +#if MAKE_CONFIG_DEFAULTS_PUBLIC + public +#endif + static class ConfigDefaults + { + /// + /// Global version of the plugin. It is set as a property of all projects. + /// + public const string VersionString = "3.0.0"; + + public static string ToolsDirectory + { + get; + private set; + } + + public static string NdkDirectory + { + get; + private set; + } + + public static string JavaHome + { + get; + private set; + } + + public static string SupplementaryInstallationConfigDirectory + { + get; + private set; + } + + public static readonly string DataDirectory; + public static readonly string InstallationConfigDirectory; + public static readonly string SupplementaryPlayBookInstallationConfigDirectory; + public static readonly string SshPublicKeyPath; + public static readonly string SshPrivateKeyPath; + public static readonly string GdbHostPath; + + private const string FieldQnxToolsPath = "QNXToolsPath"; + private const string FieldVsNdkPath = "VSNDKPath"; + private const string FieldVsNdkConfigPath = "VSNDKConfigPath"; + private const string FieldJavaHomePath = "JavaHomePath"; + + /// + /// Plugin-owned installation cache config directory. + /// + public static readonly string PluginInstallationConfigDirectory; + public static readonly string RegistryPath; + +#if DEBUG + /// + /// Full path to the DebugEngine library in build in debug, to help in easy debuggin whole stack. + /// It will not be used in release builds, as then the assumption is that the DE is next to the package. + /// + public const string DebugEngineDebugablePath = +# if PLATFORM_VS2010 + @"T:\vs-plugin\src_vs2010\DebugEngine\bin\Debug\BlackBerry.DebugEngine.dll"; +# elif PLATFORM_VS2012 + @"T:\vs-plugin\src_vs2012\DebugEngine\bin\Debug\BlackBerry.DebugEngine.dll"; +# elif PLATFORM_VS2013 + @"T:\vs-plugin\src_vs2013\DebugEngine\bin\Debug\BlackBerry.DebugEngine.dll"; +# else +# error Define path to debug version of the DebugEngine.dll to make the debugging working. +# endif +#endif + + /// + /// Gets the path to version of MSBuild used by Visual Studio. + /// + public static string MSBuildVCTargetsPath + { + get + { + var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); + + if (string.IsNullOrEmpty(programFilesX86)) + { + programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + } + +#if PLATFORM_VS2010 + return Path.Combine(programFilesX86, "MSBuild", "Microsoft.Cpp", "v4.0"); +#elif PLATFORM_VS2012 + return Path.Combine(programFilesX86, "MSBuild", "Microsoft.Cpp", "v4.0", "V110"); +#elif PLATFORM_VS2013 + return Path.Combine(programFilesX86, "MSBuild", "Microsoft.Cpp", "v4.0", "V120"); +#else +# error Define MSBuild path for current version of Visual Studio. +#endif + } + } + + /// + /// Get the path to Wiki pages. + /// + public static string GithubProjectWikiInstallation + { + get { return "https://github.com/phofman/vs-plugin/wiki/Installation"; } + } + + public static string GithubProjectSourceCode + { + get { return "https://github.com/phofman/vs-plugin"; } // "https://github.com/blackberry/VSPlugin" + } + + public static string GithubProjectIssues + { + get { return "https://github.com/phofman/vs-plugin/issues"; } // "https://github.com/blackberry/VSPlugin/issues" + } + + public static string GithubProjectAuthor + { + get { return "http://www.codetitans.pl"; } + } + + public static string GithubProjectAuthorTwitter + { + get { return "https://twitter.com/CodeTitans"; } + } + + public static string GithubProjectReleaseBBNDKforVS + { + get { return "https://github.com/phofman/vs-plugin/releases/tag/v3.0.1-bbndk"; } + } + + static ConfigDefaults() + { + RegistryPath = @"Software\BlackBerry\VSPlugin"; + + LoadDynamicSettings(); + + // the base data folder is different for each platform... + if (IsWindowsXP) + { + // HINT: in general LocalApplicationData should point to similar path... + // but if you use localized version of Windows XP, the folder is different ;) + DataDirectory = Path.Combine(Environment.ExpandEnvironmentVariables("%HomeDrive%%HomePath%"), "Local Settings", "Application Data", "Research In Motion"); + } + else + { + DataDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Research In Motion"); + } + + InstallationConfigDirectory = Path.Combine(DataDirectory, "BlackBerry Native SDK", "qconfig"); + SupplementaryPlayBookInstallationConfigDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "QNX Software Systems", "qconfig"); + PluginInstallationConfigDirectory = Path.Combine(DataDirectory, "VSPlugin", "qconfig"); + + SshPublicKeyPath = Path.Combine(DataDirectory, "bbt_id_rsa.pub"); + SshPrivateKeyPath = Path.Combine(DataDirectory, "bbt_id_rsa"); + +#if DEBUG + // PH: INFO: here is a small trick - since we develop this plugin in 'debug build', we also overwrite in that build + // the place, where the debug-engine is stored (check package attributes), to have it also debuggable; that's why + // the package and DE are not in the same folder and even GDBHost is not inside any of them + // so let it be hardcoded for that moment to have a fluent GDB attaching... +# if PLATFORM_VS2010 + GdbHostPath = @"T:\vs-plugin\src_vs2010\GDBHost\Debug\BlackBerry.GDBHost.exe"; +# elif PLATFORM_VS2012 + GdbHostPath = @"T:\vs-plugin\src_vs2012\Debug\BlackBerry.GDBHost.exe"; +# elif PLATFORM_VS2013 + GdbHostPath = @"T:\vs-plugin\src_vs2013\Debug\BlackBerry.GDBHost.exe"; +# else +# error Define path to debug version of the GDBHost.dll to make the debugging working. +# endif +#else + GdbHostPath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "BlackBerry.GDBHost.exe"); +#endif + } + + private static void LoadDynamicSettings() + { + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // read master values from registry: + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + string defaultToolsDirectory = null; + string defaultNdkDirectory = null; + string defaultNdkConfigDirectory = null; + string defaultJavaHomeDirectory = null; + + try + { + settings = registry.OpenSubKey(RegistryPath); + if (settings != null) + { + defaultToolsDirectory = (string) settings.GetValue(FieldQnxToolsPath); + defaultNdkDirectory = (string) settings.GetValue(FieldVsNdkPath); + defaultNdkConfigDirectory = (string) settings.GetValue(FieldVsNdkConfigPath); + defaultJavaHomeDirectory = (string) settings.GetValue(FieldJavaHomePath); + } + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + ToolsDirectory = !string.IsNullOrEmpty(defaultToolsDirectory) ? defaultToolsDirectory : GetEmbeddedToolsLocation(); + ToolsDirectory = ExistingPathOrNull(ToolsDirectory) ?? GetToolsDefaultLocation(); + + NdkDirectory = !string.IsNullOrEmpty(defaultNdkDirectory) ? defaultNdkDirectory : GetNdkDefaultLocation(); + JavaHome = FindJavaHomePath(defaultJavaHomeDirectory, NdkDirectory) ?? GetOracleJavaDefaultLocation(); + SupplementaryInstallationConfigDirectory = !string.IsNullOrEmpty(defaultNdkConfigDirectory) ? defaultNdkConfigDirectory : Path.Combine(Path.GetDirectoryName(NdkDirectory), "qconfig"); + + // make sure paths exist: + ToolsDirectory = ExistingPathOrNull(ToolsDirectory); + NdkDirectory = ExistingPathOrNull(NdkDirectory); + JavaHome = ExistingPathOrNull(JavaHome); + SupplementaryInstallationConfigDirectory = ExistingPathOrNull(SupplementaryInstallationConfigDirectory); + } + + #region Default Locations + + /// + /// Returns specified path, or null, when it doesn't exist. + /// + private static string ExistingPathOrNull(string path) + { + return Directory.Exists(path) ? path : null; + } + + private static string GetToolsDefaultLocation() + { + var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); + if (string.IsNullOrEmpty(programFilesX86)) + programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + + return Path.Combine(programFilesX86, "MSBuild", "BlackBerry", "QnxTools", "bin"); + } + + private static string GetEmbeddedToolsLocation() + { + var executingAssemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location; + var path = Path.Combine(Path.GetDirectoryName(executingAssemblyLocation), "QnxTools", "bin"); + + // HACK: somehow the location is written in capitals, what doesn't look good on UI + // so convert it to short path and back to long, to force to OS to provide the location + // using the true folder names + return NativeMethods.GetLongPathName(NativeMethods.GetShortPathName(path)); + } + + private static string GetNdkDefaultLocation() + { + return Path.Combine(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)), "bbndk_vs"); + } + + private static string GetJavaHomeDefaultLocation(string vsndkDirectory) + { + return Path.Combine(vsndkDirectory, "features", "com.qnx.tools.jre.win32_1.6.0.43", "jre"); + } + + private static string GetOracleJavaDefaultLocation() + { + var path = FindJavaHomePath(null, Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); + return !string.IsNullOrEmpty(path) ? path : FindJavaHomePath(null, Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); + } + + #endregion + + #region Java Localization + + private static string FindJavaHomePath(string expectedJavaHomeDirectory, string vsndkDirectory) + { + // first check, if specified expected path is really a home of Java: + if (!string.IsNullOrEmpty(expectedJavaHomeDirectory)) + { + if (IsValidJavaHomePath(expectedJavaHomeDirectory)) + { + return expectedJavaHomeDirectory; + } + + // nope, so maybe the parent directory has info about Java? + var parentOfExpected = Path.GetDirectoryName(expectedJavaHomeDirectory); + if (IsValidJavaHomePath(parentOfExpected)) + { + SetJavaHome(parentOfExpected); + return parentOfExpected; + } + } + + // is Java in any location of the BB-NDK for Visual Studio? + if (!string.IsNullOrEmpty(vsndkDirectory)) + { + // predefined one: + var predefinedPath = GetJavaHomeDefaultLocation(vsndkDirectory); + if (IsValidJavaHomePath(predefinedPath)) + { + SetJavaHome(null); // delete the value from registry, as we use the default one + return predefinedPath; + } + + // or anywhere: + var newPath = GetJavaHomeFromNdk(vsndkDirectory); + if (!string.IsNullOrEmpty(newPath)) + { + SetJavaHome(newPath); + return newPath; + } + } + + // no way to find, where the Java is: + return null; + } + + private static bool IsValidJavaHomePath(string path) + { + if (string.IsNullOrEmpty(path)) + return false; + + return File.Exists(Path.Combine(path, "bin", "java.exe")); + } + + /// + /// Enumerates all folders from specified one looking for Java binaries. + /// + private static string GetJavaHomeFromNdk(string vsndkDirectory) + { + if (string.IsNullOrEmpty(vsndkDirectory) || !Directory.Exists(vsndkDirectory)) + return null; + + // or if not, enumerate all folders (2-levels only) and finding one with 'java.exe' inside: + try + { + foreach (var directory in Directory.EnumerateDirectories(vsndkDirectory)) + { + foreach (var feature in Directory.EnumerateDirectories(directory)) + { + var expectedPath = Path.Combine(feature, "jre"); + if (File.Exists(Path.Combine(expectedPath, "bin", "java.exe"))) + { + return expectedPath; + } + } + } + + return null; + } + catch + { + return null; + } + } + + private static void SetJavaHome(string path) + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(RegistryPath); + SetOrDelete(settings, FieldJavaHomePath, IsValidJavaHomePath(path) ? path : null, GetJavaHomeDefaultLocation(NdkDirectory), null); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + #endregion + + public static void Apply(string vsndkDirectory, string toolsDirectory, string javaHomeDirectory) + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(RegistryPath); + SetOrDelete(settings, FieldVsNdkPath, vsndkDirectory, GetNdkDefaultLocation(), null); + SetOrDelete(settings, FieldQnxToolsPath, toolsDirectory, GetEmbeddedToolsLocation(), GetToolsDefaultLocation()); + SetOrDelete(settings, FieldJavaHomePath, javaHomeDirectory, GetJavaHomeDefaultLocation(vsndkDirectory), null); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + + LoadDynamicSettings(); + } + + private static void SetOrDelete(RegistryKey context, string fieldName, string value, string defaultValue1, string defaultValue2) + { + if (string.IsNullOrEmpty(fieldName)) + throw new ArgumentNullException("fieldName"); + + if (context != null) + { + if (string.IsNullOrEmpty(value) + || string.Compare(value, defaultValue1, StringComparison.OrdinalIgnoreCase) == 0 + || string.Compare(value, defaultValue2, StringComparison.OrdinalIgnoreCase) == 0) + { + context.DeleteValue(fieldName, false); + } + else + { + context.SetValue(fieldName, value, RegistryValueKind.String); + } + } + } + + /// + /// Gets the full path to specified file within BlackBerry developer's configuration area. + /// + public static string DataFileName(string fileName) + { + if (string.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + + return Path.Combine(DataDirectory, fileName); + } + + /// + /// Gets an indication, if currently running on Windows XP. + /// + public static bool IsWindowsXP + { + get + { + var os = Environment.OSVersion; + return os.Platform == PlatformID.Win32NT && os.Version.Major == 5 && os.Version.Minor == 1; + } + } + + /// + /// Gets an indication, if currently running on Windows XP, Vista, 7, 8 or newer system. + /// + public static bool IsWindowsXPorNewer + { + get + { + var os = Environment.OSVersion; + return os.Platform == PlatformID.Win32NT && (os.Version.Major > 5 || (os.Version.Major == 5 && os.Version.Minor == 1)); + } + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/GdbProcessor.cs b/src_vs2012/NativeCore/Debugger/GdbProcessor.cs new file mode 100644 index 00000000..ddfb2aa0 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/GdbProcessor.cs @@ -0,0 +1,330 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Threading; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Class designed to communited directly with GDB. It is required to startup GDB in MI mode. + /// More info here: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI.html + /// + public sealed class GdbProcessor : IDisposable + { + public const string Prompt = "(gdb) "; + internal const int ShortInfinite = 30 * 1000; // 30 sec + + private readonly IGdbSender _sender; + private readonly object _sync; + private AutoResetEvent _eventMessageAvailable; + + private readonly List _messageCache; + private readonly Queue _responses; + + private Request _currentRequest; + private readonly Queue _requests; + + public event EventHandler Received; + + /// + /// Init constructor. + /// + public GdbProcessor(IGdbSender sender) + { + if (sender == null) + throw new ArgumentNullException("sender"); + + _sender = sender; + _sync = new object(); + _eventMessageAvailable = new AutoResetEvent(false); + + _messageCache = new List(); + _responses = new Queue(); + _requests = new Queue(); + IsClosed = false; + } + + ~GdbProcessor() + { + Dispose(false); + } + + #region Properties + + public IEventDispatcher Dispatcher + { + get; + set; + } + + public bool IsClosed + { + get; + private set; + } + + #endregion + + #region IDisposable Implemenation + + public void Dispose() + { + GC.SuppressFinalize(this); + Dispose(true); + } + + private void Dispose(bool dispose) + { + IsClosed = true; + + if (dispose) + { + Received = null; + + if (_eventMessageAvailable != null) + { + _eventMessageAvailable.Dispose(); + _eventMessageAvailable = null; + } + } + } + + #endregion + + /// + /// Stores each line of text received from GDB for further processing and converts them into a complete message. + /// Single message is a multiline notification, that usually is response to request issued earlier or asynchronous notification. + /// + /// Returns 'true', when whole new message has been read and there is something to process. + public bool Receive(string text) + { + // ignore empty lines: + if (string.IsNullOrEmpty(text)) + return false; + + Request currentRequest; + Response response = null; + bool clearCurrentRequest = false; + bool retryRequest = false; + + lock (_sync) + { + currentRequest = _currentRequest; + var currentID = currentRequest != null ? currentRequest.ID.ToString(CultureInfo.InvariantCulture) : null; + var currentIDLength = string.IsNullOrEmpty(currentID) ? 0 : currentID.Length; + + // is it an end of the message? + if (text == Prompt) + { + // then convert to message object and pass for further processing: + if (_messageCache.Count > 0) + { + response = Response.Parse(_messageCache.ToArray()); + _messageCache.Clear(); + } + } + else + { + // check, if exit response, in that case, don't wait for never coming prompt: + if (string.CompareOrdinal(text, currentIDLength, "^exit", 0, text.Length - currentIDLength) == 0) + { + response = Response.Parse(new[] { text }); + if (response != null) + { + IsClosed = true; + } + } + + if (response == null) + { + _messageCache.Add(text); + } + } + } + + // if completed the message wake up one thread waiting for ANY response: + if (response != null) + { + // inform a request, that a matching response arrived: + if (currentRequest != null && currentRequest.HasIdenticalID(response.ID)) + { + clearCurrentRequest = currentRequest.Complete(response, out retryRequest); + } + + // if response was not handled by listeners of Received event + // than add it to the queue for to be processed by waiting thread: + if (!NotifyResponseReceived(clearCurrentRequest ? currentRequest : null, response)) + { + lock (_sync) + { + _responses.Enqueue(response); + _eventMessageAvailable.Set(); + } + } + } + + // send the same request, in case it expects more data + // or the next stored one: + if (retryRequest) + { + if (!Send(currentRequest)) + return false; + } + else + { + if (clearCurrentRequest) + { + _currentRequest = null; + if (!SendNextRequest()) + return false; + } + } + + return response != null; + } + + private bool NotifyResponseReceived(Request request, Response response) + { + var receivedHandler = Received; + var dispatcher = Dispatcher; + ResponseReceivedEventArgs e = null; + + if (dispatcher != null) + { + e = new ResponseReceivedEventArgs(request, response, false); + dispatcher.Invoke(receivedHandler, this, e); + } + else + { + if (receivedHandler != null) + { + e = new ResponseReceivedEventArgs(request, response, false); + receivedHandler(this, e); + } + } + + return e != null && e.Handled; + } + + /// + /// Waits until a valid message was not received. + /// + /// Returns 'true', if the signal was received and data is valid, 'false' in case of timeout. + public bool Wait(out Response response) + { + return Wait(ShortInfinite, out response); + } + + /// + /// Waits until a valid message was not received. + /// + /// Returns 'true', if the signal was received and data is valid, 'false' in case of timeout. + public bool Wait(int millisecondsTimeout, out Response response) + { + bool hasSignal = _eventMessageAvailable.WaitOne(millisecondsTimeout); + + if (hasSignal) + { + lock (_sync) + { + response = _responses.Dequeue(); + } + } + else + { + response = null; + } + + return hasSignal && response != null; + } + + /// + /// Reads next response from the buffer. + /// If there is nothing received until last call, null value is returned. + /// + public Response Read() + { + Response response; + + lock (_sync) + { + response = _responses.Count > 0 ? _responses.Dequeue() : null; + } + + if (response != null) + _eventMessageAvailable.Reset(); + + return response; + } + + /// + /// Removes all stored responses. + /// + public void ClearResponses() + { + lock (_sync) + { + _responses.Clear(); + } + } + + /// + /// This method sends a desired request to the GDB. + /// + public bool Send(Request request) + { + if (request == null) + throw new ArgumentNullException("request"); + if (IsClosed) + return false; + + bool canSend = false; + + lock (_sync) + { + if (_currentRequest != null && _currentRequest != request) + { + _requests.Enqueue(request); + } + else + { + _currentRequest = request; + canSend = true; + } + } + + if (canSend) + { + // serialize the request into string and send it to GDB: + return request.Execute(_sender); + } + + return true; + } + + /// + /// Gets next request from the queue and sends it to the GDB. + /// + private bool SendNextRequest() + { + Request next = null; + + lock (_sync) + { + if (_currentRequest == null && _requests.Count > 0) + { + next = _currentRequest = _requests.Dequeue(); + } + } + + if (next != null) + { + // serialize the request into string and send it to GDB: + return next.Execute(_sender); + } + + return true; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/GdbWrapper.cs b/src_vs2012/NativeCore/Debugger/GdbWrapper.cs new file mode 100644 index 00000000..5f450c5c --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/GdbWrapper.cs @@ -0,0 +1,454 @@ +using System; +using System.Collections.Generic; +using System.IO; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Debugger.Requests; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Wrapper class for calls, that used to be exposed by C++ GDBWrapper project. + /// + public static class GdbWrapper + { + #region Internal Classes + + /// + /// Class to store context for specified requests, that expect async responses. + /// + sealed class AsyncContext + { + public AsyncContext(Request request, Instruction instruction) + { + if (request == null) + throw new ArgumentNullException("request"); + if (instruction == null) + throw new ArgumentNullException("instruction"); + + Request = request; + Instruction = instruction; + } + + #region Properties + + public Request Request + { + get; + private set; + } + + public Instruction Instruction + { + get; + private set; + } + + #endregion + + public override string ToString() + { + return Request.ToString(); + } + } + + #endregion + + private static GdbRunner _gdbRunner; + private static readonly InstructionCollection Instructions = InstructionCollection.Load(); + private static readonly Dictionary Context = new Dictionary(); + + private const uint LastSyncInstructionID = 50; + + /// + /// Event send each time a response is received by GDB processor created during attaching to process. + /// + public static event EventHandler Received; + + /// + /// Event send, when GDB unexpectedly crashed or was killed by developer. + /// + public static event EventHandler UnexpectedlyClosed; + + /// + /// Attaches to the process with given PID or binary name on a target device. + /// + /// PID of the process or name of the binary. + /// Local path to the executable being debugged. It is required by GDB to load debug symbols. + /// Info about existing process running on the device or null, if not known. + /// Location of the NDK used to compile the binary. + /// Target device to connect to. + /// Path to the runtime with matching device libraries. Used to decipher OS callstacks. + /// Numerical PID of the process the GDB attached to. + /// Returns 'true', when attaching succeeded, otherwise 'false'. It will automatically close GDB, if anything failed. + public static bool AttachToProcess(string pidOrBinaryName, string localBinaryPath, ProcessInfo existingProcessOrNull, NdkDefinition ndk, DeviceDefinition device, RuntimeDefinition runtime, out uint pidNumber) + { + if (ndk == null) + throw new ArgumentNullException("device"); + if (device == null) + throw new ArgumentNullException("device"); + + pidNumber = 0; + Targets.Connect(device, ConfigDefaults.SshPublicKeyPath, ConfigDefaults.SshPrivateKeyPath, null); + + // establish GDB connection: + var gdbInfo = new GdbInfo(ndk, device, runtime, null); + if (_gdbRunner != null) + { + _gdbRunner.Dispose(); + } + + // PH: INFO: + // Here create a dedicated runner to let us communicate with GDB. We use a 'hosted' version + // as communication is done via BlackBerry.GDBHost.exe (not directly as it would be done using GdbRunner). + // The reason is simple - this is the ONLY way to send BreakRequest (aka Ctrl+C) to the GDB, while + // it's running program. This allows to pause current binary execution at any time and inject other commands. + // Second trick we do here is using a dedicated 'event dispatcher'. This async dispatcher simply instantiates + // single background-thread and all event notifications from GDB are sent from that thread with order kept. + // It is required since the current DE architecture assumes that blocking calls of SendCommand() can be + // send immediately when processing asynchronous GDB notification. That, without an extra thread, + // would lead to a total blockage of whole communication, as we would block in the reading thread + // and wait for data it was supposed to produce. + _gdbRunner = new GdbHostRunner(ConfigDefaults.GdbHostPath, gdbInfo); + _gdbRunner.Finished += GdbRunnerUnexpectedlyFinished; + _gdbRunner.Processor.Dispatcher = EventDispatcher.NewAsync("Default GDB events dispatcher"); + _gdbRunner.Processor.Received += GdbRunnerResponseReceived; + _gdbRunner.ExecuteAsync(); + + // setup environment: + var parsed = _gdbRunner.Send(RequestsFactory.SetPendingBreakpoints(true), Instructions[8]); + if (parsed == string.Empty || parsed[0] == '!') + { + _gdbRunner.Send(RequestsFactory.Exit()); + return false; + } + + // select device: + // and select current target device: + parsed = _gdbRunner.Send(RequestsFactory.SetTargetDevice(_gdbRunner.Device), Instructions[3]); + if (parsed == string.Empty || parsed[0] == '!') + { + _gdbRunner.Send(RequestsFactory.Exit()); + return false; + } + + // load PID of the process to attach: + if (!uint.TryParse(pidOrBinaryName, out pidNumber)) + { + /////////////////////////////////////////////////////// + // "the old way" - which seems not to work on PlayBook: + /* + var listRequest = RequestsFactory.ListProcesses(); + _gdbRunner.Send(listRequest); + + // wait for response: + listRequest.Wait(); + var existingProcess = listRequest.Find(pidOrBinaryName); + */ + /////////////////////////////////////////////////////// + + // this should succeed as we already used GDB successfully, so secure communication is working... + var qClient = Targets.Get(device); + if (qClient == null || qClient.FileService == null) + { + throw new InvalidOperationException("Missing the client connected to target - this should never happen"); + } + + var existingProcess = qClient.SysInfoService.FindProcess(pidOrBinaryName); + if (existingProcess != null) + { + // doesn't run + pidNumber = existingProcess.ID; + + // start monitoring for console logs: + Targets.Trace(device, existingProcess, true); + } + else + { + _gdbRunner.Send(RequestsFactory.Exit()); + return false; + } + } + else + { + if (existingProcessOrNull != null) + { + // start monitoring for console logs: + Targets.Trace(device, existingProcessOrNull, true); + } + } + + // symbols paths: + parsed = _gdbRunner.Send(RequestsFactory.SetLibrarySearchPath(_gdbRunner), Instructions[7]); + if (parsed == string.Empty || parsed[0] == '!') + { + _gdbRunner.Send(RequestsFactory.Exit()); + return false; + } + + if (!string.IsNullOrEmpty(localBinaryPath) && File.Exists(localBinaryPath)) + { + parsed = _gdbRunner.Send(RequestsFactory.SetExecutable(localBinaryPath, true), Instructions[8]); + + // PH: TODO: HINT: potentially we could ignore the error here + if (parsed == string.Empty || parsed[0] == '!') + { + _gdbRunner.Send(RequestsFactory.Exit()); + return false; + } + } + + // and attach: + parsed = _gdbRunner.Send(RequestsFactory.AttachTargetProcess(pidNumber), Instructions[6]); + if (parsed == string.Empty || parsed[0] == '!') + { + _gdbRunner.Send(RequestsFactory.Exit()); + return false; + } + + return true; + } + + private static void GdbRunnerResponseReceived(object sender, ResponseReceivedEventArgs e) + { + // process the data only of asynchronous responses: + if (IsAsync(e.Response)) + { + Instruction instruction; + string parsedResponse; + + // process notifications: + foreach (var notification in e.Response.Notifications) + { + var name = GetNotificationName(notification); + + if (!string.IsNullOrEmpty(name)) + { + string param; + instruction = Instructions.Find(name, out param); + if (instruction != null) + { + parsedResponse = instruction.Parse(notification + "\r\n"); + NotifyParsedResponse(e, parsedResponse); + } + } + } + + // process result records and status changes: + var context = GetContext(e.Response); + instruction = context != null ? context.Instruction : Instructions[0]; + + parsedResponse = instruction.Parse(e.Response); + NotifyParsedResponse(e, parsedResponse); + } + + // schedule all responses to be removed from the source queue: + e.Handled = true; + } + + private static string GetNotificationName(string notification) + { + if (string.IsNullOrEmpty(notification)) + return null; + + int endAt = notification.IndexOf(','); + return endAt < 0 ? notification : notification.Substring(0, endAt); + } + + private static void NotifyParsedResponse(ResponseReceivedEventArgs e, string parsedResponse) + { + if (!string.IsNullOrEmpty(parsedResponse) && parsedResponse != ";") + { + // notify about the response: + var handler = Received; + if (handler != null) + { + handler(null, new ResponseParsedEventArgs(e, parsedResponse)); + } + } + } + + private static void GdbRunnerUnexpectedlyFinished(object sender, ToolRunnerEventArgs e) + { + _gdbRunner = null; + + // notify, that it unexpectedly closed: + var handler = UnexpectedlyClosed; + if (handler != null) + { + handler(null, EventArgs.Empty); + } + } + + /// + /// Closes communication channel with GDB. + /// + public static void Exit() + { + if (_gdbRunner != null) + { + // stop all tracing for specified device: + Targets.TraceStop(_gdbRunner.GDB.Device); + + _gdbRunner.Finished -= GdbRunnerUnexpectedlyFinished; + _gdbRunner.Dispose(); + _gdbRunner = null; + } + } + + /// + /// Gets an indication, if there is open GDB connection to target device. + /// + public static bool IsRunning + { + get { return _gdbRunner != null && _gdbRunner.IsProcessing; } + } + + /// + /// Gets an indication, if specified response is asynchronous. + /// + private static bool IsAsync(Response response) + { + if (response == null) + return false; + + return response.ID == 0 || response.ID >= LastSyncInstructionID; + } + + /// + /// Lists all running processes from specified target device. + /// + public static ProcessListRequest ListProcesses(NdkDefinition ndk, DeviceDefinition device) + { + if (ndk == null) + throw new ArgumentNullException("device"); + if (device == null) + throw new ArgumentNullException("device"); + + Targets.Connect(device, ConfigDefaults.SshPublicKeyPath, ConfigDefaults.SshPrivateKeyPath, null); + + // start own GDB, if any specified: + var info = new GdbInfo(ndk, device, null, null); + var gdb = new GdbRunner(info); + gdb.ExecuteAsync(); + + var selectTarget = RequestsFactory.SetTargetDevice(device); + gdb.Send(selectTarget); + if (!selectTarget.Wait() || selectTarget.Response == null || selectTarget.Response.Name == "error") + { + // ask the GDB to exit, if created internally: + gdb.Send(RequestsFactory.Exit()); + return null; + } + + var listRequest = RequestsFactory.ListProcesses(); + gdb.Send(listRequest); + + // wait for response: + bool hasResponse = listRequest.Wait(); + + // ask GDB to exit, if created internally: + gdb.Send(RequestsFactory.Exit()); + return hasResponse ? listRequest : null; + } + + /// + /// Sends a synchronous GDB command and waiting for the respective GDB response. This method is called by the Debug Engine whenever it needs a GDB response for a given GDB command. + /// + /// Command to be sent to GDB. + /// Instruction ID. + public static string SendCommand(string command, uint instructionID) + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + if (instructionID >= LastSyncInstructionID) + throw new ArgumentOutOfRangeException("instructionID"); + if (_gdbRunner == null) + throw new InvalidOperationException("Unable to send the command"); + + string parsingParam; + var instruction = Instructions.Find(command, out parsingParam); + if (instruction == null) + throw new ArgumentOutOfRangeException("command", "Specified command has no matching parsing instruction"); + + var request = new Request(instructionID, command); + + _gdbRunner.Send(request); + var hasResponse = request.Wait(); + + // check if data was received: + if (!hasResponse || request.Response == null || request.Response.RawData == null) + { + return "TIMEOUT!"; + } + + // parse response: + var parsedResponse = instruction.Parse(request.Response); + return parsedResponse; + } + + /// + /// Sends an asynchronous GDB command. This method is called by the Debug Engine whenever it needs to send a GDB command without having to wait for the respective GDB response. + /// + /// Command to be sent to GDB. + public static void PostCommand(string command) + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + if (_gdbRunner == null) + throw new InvalidOperationException("Unable to send the command"); + + string parsingParam; + var instruction = Instructions.Find(command, out parsingParam); + if (instruction == null) + throw new ArgumentOutOfRangeException("command", "Specified command has no matching parsing instruction"); + + Request request; + + // schedule execution of a request, but don't wait for a response: + if (string.Compare("-exec-interrupt", command, StringComparison.Ordinal) == 0) + { + request = RequestsFactory.Break(); + } + else + { + request = new Request(command); + } + + SetContext(request, instruction); + _gdbRunner.Send(request); + } + + private static void SetContext(Request request, Instruction instruction) + { + if (request == null) + throw new ArgumentNullException("request"); + if (instruction == null) + throw new ArgumentNullException("instruction"); + + lock (Context) + { + Context[request.ID] = new AsyncContext(request, instruction); + } + } + + private static AsyncContext GetContext(uint id) + { + AsyncContext result; + + lock (Context) + { + Context.TryGetValue(id, out result); + } + + return result; + } + + private static AsyncContext GetContext(Response response) + { + return response != null ? GetContext(response.ID) : null; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/IGdbSender.cs b/src_vs2012/NativeCore/Debugger/IGdbSender.cs new file mode 100644 index 00000000..a0d2d4d6 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/IGdbSender.cs @@ -0,0 +1,8 @@ +namespace BlackBerry.NativeCore.Debugger +{ + public interface IGdbSender + { + void Break(); + bool Send(string command); + } +} diff --git a/src_vs2012/NativeCore/Debugger/Instruction.cs b/src_vs2012/NativeCore/Debugger/Instruction.cs new file mode 100644 index 00000000..240e6162 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Instruction.cs @@ -0,0 +1,669 @@ +using System; +using System.Diagnostics; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Class representing single GDB-response parsing instruction. + /// + [DebuggerDisplay("{ID}: {Command}")] + public sealed class Instruction + { + public Instruction(int id, string command, bool expectsParameter, string parsing) + { + ID = id; + Command = command; + ExpectsParameter = expectsParameter; + Parsing = parsing; + } + + #region Properties + + /// + /// Gets the ID of the instruction. + /// + public int ID + { + get; + private set; + } + + /// + /// Gets the command text expected to be send from GDB. + /// + public string Command + { + get; + private set; + } + + public bool ExpectsParameter + { + get; + private set; + } + + /// + /// Gets the response parsing instruction. + /// + public string Parsing + { + get; + private set; + } + + #endregion + + /// + /// Checks if given parsing instruction is about the same GDB command. + /// + /// Command to check + /// Returns 'true', when given instruction is about the same GDB command. + public bool HasCommand(string command) + { + if (string.IsNullOrEmpty(Command) && string.IsNullOrEmpty(command)) + return true; + if (string.IsNullOrEmpty(Command) != string.IsNullOrEmpty(command)) + return false; + + return string.CompareOrdinal(Command, command) == 0; + } + + #region Instantiation + + /// + /// Loads data using following format: + /// {$}gdb-command:->:parsing-instruction; + /// It must have the $ sign in front of the GDB command when it is needed to store the command parameters to be used later. + /// This usually happens whenever the GDB response for a given command does not contains enough information, like + /// only "^done" for example, when the parser needs something else. + /// The ":->:" separates the GDB command from the parsing Instruction. + /// + public static Instruction Load(int id, string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + int separatorIndex = text.IndexOf(":->:", StringComparison.Ordinal); + if (separatorIndex < 0) + return new Instruction(id, string.Empty, false, text); + + if (text[0] != '$') + return new Instruction(id, text.Substring(0, separatorIndex), false, text.Substring(separatorIndex + 4)); + return new Instruction(id, text.Substring(1, separatorIndex - 1), true, text.Substring(separatorIndex + 4)); + } + + #endregion + + #region Parsing - PH: just copied from GDBParserAPI.cpp, gdb-connect.cpp and converted to C# - it's not MY CODE! + + /// + /// Function used to call the parser that will process a GDB response according to the stored parsing instruction, returning this parsed response. + /// + /// Received GDB response (must have raw response from GDB set) + public string Parse(Response response) + { + if (response == null) + throw new ArgumentNullException("response"); + if (response.RawData == null || response.RawData.Length == 0) + throw new ArgumentOutOfRangeException("response"); + + if (response.StatusOutputs.Length == 0) + return string.Empty; + + var parsedResponse = Parse(string.Join("\r\n", response.StatusOutputs)); + + // This string means that both GDB and the parser worked well and returned an empty string. + if (string.Compare(parsedResponse, "$#@EMPTY@#$", StringComparison.Ordinal) == 0) + return string.Empty; + + return parsedResponse; + } + + /// + /// Function used to call the parser that will process a GDB response according to the stored parsing instruction, returning this parsed response. + /// + /// Unprocessed GDB response + public string Parse(string response) + { + return Parse(response, Parsing, 0, false, new string[10], "#"); + } + + /// + /// Responsible for parsing each GDB response. Depending on the parsing instruction, the parser can get the first occurrence + /// from GDB response or get all of them that satisfies this parsing instruction. + /// + public string Parse(string response, int respBegin, bool repeat, string[] variables, string separator) + { + return Parse(response, Parsing, respBegin, repeat, variables, separator); + } + + /// + /// Responsible for parsing each GDB response. Depending on the parsing instruction, the parser can get the first occurrence + /// from GDB response or get all of them that satisfies this parsing instruction. + /// + /// GDB response + /// Current character to be read in GDB response + /// Instruction used to parse the respective GDB response. + /// If the parsing instruction specifies that it has to get all occurrences from a GDB response, this value must be true. + /// A variable stores a string parsed from GDB response and can be used as many times as needed to create the parsed response. + /// If the parsing instruction allows the parser to get all occurrences from GDB response, this separator will + /// be used at the end of each occurrence. The default one is '#' but it can be specified in the parsing instruction. + /// Returns the parsed GDB response. + private static string Parse(string response, string parsingInstruction, int respBegin, bool repeat, string[] variables, string separator) + { + if (variables == null) + throw new ArgumentNullException("variables"); + if (variables.Length < 10) + throw new ArgumentOutOfRangeException("variables"); + if (string.IsNullOrEmpty(response)) + throw new ArgumentNullException("response"); + + string result = ""; // This variable will be the parsed GDB response. + int parsePos = 0; // Current character to be read in parsing instruction. + int home = respBegin; // Save the current position in GDB response. + int respEnd; + int limit = response.Length; + bool found = false; + string originalParsingInstruction = parsingInstruction; + + bool removeSelection = false; + int removeFromHere = -2; // -2 - not set; -1 - indicates that it will be set in the first '?' instruction; >=0 - already set. + + if (separator == "$EOL$") + separator = "\r\n"; + + while (parsePos < parsingInstruction.Length || repeat) + { + if (repeat && parsePos >= parsingInstruction.Length) // repeat instructions till the end of the response + { + if (found) + { + if (result != "") + result += separator; + parsePos = 0; + parsingInstruction = originalParsingInstruction; + limit = response.Length; + found = false; + } + else + repeat = false; + continue; + } + + if (parsingInstruction[parsePos] == '(') // repeat instructions till the end of the response + { + int end = parsePos; + string repeatInstruction; + + end = FindClosing(parsingInstruction, '(', ')', parsePos); + + repeatInstruction = parsingInstruction.Substring(parsePos + 1, end - (parsePos + 1)); + + end++; + if (parsingInstruction[end] == ':') + { + parsePos = end + 1; + end = GetNextChar(parsingInstruction, ';', parsePos); + separator = parsingInstruction.Substring(parsePos, end - parsePos); + int aux = separator.IndexOf("\\;"); + if (aux != -1) + { + separator = separator.Remove(aux, 1); + } + } + parsePos = end + 1; + + var nextChunk = Parse(response, repeatInstruction, respBegin, true, variables, separator); + if (string.IsNullOrEmpty(nextChunk)) + { + found = false; + } + else + { + result += nextChunk; + } + continue; + } + + if (parsingInstruction[parsePos] == '?') // search and set the beginning of the searched string. + { + int times = 1; + bool forward = true; + int end; + int aux; + string txt; + + parsePos++; + if (parsingInstruction[parsePos] == '%') // consider this position to extract and use the data and them remove this one from the GDB response string + { + removeFromHere = -1; + parsePos++; + } + + if (parsingInstruction[parsePos] == '<') // means to search backwards. + { + forward = false; + parsePos++; + } + + if (parsingInstruction[parsePos] != '?') // the number of times to search for a given string. + { + end = GetNextChar(parsingInstruction, '?', parsePos); + times = int.Parse(parsingInstruction.Substring(parsePos, end - parsePos)); + parsePos = end; + } + parsePos++; + + end = GetNextChar(parsingInstruction, ';', parsePos); + txt = SubstituteVariables(parsingInstruction.Substring(parsePos, end - parsePos), variables); + + aux = txt.IndexOf('\\'); + while (aux != -1) + { + // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed + txt = txt.Substring(0, aux) + txt.Substring(aux + 1, txt.Length - (aux + 1)); + aux = txt.IndexOf('\\', aux + 1); + }; + + int previousRespBegin = respBegin; + respBegin = SearchResponse(response, txt, respBegin, times, forward, '?'); + + // check if it was defined a set of instructions to be executed if the search is NOT valid, i.e., there is a '{' after the ';'. + // If the search is not valid, go to the '}' and keep going. If there is no '{}' and the search is not valid, just end evaluating + // these instructions. Normally, there is '{}' to allow handling gdb errors. + if (parsingInstruction[end + 1] == '{') + { + parsePos = end + 1; + + end = FindClosing(parsingInstruction, '{', '}', parsePos); + if ((respBegin != -1) && (respBegin <= limit)) + { + found = true; + // the following instructions to be evaluated are between '{' and '}'. + if (end + 1 < parsingInstruction.Length && parsingInstruction[end + 1] != '{') + { + parsingInstruction = parsingInstruction.Substring(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.Substring(end + 2, parsingInstruction.Length - (end + 2)); + } + else + { + // if there is '{' after a '}', it means that there is an 'else' sentence. + int else_end; + else_end = FindClosing(parsingInstruction, '{', '}', end + 1); + parsingInstruction = parsingInstruction.Substring(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.Substring(else_end + 2, parsingInstruction.Length - (else_end + 2)); + } + + parsePos = 0; + if (removeFromHere == -1) + { + removeFromHere = respBegin - txt.Length; + } + } + else + { + respBegin = previousRespBegin; + removeFromHere = -2; + if (end + 1 < parsingInstruction.Length && parsingInstruction[end + 1] != '{') + { + parsePos = end + 2; // move it to the next instruction, after the "};" + } + else + { + parsePos = end + 1; + end = FindClosing(parsingInstruction, '{', '}', parsePos); + parsingInstruction = parsingInstruction.Substring(parsePos + 1, end - (parsePos + 1)) + parsingInstruction.Substring(end + 2, parsingInstruction.Length - (end + 2)); + parsePos = 0; + } + } + } + else + { + if ((respBegin == -1) || (respBegin > limit)) + { + if (respBegin > limit) + respBegin = previousRespBegin; + + parsePos = parsingInstruction.Length; + removeFromHere = -2; + removeSelection = false; + } + else + { + found = true; + parsePos = end + 1; + if (removeFromHere == -1) + { + removeFromHere = respBegin - txt.Length; + } + } + } + + continue; + } + + if (parsingInstruction[parsePos] == '@') // till here: search and set the end of the searched string. Return the string between the last ? and this "till here" position + { + int times = 1; + int end; + string txt; + int aux; + + parsePos++; + + if (parsingInstruction[parsePos] != '@') // get the number of times to search for a given string. + { + end = GetNextChar(parsingInstruction, '@', parsePos); + times = int.Parse(parsingInstruction.Substring(parsePos, end - parsePos)); + parsePos = end; + } + parsePos++; + + end = GetNextChar(parsingInstruction, ';', parsePos); + txt = SubstituteVariables(parsingInstruction.Substring(parsePos, end - parsePos), variables); + + aux = txt.IndexOf('\\'); + while (aux != -1) + { // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed + txt = txt.Substring(0, aux) + txt.Substring(aux + 1, txt.Length - (aux + 1)); + aux = txt.IndexOf('\\', aux + 1); + }; + + respEnd = SearchResponse(response, txt, respBegin, times, true, '@'); + if ((respEnd == -1) || (respEnd > limit)) + { + result = ""; + break; + } + if (!removeSelection) + result += response.Substring(respBegin, respEnd - respBegin); + + respBegin = respEnd; + + if (removeFromHere >= 0) + { + response = response.Remove(removeFromHere, respEnd + txt.Length - removeFromHere); + respBegin = removeFromHere; + removeFromHere = -2; + removeSelection = false; + } + + parsePos = end + 1; + continue; + } + + if (parsingInstruction[parsePos] == '#') // insert the following string into the result + { + int end = GetNextChar(parsingInstruction, ';', parsePos); + parsePos++; + + string txt = parsingInstruction.Substring(parsePos, end - parsePos); + int aux = txt.IndexOf('\\'); + while (aux != -1) + { + // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed + txt = txt.Substring(0, aux) + txt.Substring(aux + 1, txt.Length - (aux + 1)); + aux = txt.IndexOf('\\', aux + 1); + } + + result += SubstituteVariables(txt, variables); + parsePos = end + 1; + continue; + } + + if (parsingInstruction[parsePos] == '~') // specify a limit, so the search instructions will search till this position. + { + int end = GetNextChar(parsingInstruction, ';', parsePos); + parsePos++; + + string txt = parsingInstruction.Substring(parsePos, end - parsePos); + int aux = txt.IndexOf('\\'); + while (aux != -1) + { + // if a '\' is found, it is eliminated because it is considered an escape character. However, if '\' is needed, add two, i.e. '\\', because only one of them will be removed + txt = txt.Substring(0, aux) + txt.Substring(aux + 1, txt.Length - (aux + 1)); + aux = txt.IndexOf('\\', aux + 1); + } + + limit = SearchResponse(response, txt, respBegin, 1, true, '~'); + if (limit == -1) + { + limit = response.Length; + } + + parsePos = end + 1; + continue; + } + + if (parsingInstruction[parsePos] == '0') // set the response cursor position to home_pos (normally 0, but '(' can set a different + // value for home_pos) + { + respBegin = home; + parsePos += 2; // jump the '0' and ';' characters + continue; + } + + if (parsingInstruction[parsePos] == '%') // delete the string (between ? and @) from response + { + removeSelection = true; + removeFromHere = -1; + parsePos++; + continue; + } + + if (parsingInstruction[parsePos] == '$') // create a variable to store a value from response string. This value is defined by the instructions between the '=' and the @ symbol (till here) + { + int end, varNumber, aux; + + parsePos++; + end = GetNextChar(parsingInstruction, '=', parsePos); + aux = GetNextChar(parsingInstruction, '$', parsePos); + if ((aux > 0) && (aux < end)) + end = parsingInstruction.Length; + if (end < parsingInstruction.Length) // variable assignment + { + varNumber = int.Parse(parsingInstruction.Substring(parsePos, end - parsePos)); + + parsePos = end + 1; + end = parsingInstruction.IndexOf("$$", parsePos); + string r = Parse(response, parsingInstruction.Substring(parsePos, end - parsePos), respBegin, false, variables, "#"); + if (r == "") + break; + variables[varNumber] = r; + + parsePos = end + 3; // jump $$; + } + else // pre-defined variable: Finish the parsing task or move to the end of the GDB response. + { + end = parsingInstruction.IndexOf('$', parsePos); + if (parsingInstruction.Substring(parsePos, end - parsePos) == "END") + break; + if (parsingInstruction.Substring(parsePos, end - parsePos) == "EOR") // move respBegin to the end of the response, probably + { + // to start looking from the end to the begin. + respBegin = response.Length - 1; + } + parsePos = end + 2; + } + continue; + } + + } + return (result); + } + + /// + /// Find the position of the associated closing bracket/parenthesis. + /// + /// The associated opening character ("(", "{" or "["). + /// The associated closing character (")", "}" or "]"). + /// The string where the search will be made. + /// Start position in the parsingInstruction string. This position normally corresponds to the position of the opening + /// character, but it could be smaller than that (never bigger!). However, if it is smaller, it cannot have the same character between + /// the 'startAt' position and the corresponding one for the opening one. If need to have another one, precede it by the character '\'. + /// Returns the position of the associated closing bracket/parenthesis. If it is not found, returns the length of the string. + public static int FindClosing(string text, char opening, char closing, int startAt) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException("text"); + + int end = GetNextChar(text, closing, startAt); + int other = startAt; + bool found = true; + do + { + other = GetNextChar(text, opening, other + 1); + if (other < end) + { + end = GetNextChar(text, closing, end + 1); + } + else + found = false; + } while (found); + return end; + } + + /// + /// Get the next position of a given character (token) in a string message (txt), starting from a given position (pos). + /// + /// String message in which it will search for the given character. + /// Character to search for. + /// Starting position in the string message. + /// An integer that corresponds to the next position of the character in the string. If the character is not found, returns the length of the string. + public static int GetNextChar(string text, char token, int startAt) + { + if (string.IsNullOrEmpty(text)) + return 0; + if (startAt > text.Length) + return text.Length; + + int end = startAt; + int slash; + + do + { + slash = 0; + end = text.IndexOf(token, startAt); + if (end == -1) + end = text.Length; + + int aux = end - 1; + while (aux >= 0 && text[aux] == '\\') + { + slash++; + aux--; + } + startAt = end + 1; + } while ((slash % 2) != 0); // PH: FIXME: what if there are 4 slashes before ;) + + return end; + } + + /// + /// Substitute the existing variables in the string "txt" by their values, stored in the "variables" array. Each variable name + /// has this format: $9$, where $ characters are used to identify the variable while the number corresponds to the variable ID, that also + /// corresponds to the array index. There is a special variable "$EOL$" that is substituted by "\r\n". + /// + /// String to search for variables. + /// Array with the variable values. + /// Returns the new modified string. + public static string SubstituteVariables(string text, string[] variables) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException("text"); + + if (variables == null || variables.Length == 0) + return text; + + do + { + int aux = GetNextChar(text, '$', 0); + if (aux >= 0 && aux < text.Length) + { + aux++; + int aux2 = GetNextChar(text, '$', aux); + if (aux2 < 0) + throw new FormatException("Missing closing $ for a variable definition"); + + string varNumber = text.Substring(aux, aux2 - aux); + if (varNumber == "EOL") + { + text = string.Concat(text.Substring(0, aux - 1), "\r\n", text.Substring(aux2 + 1, text.Length - (aux2 + 1))); + } + else + { + int index = int.Parse(varNumber); + if (index < 0 || index >= variables.Length) + throw new IndexOutOfRangeException("Unable to ask for a parameter value as " + index + " is out of range"); + + text = string.Concat(text.Substring(0, aux - 1), variables[index], text.Substring(aux2 + 1, text.Length - (aux2 + 1))); + } + } + else + { + break; + } + } + while (true); + + return text; + } + + /// + /// Get the position of a given string (txt) in the string GDB response (response), starting from a given position (begin). + /// + /// GDB string response where the search will be performed. + /// String to search for in the GDB response. + /// Starting position in the GDB string response. + /// Search for that string "times" times. Ex: I want to find the third occurrence of word "qaqa" in the GDB response. + /// Direction: if true, search forwards; if not, search backwards. Only '?' instruction can search backwards. + /// The kind of parsing instruction that called this method. '?', '@', or '~'. Only '?' instruction can + /// search backwards. + /// An integer that corresponds to the next position of the string in the GDB response. -1 in case of an error. + public static int SearchResponse(string response, string txt, int begin, int times, bool forward, char instruction) + { + if (string.IsNullOrEmpty(response)) + throw new ArgumentNullException("response"); + if (string.IsNullOrEmpty(txt)) + throw new ArgumentNullException("txt"); + + for (; times > 0; times--) + { + if (begin >= response.Length || begin == -1) + break; + if (forward) + { + if (begin == 0) + { + if (txt[0] == '\r' && txt[1] == '\n') + { + string check = txt.Substring(2, txt.Length - 2); + if (response.Substring(0, check.Length) == check) + continue; + } + } + begin = response.IndexOf(txt, begin); + if (begin != -1 && (times != 1 || instruction == '?')) + begin += txt.Length; + } + else + { + begin = response.LastIndexOf(txt, begin); + if (begin != -1) + { + if (times == 1) + begin += txt.Length; + else + begin--; + } + if (begin == -1 && txt[0] == '\r' && txt[1] == '\n') + begin = 2; // 2 is the size of "\r\n". + } + } + if (times == 0) + return begin; + return -1; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Debugger/InstructionCollection.cs b/src_vs2012/NativeCore/Debugger/InstructionCollection.cs new file mode 100644 index 00000000..be272b0e --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/InstructionCollection.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Debugger +{ + public sealed class InstructionCollection + { + private readonly List _items; + + public InstructionCollection() + { + _items = new List(); + } + + private InstructionCollection(List collection) + { + if (collection == null) + throw new ArgumentNullException("collection"); + + _items = collection; + } + + #region Properties + + /// + /// Gets the number of instructions. + /// + public int Count + { + get { return _items.Count; } + } + + /// + /// Gets the instruction at specified index. + /// + public Instruction this[int index] + { + get + { + if (index < 0 || index >= _items.Count) + return null; + + return _items[index]; + } + } + + #endregion + + /// + /// Creates the collection of instructions from specified content. + /// Each instruction is defined inside a single line. + /// + public static InstructionCollection Load(string content) + { + if (string.IsNullOrEmpty(content)) + throw new ArgumentNullException("content"); + + var result = new List(); + foreach (var line in content.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) + { + var instruction = Instruction.Load(result.Count, line); + if (instruction != null) + { + result.Add(instruction); + } + else + { + TraceLog.WriteLine("Unable to load instruction from line: \"{0}\"", line); + } + } + + return new InstructionCollection(result); + } + + /// + /// Creates a collection with predefined instructions. + /// + public static InstructionCollection Load() + { + var assembly = Assembly.GetExecutingAssembly(); + using (var stream = assembly.GetManifestResourceStream("BlackBerry.NativeCore.Resources.Instructions.txt")) + { + if (stream == null) + throw new InvalidProgramException("Resource with GDB instructions not found"); + + using (var reader = new StreamReader(stream, Encoding.UTF8)) + { + return Load(reader.ReadToEnd()); + } + } + } + + /// + /// Get the associated instruction ID from the command to be sent to GDB. + /// + /// Command to be sent to GDB. + /// When the instruction code stored in "map" is negative, it means that the commands parameters must be saved to + /// be used by the listeningGDB thread. When that happens, update and return variable "param". + /// Returns the instruction code for the command to be sent to GDB or -1 in case of an error. It can also return the command + /// parameters, as it was described above. + public Instruction Find(string command, out string param) + { + param = string.Empty; + + if (string.IsNullOrEmpty(command)) + return null; + + // everything separated by space are treated as params: + int pos = command.IndexOf(' '); + if (pos != -1) + { + param = command.Substring(pos, (command.Length - pos)).Replace(' ', ';'); + command = command.Substring(0, pos); + } + + foreach (var instruction in _items) + { + if (instruction.HasCommand(command)) + { + if (!instruction.ExpectsParameter) + { + param = string.Empty; + } + + return instruction; + } + } + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Model/BreakpointInfo.cs b/src_vs2012/NativeCore/Debugger/Model/BreakpointInfo.cs new file mode 100644 index 00000000..72ca3637 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Model/BreakpointInfo.cs @@ -0,0 +1,60 @@ +namespace BlackBerry.NativeCore.Debugger.Model +{ + /// + /// Description of the breakpoint received from the GDB. + /// + public sealed class BreakpointInfo + { + /// + /// Init constructor. + /// + public BreakpointInfo(uint id, string fileName, uint line, uint address) + { + ID = id; + FileName = fileName ?? string.Empty; + LongFileName = string.IsNullOrEmpty(fileName) ? string.Empty : NativeMethods.GetLongPathName(fileName); + Line = line; + Address = address; + } + + #region Properties + + /// + /// Gets the breakpoint ID in GDB. + /// + public uint ID + { + get; + private set; + } + + public string FileName + { + get; + private set; + } + + public string LongFileName + { + get; + private set; + } + + /// + /// Line number within the file. + /// + public uint Line + { + get; + private set; + } + + public uint Address + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Debugger/Model/IResult.cs b/src_vs2012/NativeCore/Debugger/Model/IResult.cs new file mode 100644 index 00000000..66a4eb5c --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Model/IResult.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; + +namespace BlackBerry.NativeCore.Debugger.Model +{ + /// + /// Interface describing attached result data returned with any GDB response. + /// + public interface IResult + { + /// + /// Gets the name of the field. + /// + string Name + { + get; + } + + /// + /// Gets the string value of the field. + /// + string StringValue + { + get; + } + + /// + /// Gets the numerical value of the field. + /// + uint UInt32Value + { + get; + } + + /// + /// Gets an indication, if the field is enumerable with values (array or object). + /// + bool IsEnumerable + { + get; + } + + /// + /// Gets the number of values stored. + /// + int Length + { + get; + } + + /// + /// Gets the enumerator of stored values. + /// + IEnumerable ArrayItems + { + get; + } + + /// + /// Gets the value at given index. + /// + IResult this[int index] + { + get; + } + + int Count + { + get; + } + + /// + /// Gets the enumerator of stored values. + /// + IEnumerable> ObjectItems + { + get; + } + + /// + /// Gets the value with given name. + /// + IResult this[string name] + { + get; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Model/ProcessInfo.cs b/src_vs2012/NativeCore/Debugger/Model/ProcessInfo.cs new file mode 100644 index 00000000..c2fb5112 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Model/ProcessInfo.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.Debugger.Model +{ + /// + /// Description of the process received from the device. + /// + public class ProcessInfo + { + /// + /// Init constructor, designated for GDB response. + /// + public ProcessInfo(uint id, string executablePath) + { + if (string.IsNullOrEmpty(executablePath)) + throw new ArgumentNullException("executablePath"); + + ID = id; + + // get the name of the process, based on the full executable name, simply - just grabs the last item of the path: + Name = PathHelper.ExtractName(executablePath); + Directory = PathHelper.ExtractDirectory(executablePath); + ExecutablePath = executablePath; + ShortExecutablePath = ExtractShortPath(executablePath); + } + + /// + /// Gets the short version of the path to the executable. + /// + private static string ExtractShortPath(string executablePath) + { + const string startToken = "accounts/1000/appdata/"; + const string startToken2 = "/accounts/1000/appdata/"; + + // is it a sandbox application? + if (executablePath.StartsWith(startToken, StringComparison.OrdinalIgnoreCase)) + return executablePath.Substring(startToken.Length); + if (executablePath.StartsWith(startToken2, StringComparison.OrdinalIgnoreCase)) + return executablePath.Substring(startToken2.Length); + + return executablePath; + } + + #region Properties + + public uint ID + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public string Directory + { + get; + private set; + } + + public string ExecutablePath + { + get; + private set; + } + + public string ShortExecutablePath + { + get; + private set; + } + + #endregion + + public override string ToString() + { + return string.Concat("0x", ID.ToString("X8"), " ", Name, " (", ExecutablePath, ")"); + } + + /// + /// Searches for a process with specified executable (full name or partial). + /// It will return null, if not found. + /// + public static ProcessInfo Find(IEnumerable processes, string executable) + { + if (processes == null) + throw new ArgumentNullException("processes"); + if (string.IsNullOrEmpty(executable)) + throw new ArgumentNullException("executable"); + + // first try to find identical executable: + foreach (var process in processes) + { + if (string.Compare(process.ExecutablePath, executable, StringComparison.OrdinalIgnoreCase) == 0) + return process; + } + + // is the name matching: + foreach (var process in processes) + { + if (string.Compare(process.Name, executable, StringComparison.OrdinalIgnoreCase) == 0) + return process; + } + + // or maybe only ends with it? + foreach (var process in processes) + { + if (process.ExecutablePath != null && process.ExecutablePath.EndsWith(executable, StringComparison.OrdinalIgnoreCase)) + return process; + } + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Request.cs b/src_vs2012/NativeCore/Debugger/Request.cs new file mode 100644 index 00000000..121ab070 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Request.cs @@ -0,0 +1,213 @@ +using System; +using System.Globalization; +using System.Threading; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Class describing a single request sent to the GDB. + /// + public class Request : IDisposable + { + private static int _globalID = 1000; + + + private readonly uint _id; + private string _command; + private AutoResetEvent _event; + + /// + /// Event fired each time a response is received. + /// + public event EventHandler Received; + + /// + /// Init constructor. + /// + public Request(string command) + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + _command = command; + _event = new AutoResetEvent(false); + + // make sure IDs never repeats, even if request created from different threads: + _id = (uint)Interlocked.Add(ref _globalID, 1); + } + + /// + /// Init constructor. + /// + public Request(uint id, string command) + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + _command = command; + _event = new AutoResetEvent(false); + + _id = id; + } + + /// + /// Dedicated constructor for a group of requests. + /// + protected Request() + { + _event = new AutoResetEvent(false); + } + + ~Request() + { + Dispose(false); + } + + #region Properties + + public virtual uint ID + { + get { return _id; } + } + + public virtual string Command + { + get { return _command; } + protected set { _command = value; } + } + + public virtual Response Response + { + get; + private set; + } + + #endregion + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (_event != null) + { + _event.Dispose(); + _event = null; + } + } + } + + #endregion + + public override string ToString() + { + // just serialize as the RAW command (with optional ID) + // INFO: the current implementation of DebugEngine assumes the IDs are at least 2-digit numbers + if (_id != 0) + return string.Concat(_id.ToString("D2", CultureInfo.InvariantCulture), _command); + return _command; + } + + /// + /// Checks if the request has identical ID as specified one. + /// + public bool HasIdenticalID(uint id) + { + return ID == id; + } + + /// + /// Method executed to perform request's action. It should return 'true', when all succeeded. + /// + public virtual bool Execute(IGdbSender sender) + { + if (sender == null) + throw new ArgumentNullException("sender"); + + return sender.Send(ToString()); + } + + /// + /// Mostly for parser testing. + /// + public bool Complete(Response response) + { + bool retry; + return Complete(response, out retry); + } + + /// + /// Method executed by GdbParser, to inform the request, that response has arrived. + /// There is no limitation for, how many responses a request can handle. + /// It should just return 'true', when it is the final one and use the 'retry' + /// parameter to be sent again to GDB. + /// + public virtual bool Complete(Response response, out bool retry) + { + if (response == null) + throw new ArgumentNullException("response"); + if (_event == null) + throw new ObjectDisposedException("Request"); + + // reset the state: + retry = false; + Response = response; + ProcessResponse(response); + + // notify all listeners synchronously: + var receivedHandler = Received; + if (receivedHandler != null) + receivedHandler(this, new ResponseReceivedEventArgs(this, response, false)); + + // wake up one waiting for response thread: + _event.Set(); + return true; + } + + /// + /// Method executed internally by the request to process incoming data. + /// + protected virtual void ProcessResponse(Response response) + { + } + + protected void SetEvent() + { + if (_event == null) + throw new ObjectDisposedException("Request"); + + _event.Set(); + } + + /// + /// Waits until this request received a response. + /// + /// Returns 'true', if the signal was received and response was valid, 'false' in case of timeout. + public bool Wait() + { + return Wait(GdbProcessor.ShortInfinite); + } + + /// + /// Waits specified number of milliseconds until this request received a response. + /// + /// Returns 'true', if the signal was received and response was valid, 'false' in case of timeout. + public bool Wait(int millisecondsTimeout) + { + if (_event == null) + throw new ObjectDisposedException("Request"); + + return _event.WaitOne(millisecondsTimeout); + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/RequestGroup.cs b/src_vs2012/NativeCore/Debugger/RequestGroup.cs new file mode 100644 index 00000000..295184d4 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/RequestGroup.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Represents a group of requests that should be threated as single request. + /// + public sealed class RequestGroup : Request + { + private readonly List _requests; + private int _activeIndex; + + public RequestGroup() + { + _requests = new List(); + _activeIndex = 0; + } + + #region Properties + + public Request ActiveRequest + { + get { return _activeIndex >= 0 && _activeIndex < _requests.Count ? _requests[_activeIndex] : null; } + } + + public override uint ID + { + get + { + var request = ActiveRequest; + if (request == null) + throw new InvalidOperationException("Current group has no active request"); + return request.ID; + } + } + + public override string Command + { + get + { + var request = ActiveRequest; + if (request == null) + throw new InvalidOperationException("Current group has no active request"); + + return request.Command; + } + } + + public override Response Response + { + get + { + var request = ActiveRequest; + if (request == null) + throw new InvalidOperationException("Current group has no active request"); + + return request.Response; + } + } + + #endregion + + public override string ToString() + { + var request = ActiveRequest; + return request == null ? string.Empty : ActiveRequest.ToString(); + } + + public void Add(Request request) + { + if (request == null) + throw new ArgumentNullException("request"); + + _requests.Add(request); + } + + public override bool Complete(Response response, out bool retry) + { + if (response == null) + throw new ArgumentNullException("response"); + + var request = ActiveRequest; + if (request == null) + throw new InvalidOperationException("Current group has no active request"); + + bool result = ActiveRequest.Complete(response, out retry); + if (result) + { + // is it the last request? + if (_activeIndex == _requests.Count - 1) + { + retry = false; + SetEvent(); + return true; + } + + // send next request from this group: + retry = true; + _activeIndex++; + } + + return false; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Requests/BreakRequest.cs b/src_vs2012/NativeCore/Debugger/Requests/BreakRequest.cs new file mode 100644 index 00000000..d3d9156d --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Requests/BreakRequest.cs @@ -0,0 +1,42 @@ +using System; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Debugger.Requests +{ + /// + /// Class wrapping sending Ctrl+C to the GDB. Since it will be a request, + /// it could be added into the queue and send at designated time, + /// without any worries that it was executed in the middle of other request execution. + /// + public sealed class BreakRequest : Request + { + /// + /// Default constructor. + /// + public BreakRequest() + : base("-exec-interrupt") + { + } + + /// + /// Method executed to perform request's action. It should return 'true', when all succeeded. + /// + public override bool Execute(IGdbSender sender) + { + if (sender == null) + throw new ArgumentNullException("sender"); + + try + { + sender.Break(); + } + catch (Exception ex) + { + TraceLog.WriteException(ex); + return false; + } + + return sender.Send(ToString()); + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Requests/CliRequest.cs b/src_vs2012/NativeCore/Debugger/Requests/CliRequest.cs new file mode 100644 index 00000000..5db3a026 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Requests/CliRequest.cs @@ -0,0 +1,19 @@ +namespace BlackBerry.NativeCore.Debugger.Requests +{ + /// + /// Class wrapping the regular CLI-command send to the GDB. + /// + public class CliRequest : Request + { + public CliRequest(string command) + : base(command) + { + } + + public override string ToString() + { + // CLI commands have no '-' in front of them + return string.Concat(ID, Command); + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Requests/MiRequest.cs b/src_vs2012/NativeCore/Debugger/Requests/MiRequest.cs new file mode 100644 index 00000000..800a6187 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Requests/MiRequest.cs @@ -0,0 +1,19 @@ +namespace BlackBerry.NativeCore.Debugger.Requests +{ + /// + /// Class wrapping the regular MI-command send to the GDB. + /// + public class MiRequest : Request + { + public MiRequest(string command) + : base(command) + { + } + + public override string ToString() + { + // MI commands to GDB have this magic '-' in front of them + return string.Concat(ID, "-", Command); + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Requests/ProcessListRequest.cs b/src_vs2012/NativeCore/Debugger/Requests/ProcessListRequest.cs new file mode 100644 index 00000000..761b4bf6 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Requests/ProcessListRequest.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.Debugger.Requests +{ + /// + /// Request class for requesting list of processes. + /// + public sealed class ProcessListRequest : CliRequest + { + /// + /// Default constructor. + /// + public ProcessListRequest() + : base("info pidlist") + { + Processes = new ProcessInfo[0]; + } + + #region Properties + + /// + /// Gets the list of processes. + /// + public ProcessInfo[] Processes + { + get; + private set; + } + + #endregion + + protected override void ProcessResponse(Response response) + { + Processes = ParseProcessList(response.Comments); + } + + /// + /// Parses typical response from GDB. + /// + private static ProcessInfo[] ParseProcessList(IEnumerable info) + { + const string processEndToken = " - "; + var result = new List(); + + foreach (var process in info) + { + int startAt = process.StartsWith("~\"") ? 2 : 0; + int pidStartAt = process.LastIndexOf(processEndToken, StringComparison.Ordinal); + + if (pidStartAt > 0) + { + string pidString; + uint pid; + int pidEndAt = process.IndexOf('/', pidStartAt); + if (pidEndAt < 0) + pidString = process.Substring(pidStartAt + processEndToken.Length).Trim(); + else + pidString = process.Substring(pidStartAt + processEndToken.Length, pidEndAt - pidStartAt - processEndToken.Length).Trim(); + + + if (uint.TryParse(pidString, NumberStyles.Number, null, out pid)) + { + // find, if there isn't already a process with identical PID: + if (!Contains(result, pid)) + { + var executablePath = process.Substring(startAt, pidStartAt - startAt); + result.Add(new ProcessInfo(pid, executablePath)); + } + } + } + } + + return result.ToArray(); + } + + private static bool Contains(IEnumerable list, uint pid) + { + foreach(var process in list) + if (process.ID == pid) + return true; + return false; + } + + /// + /// Searches for a process with specified executable (full name or partial). + /// It will return null, if not found. + /// + public ProcessInfo Find(string executable) + { + if (string.IsNullOrEmpty(executable)) + throw new ArgumentNullException("executable"); + + return ProcessInfo.Find(Processes, executable); + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/RequestsFactory.cs b/src_vs2012/NativeCore/Debugger/RequestsFactory.cs new file mode 100644 index 00000000..34aca1e3 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/RequestsFactory.cs @@ -0,0 +1,196 @@ +using System; +using System.IO; +using System.Text; +using BlackBerry.NativeCore.Debugger.Requests; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Factory class to produce GDB requests. + /// + public static class RequestsFactory + { + public static Request Exit() + { + return new MiRequest("gdb-exit"); + } + + public static Request Break() + { + return new BreakRequest(); + } + + public static Request ListFeatures() + { + return new MiRequest("list-features"); + } + + public static Request ListTargetFeatures() + { + return new MiRequest("list-target-features"); + } + + public static Request SetTargetDevice(string ip) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + + return new MiRequest(string.Concat("target-select qnx ", ip, ":8000")); + } + + public static Request SetTargetDevice(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + return SetTargetDevice(device.IP); + } + + public static ProcessListRequest ListProcesses() + { + return new ProcessListRequest(); + } + + public static Request SetPendingBreakpoints(bool on) + { + return new MiRequest("gdb-set breakpoint pending " + (on ? "on" : "off")); + } + + public static Request SetExecutable(string exeFileName, bool hasSymbols) + { + if (string.IsNullOrEmpty(exeFileName)) + throw new ArgumentNullException("exeFileName"); + if (!File.Exists(exeFileName)) + throw new FileNotFoundException("Specified executable doesn't exist", exeFileName); + + string command = hasSymbols + ? string.Concat("file-exec-and-symbols \"", exeFileName.Replace("\\", "\\\\"), "\"") + : string.Concat("file-exec-file \"", exeFileName.Replace("\\", "\\\\"), "\""); + return new MiRequest(command); + } + + public static Request SetLibrarySearchPath(string[] searchPaths) + { + if (searchPaths == null || searchPaths.Length == 0) + throw new ArgumentNullException("searchPaths"); + + // serialize paths: + var paths = new StringBuilder(); + foreach (var p in searchPaths) + { + paths.Append(p.Replace("\\", "\\\\")).Append(';'); + } + + // and return the prepared request: + return new CliRequest("set solib-search-path " + paths); + } + + public static Request SetLibrarySearchPath(GdbInfo gdbInfo) + { + if (gdbInfo == null) + throw new ArgumentNullException("gdbInfo"); + + return SetLibrarySearchPath(gdbInfo.LibraryPaths); + } + + public static Request SetLibrarySearchPath(GdbRunner runner) + { + if (runner == null) + throw new ArgumentNullException("runner"); + + return SetLibrarySearchPath(runner.GDB.LibraryPaths); + } + + public static Request AttachTargetProcess(uint pid) + { + return new MiRequest("target-attach " + pid); + } + + public static Request InfoThreads() + { + return new CliRequest("info threads"); + } + + public static Request DetachTargetProcess() + { + return new MiRequest("target-detach"); + } + + public static Request SetStackTraceDepth(int threadID, int depth) + { + if (depth < 0) + return new MiRequest("stack-info-depth --thread " + threadID + " --frame 0"); + return new MiRequest("stack-info-depth " + depth + " --thread " + threadID + " --frame 0"); + } + + public static Request StackTraceListFrames() + { + return new MiRequest("stack-list-frames"); + } + + public static Request InsertBreakPoint(string fileName, uint line) + { + if (string.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + + return new MiRequest("break-insert --thread-group i1 -f " + fileName + ":" + line); + } + + public static Request InsertBreakpoint(string functionName) + { + if (string.IsNullOrEmpty(functionName)) + throw new ArgumentNullException("functionName"); + + return new MiRequest("break-insert --thread-group i1 -f " + functionName); + } + + public static Request DeleteBreakpoint(params uint[] breakpointIDs) + { + if (breakpointIDs == null || breakpointIDs.Length == 0) + throw new ArgumentNullException("breakpointIDs"); + + if (breakpointIDs.Length == 1) + return new MiRequest("break-delete " + breakpointIDs[0]); + + var identifiers = new StringBuilder(); + for (int i = 0; i < identifiers.Length; i++) + { + identifiers.Append(i).Append(' '); + } + + return new MiRequest("break-delete " + identifiers); + } + + public static Request Continue() + { + return new MiRequest("exec-continue"); + } + + public static Request Run() + { + return new MiRequest("exec-run"); + } + + /// + /// Creates a group request. + /// + public static RequestGroup Group(params Request[] requests) + { + if (requests != null) + { + var group = new RequestGroup(); + foreach (var r in requests) + { + if (r != null) + group.Add(r); + } + + return group; + } + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/Response.cs b/src_vs2012/NativeCore/Debugger/Response.cs new file mode 100644 index 00000000..5a6faa27 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/Response.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Class representing any response received from GDB. + /// + [DebuggerDisplay("{RawData}")] + public class Response + { + /// + /// List of characters that describe a response. + /// Full info here: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Output-Syntax.html + /// + private const string ResponseTypeChars = "^*+=~@&"; + + private const string ResponseCommentChars = "~@&"; + + /// + /// Init constructor. + /// + /// Optional original response received from GDB, before parsing + /// Identifier of the response (it should match the ID of the request) + /// Name and content of the response (this value is optional) + /// Additional asynchronous exec and status outputs received along with the result record content + /// Additional asynchronous notifications received along with the result record content + /// Additional comments received along with the content + public Response(string[] rawData, uint id, string content, string[] statusOutputs, string[] notifications, string[] comments) + { + if (rawData == null || rawData.Length == 0) + throw new ArgumentOutOfRangeException("rawData"); + + RawData = rawData; + ID = id; + + if (!string.IsNullOrEmpty(content)) + { + int argumentsAt = content.IndexOf(','); + Name = argumentsAt < 0 ? content : content.Substring(0, argumentsAt); + Content = argumentsAt < 0 ? null : content.Substring(argumentsAt + 1); + } + else + { + Name = null; + Content = null; + } + StatusOutputs = statusOutputs ?? new string[0]; + Notifications = notifications ?? new string[0]; + Comments = comments ?? new string[0]; + } + + #region Properties + + /// + /// The original response received from GDB, before parsing. + /// + public string[] RawData + { + get; + private set; + } + + public uint ID + { + get; + private set; + } + + /// + /// Name of the result record. + /// + public string Name + { + get; + private set; + } + + /// + /// Content arguments passed along with the result record. + /// + public string Content + { + get; + private set; + } + + public string[] StatusOutputs + { + get; + private set; + } + + public string[] Notifications + { + get; + private set; + } + + public string[] Comments + { + get; + private set; + } + + #endregion + + public override string ToString() + { + return Name; + } + + public static Response Parse(string[] message) + { + if (message == null || message.Length == 0) + throw new ArgumentNullException("message"); + + // split the input into stream-records and result-record: + string resultRecord = null; + string resultID = null; + List streamRecords = null; + List asyncOutputRecords = null; + List notificationRecords = null; + + foreach (var line in message) + { + if (string.IsNullOrEmpty(line)) + throw new FormatException("Empty line inside message is not allowed"); + int lineIndex; + char typeChar = FindTypeChar(line, out lineIndex); + + if (lineIndex < 0) + { + // PH: unknown message type... maybe we could assume it's a comment, + // but better double check it... + throw new FormatException("Type of the line was not recognized"); + } + + // is comment? + if (IsCommentLine(typeChar)) + { + if (streamRecords == null) + streamRecords = new List(); + streamRecords.Add(line); + + if (asyncOutputRecords == null) + asyncOutputRecords = new List(); + asyncOutputRecords.Add(line); + } + else + { + var type = GetResponseType(typeChar); + + switch (type) + { + case ResponseType.ResultRecord: + if (resultRecord != null) + throw new FormatException("More than one result record is not expected inside GDB message"); + + resultID = lineIndex > 0 ? line.Substring(0, lineIndex) : null; + resultRecord = line.Substring(lineIndex + 1); + + if (asyncOutputRecords == null) + asyncOutputRecords = new List(); + asyncOutputRecords.Add(line.Substring(lineIndex)); + break; + case ResponseType.ExecAsyncOutput: /* fall through */ + case ResponseType.StatusAsyncOutput: + if (asyncOutputRecords == null) + asyncOutputRecords = new List(); + asyncOutputRecords.Add(line); + break; + case ResponseType.NotificationAsyncOutput: + if (notificationRecords == null) + notificationRecords = new List(); + notificationRecords.Add(line); + break; + } + } + } + + // found comments only message: + if (resultRecord == null) + { + return new Response(message, 0, null, asyncOutputRecords != null ? asyncOutputRecords.ToArray() : null, notificationRecords != null ? notificationRecords.ToArray() : null, streamRecords != null ? streamRecords.ToArray() : null); + } + + // get the response identifier + uint id = 0; + if (!string.IsNullOrEmpty(resultID)) + { + // this should be a valid number, otherwise check, why it failed: + id = uint.Parse(resultID); + } + + return new Response(message, id, resultRecord, asyncOutputRecords != null ? asyncOutputRecords.ToArray() : null, notificationRecords != null ? notificationRecords.ToArray() : null, streamRecords != null ? streamRecords.ToArray() : null); + } + + private static ResponseType GetResponseType(char typeChar) + { + switch (typeChar) + { + case '^': + return ResponseType.ResultRecord; + case '*': + return ResponseType.ExecAsyncOutput; + case '+': + return ResponseType.StatusAsyncOutput; + case '=': + return ResponseType.NotificationAsyncOutput; + case '~': /* fall through */ + case '@': /* fall through */ + case '&': + return ResponseType.StreamRecord; + default: + throw new ArgumentOutOfRangeException("typeChar"); + } + } + + private static bool IsCommentLine(char typeChar) + { + return ResponseCommentChars.IndexOf(typeChar) >= 0; + } + + /// + /// Gets the response type character. If the expected char is out of the known list, '\0' and -1 is returned. + /// It returns also the index, where the char was found, to easier extract the ID, if neeed. + /// + private static char FindTypeChar(string line, out int lineIndex) + { + if (string.IsNullOrEmpty(line)) + throw new ArgumentNullException("line"); + + int length = line.Length; + for (int i = 0; i < length; i++) + { + if (char.IsDigit(line[i])) + continue; + + // is it known response type? + if (ResponseTypeChars.IndexOf(line[i]) < 0) + { + lineIndex = -1; + return '\0'; + } + + lineIndex = i; + return line[i]; + } + + lineIndex = -1; + return '\0'; + } + } +} diff --git a/src_vs2012/NativeCore/Debugger/ResponseParsedEventArgs.cs b/src_vs2012/NativeCore/Debugger/ResponseParsedEventArgs.cs new file mode 100644 index 00000000..1233a617 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/ResponseParsedEventArgs.cs @@ -0,0 +1,36 @@ +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Arguments passed along with response received from GDB and processed by parsing instructions of GdbWrapper. + /// + public sealed class ResponseParsedEventArgs : ResponseReceivedEventArgs + { + /// + /// Init constructor. + /// + public ResponseParsedEventArgs(Request request, Response response, bool handled, string parsedResult) + : base(request, response, handled) + { + ParsedResult = parsedResult; + } + + /// + /// Init constructor. + /// + public ResponseParsedEventArgs(ResponseReceivedEventArgs e, string parsedResult) + : base(e != null ? e.Request : null, e != null ? e.Response : null, e != null && e.Handled) + { + ParsedResult = parsedResult; + } + + #region Properties + + public string ParsedResult + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Debugger/ResponseReceivedEventArgs.cs b/src_vs2012/NativeCore/Debugger/ResponseReceivedEventArgs.cs new file mode 100644 index 00000000..3492c903 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/ResponseReceivedEventArgs.cs @@ -0,0 +1,61 @@ +using System; + +namespace BlackBerry.NativeCore.Debugger +{ + /// + /// Arguments broadcased along with response received by given components. + /// + public class ResponseReceivedEventArgs : EventArgs + { + private bool _handled; + + /// + /// Init constructor. + /// + public ResponseReceivedEventArgs(Request request, Response response, bool handled) + { + if (response == null) + throw new ArgumentNullException("response"); + + Request = request; + Response = response; + _handled = handled; + } + + #region Properties + + /// + /// Optional request, that was supposed to issue the response. + /// + public Request Request + { + get; + private set; + } + + /// + /// Received response. + /// + public Response Response + { + get; + private set; + } + + /// + /// Gets or sets the indication, if given response was handled. + /// Once set, it can not be reverted. + /// + public bool Handled + { + get { return _handled; } + set + { + if (value) + _handled = true; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/src_vs2012/NativeCore/Debugger/ResponseType.cs b/src_vs2012/NativeCore/Debugger/ResponseType.cs new file mode 100644 index 00000000..ec08cc53 --- /dev/null +++ b/src_vs2012/NativeCore/Debugger/ResponseType.cs @@ -0,0 +1,14 @@ +namespace BlackBerry.NativeCore.Debugger +{ + public enum ResponseType + { + ResultRecord, + ExecAsyncOutput, + StatusAsyncOutput, + NotificationAsyncOutput, + /// + /// Comments only record. + /// + StreamRecord + } +} diff --git a/src_vs2012/NativeCore/Diagnostics/BlackBerryTraceListener.cs b/src_vs2012/NativeCore/Diagnostics/BlackBerryTraceListener.cs new file mode 100644 index 00000000..c2842d81 --- /dev/null +++ b/src_vs2012/NativeCore/Diagnostics/BlackBerryTraceListener.cs @@ -0,0 +1,103 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; + +namespace BlackBerry.NativeCore.Diagnostics +{ + /// + /// Trace listener, that writes BlackBerry-only messages into the file. + /// + public sealed class BlackBerryTraceListener : TraceListener + { + public const string SName = "Persistent BlackBerry Trace Listener"; + + private TextWriter _output; + private readonly TimeTracker _time; + + /// + /// Inti constructor. + /// + public BlackBerryTraceListener(string fileName, bool printTime) + : this(string.IsNullOrEmpty(fileName) ? null : File.CreateText(fileName), printTime) + { + } + + /// + /// Init constructor. + /// + public BlackBerryTraceListener(Stream stream, Encoding encoding, bool printTime) + : this((stream == null ? null : new StreamWriter(stream, encoding)), printTime) + { + } + + /// + /// Init constructor. + /// + public BlackBerryTraceListener(TextWriter output, bool printTime) + : base(SName) + { + if (output == null) + throw new ArgumentNullException("output"); + + _output = output; + if (printTime) + _time = new TimeTracker(); + } + + protected override void Dispose(bool disposing) + { + if (_output != null) + { + ((IDisposable)_output).Dispose(); + _output = null; + } + } + + public override void Flush() + { + if (_output != null) + { + _output.Flush(); + } + } + + public override void Write(string message) + { + // do nothing, only want to capture filtered-by-category messages + } + + public override void WriteLine(string message) + { + // do nothing, only want to capture filtered-by-category messages + } + + public override void Write(string message, string category) + { + if (_output == null) + return; + + // print only messages of 'BlackBerry' category: + if (string.CompareOrdinal(category, TraceLog.Category) != 0) + return; + + if (_time != null) + _time.Write(_output); + _output.Write(message); + } + + public override void WriteLine(string message, string category) + { + if (_output == null) + return; + + // print only messages of 'BlackBerry' category: + if (string.CompareOrdinal(category, TraceLog.Category) != 0) + return; + + if (_time != null) + _time.WriteAndReset(_output); + _output.WriteLine(message); + } + } +} diff --git a/src_vs2012/NativeCore/Diagnostics/QTraceLog.cs b/src_vs2012/NativeCore/Diagnostics/QTraceLog.cs new file mode 100644 index 00000000..ffb178db --- /dev/null +++ b/src_vs2012/NativeCore/Diagnostics/QTraceLog.cs @@ -0,0 +1,138 @@ +using System; +using System.Diagnostics; +using System.Text; + +namespace BlackBerry.NativeCore.Diagnostics +{ + /// + /// Helper class for printing QNX trace log messages. + /// + public static class QTraceLog + { + public const string Category = "QConn"; + + /// + /// Writes a debug message. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteLine(string message) + { + if (message == null) + return; + + Trace.WriteLine(message, Category); + } + + /// + /// Writes a debug message. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteLine(string format, params object[] args) + { + if (format == null) + return; + + Trace.WriteLine(string.Format(format, args), Category); + } + + /// + /// Writes info about the exception. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteException(Exception ex) + { + if (ex == null) + return; + + Trace.WriteLine(TraceLog.FlatException(ex, null), Category); + } + + /// + /// Writes info about the exception. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteException(Exception ex, string message) + { + if (ex == null) + { + WriteLine(message); + } + else + { + Trace.WriteLine(TraceLog.FlatException(ex, message), Category); + } + } + + /// + /// Writes info about the exception. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteException(Exception ex, string format, params object[] args) + { + if (ex == null) + { + WriteLine(format, args); + } + else + { + string message = format == null ? null : string.Format(format, args); + Trace.WriteLine(TraceLog.FlatException(ex, message), Category); + } + } + + /// + /// Dumps an array into the logs. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void PrintArray(string name, byte[] values) + { + StringBuilder result = new StringBuilder(); + + // print byte array for Java: + result.Append("byte[] ").Append(name).Append(" = new byte[ /* ").Append(values.Length).Append(" */ ] {"); + int i = 0; + foreach (byte v in values) + { + if (i > 0) + result.Append(", "); + i++; + + // print signed value: + result.Append((sbyte)v); + } + result.Append("};"); + + // and the same array for C#: + result.AppendLine(); + result.Append("// byte[] ").Append(name).Append("CS = new byte[ /* ").Append(values.Length).Append(" */ ] {"); + i = 0; + foreach (byte v in values) + { + if (i > 0) + result.Append(", "); + i++; + + // print signed value: + result.Append(v); + } + result.Append("};"); + + // and also print it out as string: + result.AppendLine(); + result.Append("String ").Append(name).Append("Str = \"00"); // fince in Java BigInteger is 2-complement, so we start with leading zeros, not to have a minus numbers... + foreach (var v in values) + { + result.Append(v.ToString("X2")); + } + result.Append("\";"); + + Trace.WriteLine(result.ToString()); + } + } +} diff --git a/src_vs2012/NativeCore/Diagnostics/TimeTracker.cs b/src_vs2012/NativeCore/Diagnostics/TimeTracker.cs new file mode 100644 index 00000000..79eb0edd --- /dev/null +++ b/src_vs2012/NativeCore/Diagnostics/TimeTracker.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; + +namespace BlackBerry.NativeCore.Diagnostics +{ + /// + /// Helper class for managing the 'time' part of the trace-log messages. + /// + public sealed class TimeTracker + { + private readonly char[] _time; + private int _messagePart; + + public TimeTracker() + { + _time = CreateTimeArray(); + } + + private static char[] CreateTimeArray() + { + return new[] { '0', '0', ':', '0', '0', ':', '0', '0', '.', '0', '0', '0', ':', ' ' }; + } + + /// + /// Update the already allocated array with current time. + /// + private void UpdateTimeArray() + { + DateTime time = DateTime.Now; + + _time[0] = time.Hour < 10 ? '0' : (char)('0' + (time.Hour / 10)); + _time[1] = (char)('0' + (time.Hour % 10)); + + _time[3] = time.Minute < 10 ? '0' : (char)('0' + (time.Minute / 10)); + _time[4] = (char)('0' + (time.Minute % 10)); + + _time[6] = time.Second < 10 ? '0' : (char)('0' + (time.Second / 10)); + _time[7] = (char)('0' + (time.Second % 10)); + + int millisecond = time.Millisecond; + _time[11] = (char)('0' + (millisecond % 10)); + millisecond /= 10; + _time[10] = (char)('0' + (millisecond % 10)); + millisecond /= 10; + _time[9] = (char)('0' + (millisecond % 10)); + } + + public void Write(TextWriter output) + { + if (_messagePart == 0) + { + UpdateTimeArray(); + output.Write(_time); + } + + _messagePart++; + } + + public void WriteAndReset(TextWriter output) + { + if (_messagePart == 0) + { + UpdateTimeArray(); + output.Write(_time); + } + + _messagePart = 0; + } + + public string GetCurrent() + { + string result = null; + + if (_messagePart == 0) + { + UpdateTimeArray(); + result = new string(_time); + } + + _messagePart++; + return result; + } + + public string GetCurrentAndReset() + { + string result = null; + + if (_messagePart == 0) + { + UpdateTimeArray(); + result = new string(_time); + } + + _messagePart = 0; + return result; + } + } +} diff --git a/src_vs2012/NativeCore/Diagnostics/TraceLog.cs b/src_vs2012/NativeCore/Diagnostics/TraceLog.cs new file mode 100644 index 00000000..c8e552c0 --- /dev/null +++ b/src_vs2012/NativeCore/Diagnostics/TraceLog.cs @@ -0,0 +1,152 @@ +using System; +using System.Diagnostics; +using System.Text; + +namespace BlackBerry.NativeCore.Diagnostics +{ + /// + /// Helper class for printing trace log messages. + /// + public static class TraceLog + { + public const string Category = "BlackBerry"; + public const string CategoryGDB = "GDB"; + public const string CategoryDevice = "BBDeviceLog"; + + /// + /// Add new trace-log message listener. + /// + [Conditional("TRACE")] + public static void Add(TraceListener listener) + { + if (listener != null) + { + Trace.Listeners.Add(listener); + } + } + + /// + /// Writes a debug message. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteLine(string message) + { + if (message == null) + return; + + Trace.WriteLine(message, Category); + } + + /// + /// Writes a debug message. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteLine(string format, params object[] args) + { + if (format == null) + return; + + Trace.WriteLine(string.Format(format, args), Category); + } + + /// + /// Writes a warning message. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WarnLine(string message) + { + if (message == null) + return; + + Trace.WriteLine("!! " + message, Category); + } + + /// + /// Writes a warning message. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WarnLine(string format, params object[] args) + { + if (format == null) + return; + + Trace.WriteLine("!! " + string.Format(format, args), Category); + } + + /// + /// Writes info about the exception. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteException(Exception ex) + { + if (ex == null) + return; + + Trace.WriteLine(FlatException(ex, null), Category); + } + + /// + /// Writes info about the exception. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteException(Exception ex, string message) + { + if (ex == null) + { + WriteLine(message); + } + else + { + Trace.WriteLine(FlatException(ex, message), Category); + } + } + + /// + /// Writes info about the exception. + /// + [Conditional("TRACE")] + [DebuggerStepThrough] + public static void WriteException(Exception ex, string format, params object[] args) + { + if (ex == null) + { + WriteLine(format, args); + } + else + { + string message = format == null ? null : string.Format(format, args); + Trace.WriteLine(FlatException(ex, message), Category); + } + } + + /// + /// Converts exception data into a single string. + /// + [DebuggerStepThrough] + internal static string FlatException(Exception ex, string message) + { + var result = new StringBuilder(); + + if (message != null) + result.AppendLine(message); + + while (ex != null) + { + // get info: + result.Append("### (").Append(ex.GetType().Name).Append(") ").AppendLine(ex.Message); + result.AppendLine(ex.StackTrace); + + // switch to inner one: + ex = ex.InnerException; + } + + return result.ToString(); + } + } +} diff --git a/src_vs2012/NativeCore/Helpers/BitHelper.cs b/src_vs2012/NativeCore/Helpers/BitHelper.cs new file mode 100644 index 00000000..cf936e57 --- /dev/null +++ b/src_vs2012/NativeCore/Helpers/BitHelper.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BlackBerry.NativeCore.Helpers +{ + /// + /// Helper class for array-of-bytes conversions. + /// + static class BitHelper + { + /// + /// Appends values from specified arrays one-by-one, starting at the given index. + /// + public static void Copy(byte[] data, int at, params byte[][] arrays) + { + if (data == null) + throw new ArgumentNullException("data"); + + foreach (byte[] values in arrays) + { + Array.Copy(values, 0, data, at, values.Length); + at += values.Length; + } + } + + /// + /// Sets unsigned short value at specified index of an array. + /// + public static void BigEndian_Set(byte[] data, int at, ushort value) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 1 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + data[at] = (byte)((value >> 8) & 0xFF); + data[at + 1] = (byte)(value & 0xFF); + } + + /// + /// Gets unsigned short value from specified index of an array. + /// + public static ushort BigEndian_ToUInt16(byte[] data, int at) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 1 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + return (ushort)((data[at] << 8) | data[at + 1]); + } + + /// + /// Gets unsigned integer value from specified index of an array. + /// + public static uint BigEndian_ToUInt32(byte[] data, int at) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 3 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + return (uint)((data[at] << 24) | (data[at + 1] << 16) | (data[at + 2] << 8) | data[at + 3]); + } + + /// + /// Gets unsigned long integer value from specified index of an array. + /// + public static ulong BigEndian_ToUInt64(byte[] data, int at) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 7 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + uint high = (uint)((data[at] << 24) | (data[at + 1] << 16) | (data[at + 2] << 8) | data[at + 3]); + uint low = (uint)((data[at + 4] << 24) | (data[at + 5] << 16) | (data[at + 6] << 8) | data[at + 7]); + return ((ulong)high << 32) | low; + } + + /// + /// Sets unsigned short value at specified index of an array. + /// + public static void LittleEndian_Set(byte[] data, int at, ushort value) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 1 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + data[at] = (byte)(value & 0xFF); + data[at + 1] = (byte)((value >> 8) & 0xFF); + } + + /// + /// Sets unsigned integer value at specified index of an array. + /// + public static void LittleEndian_Set(byte[] data, int at, uint value) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 3 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + data[at] = (byte)(value & 0xFF); + data[at + 1] = (byte)((value >> 8) & 0xFF); + data[at + 2] = (byte)((value >> 16) & 0xFF); + data[at + 3] = (byte)((value >> 24) & 0xFF); + } + + /// + /// Gets unsigned short value from specified index of an array. + /// + public static ushort LittleEndian_ToUInt16(byte[] data, int at) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 1 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + return (ushort)(data[at] | (data[at + 1] << 8)); + } + + /// + /// Gets unsigned integer value from specified index of an array. + /// + public static uint LittleEndian_ToUInt32(byte[] data, int at) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 3 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + return (uint)(data[at] | (data[at + 1] << 8) | (data[at + 2] << 16) | (data[at + 3] << 24)); + } + + /// + /// Gets unsigned long integer value from specified index of an array. + /// + public static ulong LittleEndian_ToUInt64(byte[] data, int at) + { + if (data == null) + throw new ArgumentNullException("data"); + if (at + 7 >= data.Length || at < 0) + throw new ArgumentOutOfRangeException("at"); + + uint low = (uint)(data[at] | (data[at + 1] << 8) | (data[at + 2] << 16) | (data[at + 3] << 24)); + uint high = (uint)(data[at + 4] | (data[at + 5] << 8) | (data[at + 6] << 16) | (data[at + 7] << 24)); + return ((ulong)high << 32) | low; + } + + /// + /// Converts given byte array to hex number. + /// + public static string Enconde(IEnumerable data) + { + if (data == null) + throw new ArgumentNullException("data"); + + StringBuilder result = new StringBuilder(); + char[] HexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + foreach (var v in data) + { + result.Append(HexChars[(v & 0xF0) >> 4]); + result.Append(HexChars[v & 0x0F]); + } + + return result.ToString(); + } + + /// + /// Allocates new array and copies there data from specified collection of chunks. + /// The last one (lastChunk) doesn't need to be fully filled. + /// + public static byte[] Combine(List buffers, byte[] lastChunk, int lastChunkLength) + { + // calculate result length: + int resultLength = lastChunkLength; + if (buffers != null) + { + // or is it a special case, when abandoned buffer is the only item: + if (buffers.Count == 1 && (lastChunk == null || lastChunkLength == 0)) + { + return buffers[0]; + } + + for (int i = 0; i < buffers.Count; i++) + { + resultLength += buffers[i].Length; + } + } + + // copy data: + var result = new byte[resultLength]; + int index = 0; + + if (buffers != null) + { + for (int i = 0; i < buffers.Count; i++) + { + byte[] src = buffers[i]; + Array.Copy(src, 0, result, index, src.Length); + index += src.Length; + } + } + + if (lastChunk != null) + { + // and copy the last chunk: + Array.Copy(lastChunk, 0, result, index, lastChunkLength); + } + + return result; + } + + /// + /// Combines two arrays into one. + /// + public static byte[] Combine(byte[] buffer, byte[] chunk, int chunkAt, int chunkLength) + { + if (buffer == null) + { + if (chunk == null) + { + return null; + } + + // extract only the part of the chunk: + var result = new byte[chunkLength]; + Array.Copy(chunk, chunkAt, result, 0, chunkLength); + return result; + } + + if (chunk == null || chunkLength == 0) + { + return buffer; + } + + var bothArrays = new byte[buffer.Length + chunkLength]; + Array.Copy(buffer, 0, bothArrays, 0, buffer.Length); + Array.Copy(chunk, chunkAt, bothArrays, buffer.Length, chunkLength); + return bothArrays; + } + + /// + /// Combines two arrays into one. + /// + public static byte[] Combine(byte[] buffer, int bufferAt, int bufferLength, byte[] chunk) + { + if (buffer == null || bufferLength == 0) + { + return chunk; + } + + if (chunk == null) + { + // extract only the part of the buffer: + var result = new byte[bufferLength]; + Array.Copy(buffer, bufferAt, result, 0, bufferLength); + return result; + } + + var bothArrays = new byte[bufferLength + chunk.Length]; + Array.Copy(buffer, bufferAt, bothArrays, 0, bufferLength); + Array.Copy(chunk, 0, bothArrays, bufferLength, chunk.Length); + return bothArrays; + } + } +} diff --git a/src_vs2012/NativeCore/Helpers/DeviceHelper.cs b/src_vs2012/NativeCore/Helpers/DeviceHelper.cs new file mode 100644 index 00000000..ea8163f8 --- /dev/null +++ b/src_vs2012/NativeCore/Helpers/DeviceHelper.cs @@ -0,0 +1,85 @@ +using System; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Helpers +{ + /// + /// Helper class with DeviceFamilyType methods. + /// + public sealed class DeviceHelper + { + /// + /// Gets the string representation of the DeviceDefinitionType. + /// + public static string GetTypeToString(DeviceDefinitionType type) + { + switch (type) + { + case DeviceDefinitionType.Simulator: + return "simulator"; + case DeviceDefinitionType.Device: + return "device"; + default: + throw new ArgumentOutOfRangeException("type"); + } + } + + /// + /// Gets the DeviceDefinitionType from string. + /// + public static DeviceDefinitionType GetTypeFromString(string name, bool throwOnFailure) + { + if (string.IsNullOrEmpty(name)) + return DeviceDefinitionType.Device; + + if (string.Compare("simulator", name, StringComparison.OrdinalIgnoreCase) == 0) + return DeviceDefinitionType.Simulator; + if (string.Compare("sim", name, StringComparison.OrdinalIgnoreCase) == 0) + return DeviceDefinitionType.Simulator; + if(name == "S" || name == "s") + return DeviceDefinitionType.Simulator; + + if (string.Compare("device", name, StringComparison.OrdinalIgnoreCase) == 0) + return DeviceDefinitionType.Device; + if (string.Compare("dev", name, StringComparison.OrdinalIgnoreCase) == 0) + return DeviceDefinitionType.Device; + if (name == "D" || name == "d") + return DeviceDefinitionType.Device; + + if (throwOnFailure) + throw new ArgumentOutOfRangeException("name", "Invalid device type specified: \"" + name + "\""); + + return DeviceDefinitionType.Device; + } + + /// + /// Gets the string representation of the DeviceFamilyType. + /// + public static string GetFamilyTypeToString(DeviceFamilyType type) + { + switch (type) + { + case DeviceFamilyType.Phone: + return "phone"; + case DeviceFamilyType.Tablet: + return "tablet"; + default: + throw new ArgumentOutOfRangeException("type"); + } + } + + /// + /// Gets the DeviceFamilyType from string. + /// + public static DeviceFamilyType GetFamilyTypeFromString(string name) + { + if (string.IsNullOrEmpty(name)) + return DeviceFamilyType.Phone; + + if (string.Compare("tablet", name, StringComparison.OrdinalIgnoreCase) == 0) + return DeviceFamilyType.Tablet; + + return DeviceFamilyType.Phone; + } + } +} diff --git a/src_vs2012/NativeCore/Helpers/GlobalHelper.cs b/src_vs2012/NativeCore/Helpers/GlobalHelper.cs new file mode 100644 index 00000000..f16a33f1 --- /dev/null +++ b/src_vs2012/NativeCore/Helpers/GlobalHelper.cs @@ -0,0 +1,71 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Security; +using System.Text; +using System.Security.Cryptography; + +namespace BlackBerry.NativeCore.Helpers +{ + /// + /// Class providing common helper functions. + /// + public static class GlobalHelper + { + /// + /// Checks if user is online. Needs to be online for UpdateManager to work. + /// + public static bool IsOnline + { + get + { + try + { + Dns.GetHostEntry("downloads.blackberry.com"); + return true; + } + catch (SocketException) + { + return false; + } + } + } + + /// + /// Encrypts a given password and returns the encrypted data as a base64 string. + /// + /// An unencrypted string that needs to be secured. + /// A base64 encoded string that represents the encrypted binary data. + /// + /// This solution is not really secure as we are keeping strings in memory. If runtime protection is essential, should be used. + /// If is a null reference. + public static string Encrypt(string text) + { + if (text == null) + throw new ArgumentNullException("text"); + + var data = Encoding.Unicode.GetBytes(text); + var encrypted = ProtectedData.Protect(data, null, DataProtectionScope.LocalMachine); + + return Convert.ToBase64String(encrypted); + } + + /// + /// Decrypts a given string. + /// + /// A base64 encoded string that was created through the extension method. + /// The decrypted string. + /// Keep in mind that the decrypted string remains in memory and makes your application vulnerable per se. If runtime protection is essential, should be used. + /// If is a null reference. + public static string Decrypt(string cipher) + { + if (cipher == null) + throw new ArgumentNullException("cipher"); + + var data = Convert.FromBase64String(cipher); + var decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.LocalMachine); + + return Encoding.Unicode.GetString(decrypted); + } + } +} diff --git a/src_vs2012/NativeCore/Helpers/NameValueCollectionHelper.cs b/src_vs2012/NativeCore/Helpers/NameValueCollectionHelper.cs new file mode 100644 index 00000000..c8da0364 --- /dev/null +++ b/src_vs2012/NativeCore/Helpers/NameValueCollectionHelper.cs @@ -0,0 +1,181 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using System.Text; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Helpers +{ + /// + /// Helper class for managing key-value collection. + /// + public static class CollectionHelper + { + /// + /// Dumps given collection into a single string. + /// All values are converted to Base64 (just to avoid possible collisions with special separator chars: ';' and '='). + /// + public static string Serialize(Dictionary dictionary) + { + if (dictionary == null) + throw new ArgumentNullException("dictionary"); + + var result = new StringBuilder(); + foreach (var pair in dictionary) + { + if (pair.Key.IndexOf('=') >= 0 || pair.Key.IndexOf(';') >= 0) + throw new ArgumentOutOfRangeException("dictionary", "Forbidden char found in key name (" + pair.Key + ")"); + + result.Append(pair.Key).Append('='); + if (pair.Value == null) + result.Append('~'); + else + { + if (!string.IsNullOrEmpty(pair.Value)) + result.Append(Convert.ToBase64String(Encoding.UTF8.GetBytes(pair.Value))); + } + result.Append(';'); + } + return result.ToString(); + } + + /// + /// Updates the collection with a value parsed out from a given string. + /// + public static Dictionary Deserialize(string data) + { + var result = new Dictionary(); + + // if there was any input data: + if (!string.IsNullOrEmpty(data)) + { + string[] entryDescriptor = data.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var item in entryDescriptor) + { + int valueAt = item.IndexOf('='); + if (valueAt < 0) + throw new ArgumentOutOfRangeException("data", "Missing value definition in entry: \"" + item + "\""); + + var key = item.Substring(0, valueAt); + var value = item.Substring(valueAt + 1); + if (string.IsNullOrEmpty(value)) + { + result.Add(key, string.Empty); + } + else + { + if (value == "~") + result.Add(key, null); + else + result.Add(key, Encoding.UTF8.GetString(Convert.FromBase64String(value))); + } + } + } + + return result; + } + + /// + /// Appends info about the device into the dictionary. + /// + public static void AppendDevice(Dictionary data, DeviceDefinition device) + { + if (data == null) + throw new ArgumentNullException("data"); + if (device == null) + throw new ArgumentNullException("device"); + + data["target.name"] = device.Name; + data["target.IP"] = device.IP; + data["target.password"] = device.Password; + data["target.type"] = DeviceHelper.GetTypeToString(device.Type); + } + + /// + /// Gets the info about target device from the specified dictionary. + /// + public static DeviceDefinition GetDevice(Dictionary data) + { + if (data == null) + throw new ArgumentNullException("data"); + + // data about the device is missing: + if (!data.ContainsKey("target.IP") || !data.ContainsKey("target.type") || !data.ContainsKey("target.password")) + return null; + + var name = data.ContainsKey("target.name") ? data["target.name"] : "Ad-hoc device"; + + return new DeviceDefinition(name, data["target.IP"], data["target.password"], DeviceHelper.GetTypeFromString(data["target.type"], false)); + } + + /// + /// Appends info about the NDK into the dictionary. + /// + public static void AppendNDK(Dictionary data, NdkDefinition ndk) + { + if (data == null) + throw new ArgumentNullException("data"); + if (ndk == null) + throw new ArgumentNullException("ndk"); + + data["ndk.type"] = DeviceHelper.GetFamilyTypeToString(ndk.Type); + data["ndk.path.host"] = ndk.HostPath; + data["ndk.path.target"] = ndk.TargetPath; + } + + /// + /// Gets the info about NDK from the specified dictionary. + /// + public static NdkDefinition GetNDK(Dictionary data) + { + if (data == null) + throw new ArgumentNullException("data"); + + // data about the NDK is missing: + if (!data.ContainsKey("ndk.type") || !data.ContainsKey("ndk.path.host") || !data.ContainsKey("ndk.path.target")) + return null; + + return new NdkDefinition(data["ndk.path.host"], data["ndk.path.target"], DeviceHelper.GetFamilyTypeFromString(data["ndk.type"])); + } + + /// + /// Appends info about the runtime libraries into the dictionary. + /// + public static void AppendRuntime(Dictionary data, RuntimeDefinition runtime) + { + if (data == null) + throw new ArgumentNullException("data"); + if (runtime == null) + throw new ArgumentNullException("runtime"); + + data["runtime.path"] = runtime.Folder; + } + + /// + /// Gets the info about runtime libraries from the specified dictionary. + /// + public static RuntimeDefinition GetRuntime(Dictionary data) + { + if (data == null) + throw new ArgumentNullException("data"); + + if (data.ContainsKey("runtime.path")) + return new RuntimeDefinition(data["runtime.path"]); + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/Helpers/PathHelper.cs b/src_vs2012/NativeCore/Helpers/PathHelper.cs new file mode 100644 index 00000000..04195897 --- /dev/null +++ b/src_vs2012/NativeCore/Helpers/PathHelper.cs @@ -0,0 +1,88 @@ +using System; + +namespace BlackBerry.NativeCore.Helpers +{ + /// + /// Helper class for path operations. + /// + static class PathHelper + { + /// + /// Gets the last non-empty item of the path. + /// + public static string ExtractName(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + // skip last path separators: + int end = path.Length - 1; + while (end >= 0 && IsPathSeparator(path[end])) + end--; + if (end < 0) + return null; + + // locate the segment beginning: + int start = end; + while (start >= 0 && !IsPathSeparator(path[start])) + start--; + + if (start < 0) + return path.Substring(0, end + 1); + return path.Substring(start + 1, end - start); + } + + private static bool IsPathSeparator(char c) + { + return c == '/' || c == '\\'; + } + + /// + /// Gets the beginning of the path without the name. + /// + public static string ExtractDirectory(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + // skip last path separators: + int end = path.Length - 1; + while (end >= 0 && IsPathSeparator(path[end])) + end--; + if (end < 0) + return "/"; + + // locate the segment beginning: + int start = end; + while (start >= 0 && !IsPathSeparator(path[start])) + start--; + + if (start <= 0) + return "/"; + + return path.Substring(0, start); + } + + /// + /// Concatenates two path segments. + /// + public static string MakePath(string path, string name) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + + if (path[path.Length - 1] == '/') + { + if (name[0] == '/') + return path + name.Substring(1); + return path + name; + } + + if (name[0] == '/') + return path + name; + return string.Concat(path, "/", name); + } + } +} diff --git a/src_vs2012/NativeCore/Model/ApiInfo.cs b/src_vs2012/NativeCore/Model/ApiInfo.cs new file mode 100644 index 00000000..7ecdb9a8 --- /dev/null +++ b/src_vs2012/NativeCore/Model/ApiInfo.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Descriptor of a available remotely NDK. + /// + public class ApiInfo : IComparable + { + private readonly string _description; + + public ApiInfo(string name, Version version, DeviceFamilyType type) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (version == null) + throw new ArgumentNullException("version"); + + Name = name; + Version = version; + Type = type; + Level = new Version(version.Major, version.Minor); + + var versionString = Version.ToString(); + _description = Name.IndexOf(versionString, StringComparison.Ordinal) >= 0 || type == DeviceFamilyType.Tablet ? Name : string.Concat(Name, " (", versionString, ")"); + + IsBeta = !string.IsNullOrEmpty(Name) + && (Name.IndexOf("beta", StringComparison.OrdinalIgnoreCase) >= 0 || Name.IndexOf("alpha", StringComparison.InvariantCultureIgnoreCase) >= 0); + } + + #region Properties + + public string Name + { + get; + private set; + } + + public Version Version + { + get; + private set; + } + + public Version Level + { + get; + private set; + } + + public DeviceFamilyType Type + { + get; + protected set; + } + + /// + /// Gets the optional description of this API Level. + /// + public string Details + { + get; + protected set; + } + + /// + /// Checks if it is really available on current machine. + /// + public virtual bool IsInstalled + { + get { return false; } + } + + /// + /// Gets an indication, if current API is in 'beta' state. + /// + public bool IsBeta + { + get; + private set; + } + + #endregion + + /// + /// Compares the current object with another object of the same type. + /// + /// + /// A value that indicates the relative order of the objects being compared. The return value has the following meanings: Value Meaning Less than zero This object is less than the parameter.Zero This object is equal to . Greater than zero This object is greater than . + /// + /// An object to compare with this object. + public int CompareTo(ApiInfo other) + { + if (other == null) + return 1; + + int cmp = Type.CompareTo(other.Type); + if (cmp != 0) + return cmp; + + cmp = Version.CompareTo(other.Version); + if (cmp != 0) + return cmp; + + return string.Compare(Name, other.Name, StringComparison.InvariantCultureIgnoreCase); + } + + public override string ToString() + { + return _description; + } + + /// + /// Creates an instance of the API for PlayBook. + /// + public static ApiInfo CreateTabletInfo() + { + return new ApiInfo("BlackBerry Native SDK for Tablet OS 2.1.0", new Version(2, 1, 0, 1032), DeviceFamilyType.Tablet); + } + + /// + /// Creates an instance of the API to allow custom NDK insertion. + /// + public static ApiInfo CreateAddCustomInfo() + { + return new ApiInfo("Add Custom NDK", new Version(0, 0), DeviceFamilyType.Unknown); + } + + /// + /// Creates an instance of the API to allow BBNDK for VS insertion. + /// + public static ApiInfo CreateBBNDKforVSInfo() + { + return new ApiInfo("Download BBNDK for Visual Studio", new Version(0, 1), DeviceFamilyType.Unknown); + } + + /// + /// Creates an instance of the API to inform that NdkDirectory doesn't exist. + /// + public static ApiInfo CreateMissingNdkDirectoryInfo() + { + return new ApiInfo("No \"BBNDK for Visual Studio\" (bbndk_vs) folder found", new Version(), DeviceFamilyType.Unknown); + } + + /// + /// Returns an index of NdkInfo inside a collection that has the same version. + /// + public static int IndexOf(IEnumerable list, Version version) + { + if (version == null) + throw new ArgumentNullException("version"); + + if (list != null) + { + int i = 0; + foreach (var item in list) + { + if (item.Version == version) + return i; + i++; + } + } + + return -1; + } + + /// + /// Extracts the 'version' fragment out of the given directory name. Or returns 'null' in case of any problems. + /// + protected static Version GetVersionFromFolderName(string directoryName) + { + if (string.IsNullOrEmpty(directoryName)) + return null; + + int i = directoryName.Length; + + // find the version substring at the end of the name: + while (i > 0 && directoryName[i - 1] == '_' || directoryName[i - 1] == '.' || char.IsDigit(directoryName[i - 1])) + i--; + + // we might read one char too much: + if (i < directoryName.Length && !char.IsDigit(directoryName[i])) + i++; + + // parse: + var versionString = directoryName.Substring(i).Trim().Replace('_', '.'); + if (string.IsNullOrEmpty(versionString) || versionString.IndexOf('.') < 0) + return null; + + return new Version(versionString); + } + } +} diff --git a/src_vs2012/NativeCore/Model/ApiInfoArray.cs b/src_vs2012/NativeCore/Model/ApiInfoArray.cs new file mode 100644 index 00000000..a1b0c115 --- /dev/null +++ b/src_vs2012/NativeCore/Model/ApiInfoArray.cs @@ -0,0 +1,61 @@ +using System; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Wrapper class for array of API info that belong to the same API Level. + /// + public sealed class ApiInfoArray : ApiInfo + { + /// + /// Init constructor. + /// + public ApiInfoArray(string name, Version version, ApiInfo[] items) + : base(name, version, items != null && items.Length > 0 ? items[0].Type : DeviceFamilyType.Unknown) + { + Items = items ?? new ApiInfo[0]; + } + + /// + /// Init constructor. + /// + public ApiInfoArray(ApiInfo item) + : base(item != null ? item.Name : null, item != null ? item.Version : null, item != null ? item.Type : DeviceFamilyType.Unknown) + { + if (item == null) + throw new ArgumentNullException("item"); + + Items = new ApiInfo[0]; + } + + #region Properties + + public ApiInfo[] Items + { + get; + private set; + } + + /// + /// Gets the number of stored items. + /// + public int Length + { + get { return Items.Length; } + } + + #endregion + + public override bool IsInstalled + { + get + { + foreach (var item in Items) + if (!item.IsInstalled) + return false; + + return true; + } + } + } +} diff --git a/src_vs2012/NativeCore/Model/ApiLevelAction.cs b/src_vs2012/NativeCore/Model/ApiLevelAction.cs new file mode 100644 index 00000000..0cb7e406 --- /dev/null +++ b/src_vs2012/NativeCore/Model/ApiLevelAction.cs @@ -0,0 +1,11 @@ +namespace BlackBerry.NativeCore.Model +{ + /// + /// Actions to perform by Update Manager. + /// + public enum ApiLevelAction + { + Install, + Uninstall + } +} diff --git a/src_vs2012/NativeCore/Model/ApiLevelListTypes.cs b/src_vs2012/NativeCore/Model/ApiLevelListTypes.cs new file mode 100644 index 00000000..17e424e8 --- /dev/null +++ b/src_vs2012/NativeCore/Model/ApiLevelListTypes.cs @@ -0,0 +1,13 @@ +namespace BlackBerry.NativeCore.Model +{ + /// + /// Available lists of NDKs. + /// + public enum ApiLevelListTypes + { + Default, + Full, + Simulators, + Runtimes + } +} diff --git a/src_vs2012/NativeCore/Model/ApiLevelTarget.cs b/src_vs2012/NativeCore/Model/ApiLevelTarget.cs new file mode 100644 index 00000000..df730046 --- /dev/null +++ b/src_vs2012/NativeCore/Model/ApiLevelTarget.cs @@ -0,0 +1,12 @@ +namespace BlackBerry.NativeCore.Model +{ + /// + /// Targets processed by Update Manager. + /// + public enum ApiLevelTarget + { + NDK, + Simulator, + Runtime + } +} diff --git a/src_vs2012/NativeCore/Model/ApiLevelTask.cs b/src_vs2012/NativeCore/Model/ApiLevelTask.cs new file mode 100644 index 00000000..e8033176 --- /dev/null +++ b/src_vs2012/NativeCore/Model/ApiLevelTask.cs @@ -0,0 +1,41 @@ +namespace BlackBerry.NativeCore.Model +{ + /// + /// Enumeration describing, what action can be performed over specified API Level. + /// + public enum ApiLevelTask + { + /// + /// Nothing can be done with this API Level (it was installed separately and just detected). + /// + Nothing = 0, + /// + /// New API Level can be installed. + /// + Install, + /// + /// Installation of the API Level must be done manually (specified URL should be opened in a browser). + /// + InstallManually, + /// + /// Installation of the API Level was already done, but not detected automatically. + /// + AddExisting, + /// + /// Installed API Level, owned by the plugin, can be removed. + /// + Uninstall, + /// + /// Link added by the developer to custom API Level (installed NDK), can be just removed. + /// + Forget, + /// + /// No action is allowed to be performed. + /// + Hide, + /// + /// Data is out-dated and needs to be reloaded. + /// + Refresh + } +} diff --git a/src_vs2012/NativeCore/Model/AuthorInfo.cs b/src_vs2012/NativeCore/Model/AuthorInfo.cs new file mode 100644 index 00000000..fafe86fb --- /dev/null +++ b/src_vs2012/NativeCore/Model/AuthorInfo.cs @@ -0,0 +1,42 @@ +namespace BlackBerry.NativeCore.Model +{ + /// + /// Class describing the info about BAR file author (publisher). + /// + public sealed class AuthorInfo + { + /// + /// Init constructor. + /// Null values are accepted as this is something from user's input. + /// + public AuthorInfo(string id, string name) + { + ID = id; + Name = name; + } + + #region Properties + + public string ID + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + #endregion + + /// + /// Returns a string that represents the current object. + /// + public override string ToString() + { + return string.Concat(Name, " (", ID, ")"); + } + } +} diff --git a/src_vs2012/NativeCore/Model/CertificateInfo.cs b/src_vs2012/NativeCore/Model/CertificateInfo.cs new file mode 100644 index 00000000..6ca392b0 --- /dev/null +++ b/src_vs2012/NativeCore/Model/CertificateInfo.cs @@ -0,0 +1,268 @@ +using System; +using System.Globalization; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Class describing developer's certificate. + /// + public sealed class CertificateInfo + { + private CertificateInfo() + { + } + + public CertificateInfo(string alias, string subjectName, string issuer, string algorithm, string fingerprintSHA1, string fingerprintMD5) + { + Alias = alias; + SubjectName = subjectName; + Issuer = issuer; + Algorithm = algorithm; + FingerprintSHA1 = fingerprintSHA1; + FingerprintMD5 = fingerprintMD5; + } + + #region Properties + + public string Alias + { + get; + private set; + } + + public string SerialNumber + { + get; + private set; + } + + public string SubjectName + { + get; + private set; + } + + public string Issuer + { + get; + private set; + } + + public DateTime ValidFrom + { + get; + private set; + } + + public DateTime ValidTo + { + get; + private set; + } + + public string Algorithm + { + get; + private set; + } + + public string PublicKey + { + get; + private set; + } + + public string FingerprintSHA1 + { + get; + private set; + } + + public string FingerprintMD5 + { + get; + private set; + } + + #endregion + + /// + /// Extracts certificate info out of given text. + /// + public static CertificateInfo Parse(string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + /* +Found 1 private key +Found 1 certificate: + Alias: + author + Serial Number: + aa:bb:cc:dd + Subject Name: + CommonName=XyXyXyXyXyXy + Issuer Name: + CommonName=XyXyXyXyXyXy + Valid From: + Thu Oct 18 22:25:41 CEST 2012 + Valid To: + Wed Oct 13 22:25:41 CEST 2032 + Public Key: + ECC-SECP521R1 + Signature Algorithm: + SHA512withECDSA + SHA1 Fingerprint: + aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:00:11:22:33:44:55:66:77 + MD5 Fingerprint: + 00:11:22:33:44:55:66:77:88:99:00:11:22:33:44:55 + */ + + var lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + + // remove white chars... + for (int i = 0; i < lines.Length; i++) + { + lines[i] = lines[i].Trim(); + } + + var result = new CertificateInfo(); + + // do the parsing: + // - assuming that n-line has header and n+1 - data + for (int i = 0; i < lines.Length - 1; i++) + { + if (string.Compare("alias:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.Alias = lines[++i]; + continue; + } + if (string.Compare("serial number:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.SerialNumber = lines[++i]; + continue; + } + if (string.Compare("subject name:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.SubjectName = GetCommonName(lines[++i]); + continue; + } + if (string.Compare("issuer name:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.Issuer = GetCommonName(lines[++i]); + continue; + } + if (string.Compare("valid from:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.ValidFrom = ParseDate(lines[++i]); + continue; + } + if (string.Compare("valid to:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.ValidTo = ParseDate(lines[++i]); + continue; + } + if (string.Compare("signature algorithm:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.Algorithm = lines[++i]; + continue; + } + if (string.Compare("public key:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.PublicKey = lines[++i]; + continue; + } + if (string.Compare("md5 fingerprint:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.FingerprintMD5 = lines[++i]; + continue; + } + if (string.Compare("sha1 fingerprint:", lines[i], StringComparison.InvariantCultureIgnoreCase) == 0) + { + result.FingerprintSHA1 = lines[++i]; + continue; + } + } + + // verify if at least some basic fields are set, + // then return the result, else treat everything as parsing failure: + return string.IsNullOrEmpty(result.Issuer) ? null : result; + } + + private static string GetCommonName(string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + if (text.StartsWith("CommonName=", StringComparison.InvariantCultureIgnoreCase)) + return "CN=" + text.Substring(11); + + return text; + } + + /// + /// Parses the date out of given text. + /// + internal static DateTime ParseDate(string text) + { + DateTime date; + + return TryParseDate(text, out date) ? date : date; + } + + /// + /// Tries to parse the date from specified string. + /// + internal static bool TryParseDate(string text, out DateTime result) + { + string timeZoneName; + + text = RemoveTimeZone(text, out timeZoneName); + if (string.IsNullOrEmpty(text)) + { + result = DateTime.MinValue.ToUniversalTime(); + return false; + } + + var culture = CultureInfo.GetCultureInfo("en-US"); + var timeZoneShift = GetTimeZoneShift(timeZoneName); + + // Thu Oct 18 22:25:41 2012 + if (!DateTime.TryParseExact(text, + new[] { "ddd MMM d HH:mm:ss yyyy", "ddd MMM dd HH:mm:ss yyyy" }, + culture, DateTimeStyles.AssumeLocal, + out result)) + return false; + + result = result.Subtract(timeZoneShift).ToUniversalTime(); + return true; + } + + private static TimeSpan GetTimeZoneShift(string timeZoneName) + { + // PH: TODO: implement proper time-zone shift detection + // like for CEST -> +2:00 + // and change the parsing code to use AssumeUniversal instead of AssumeLocal + return new TimeSpan(0, 0, 0); + } + + private static string RemoveTimeZone(string text, out string timeZoneName) + { + timeZoneName = null; + if (string.IsNullOrEmpty(text)) + return null; + + // find text between last two spaces: + int endIndex = text.LastIndexOf(' '); + if (endIndex <= 0) + return text; + int startIndex = text.LastIndexOf(' ', endIndex - 1); + if (startIndex < 0) + return text; + + timeZoneName = text.Substring(startIndex + 1, endIndex - startIndex - 1); + return string.Concat(text.Substring(0, startIndex), text.Substring(endIndex)); + } + } +} diff --git a/src_vs2012/NativeCore/Model/CskTokenInfo.cs b/src_vs2012/NativeCore/Model/CskTokenInfo.cs new file mode 100644 index 00000000..d7fd1b3b --- /dev/null +++ b/src_vs2012/NativeCore/Model/CskTokenInfo.cs @@ -0,0 +1,202 @@ +using System; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Class describing BlackBerry ID token. + /// + public sealed class CskTokenInfo + { + private CskTokenInfo() + { + } + + /// + /// Init constructor. + /// + public CskTokenInfo(string content) + { + Content = content; + Parse(content, this); + } + + #region Properties + + /// + /// Gets the whole content of the token data. + /// + public string Content + { + get; + private set; + } + + public bool HasContent + { + get { return !string.IsNullOrEmpty(Content); } + } + + public DateTime CreatedAt + { + get; + private set; + } + + public DateTime ValidTo + { + get; + private set; + } + + /// + /// Gets an indication, if the token is still valid. + /// + public bool IsValid + { + get { return DateTime.UtcNow < ValidTo; } + } + + /// + /// Gets the string representation of the creation date. + /// + public string CreatedAtString + { + get { return CreatedAt.ToString("yyyy-MM-dd HH:mm:ss"); } + } + + /// + /// Gets the string representation of the validation date. + /// + public string ValidDateString + { + get { return ValidTo.ToString("yyyy-MM-dd"); } + } + + /// + /// Gets the number of days passed after the token validation date. + /// + public int ExpirationDays + { + get + { + if (IsValid) + return 0; + if (ValidTo == DateTime.MinValue) + return 365; + + var diff = DateTime.UtcNow - ValidTo; + return (int) diff.TotalDays; + } + } + + public string HMAC + { + get; + private set; + } + + public string Version + { + get; + private set; + } + + public string Token + { + get; + private set; + } + + public string Company + { + get; + private set; + } + + #endregion + + /// + /// Loads token info from specified file. + /// + public static CskTokenInfo Load(string fileName) + { + if (string.IsNullOrEmpty(fileName)) + return null; + + try + { + return Parse(File.ReadAllText(fileName)); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load file: \"{0}\"", fileName); + return null; + } + } + + /// + /// Extracts token info from a text content. + /// + public static CskTokenInfo Parse(string text) + { + return Parse(text, new CskTokenInfo()); + } + + /// + /// Updates token info from a text content inside given result. + /// + private static CskTokenInfo Parse(string text, CskTokenInfo result) + { + if (string.IsNullOrEmpty(text)) + return null; + + var lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var line in lines) + { + // date from comment: + if (line.Length > 0 && line[0] == '#') + { + DateTime date; + if (CertificateInfo.TryParseDate(line.Substring(1), out date)) + { + result.CreatedAt = date; + result.ValidTo = date.Date.AddYears(1); // BBID token is valid only for one year! + continue; + } + } + + // HMAC: + if (line.StartsWith("hmac=", StringComparison.InvariantCultureIgnoreCase)) + { + result.HMAC = line.Substring(5).Trim(); + continue; + } + + // version: + if (line.StartsWith("version=", StringComparison.InvariantCultureIgnoreCase)) + { + result.Version = line.Substring(8).Trim(); + continue; + } + + // token: + if (line.StartsWith("token=", StringComparison.InvariantCultureIgnoreCase)) + { + result.Token = line.Substring(6).Trim(); + continue; + } + + // company: + if (line.StartsWith("company=", StringComparison.InvariantCultureIgnoreCase)) + { + result.Company = line.Substring(8).Trim(); + continue; + } + } + + return result; + } + } +} diff --git a/src_vs2012/NativeCore/Model/DebugTokenInfo.cs b/src_vs2012/NativeCore/Model/DebugTokenInfo.cs new file mode 100644 index 00000000..795e7213 --- /dev/null +++ b/src_vs2012/NativeCore/Model/DebugTokenInfo.cs @@ -0,0 +1,350 @@ +using System; +using System.Text; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Model data describing info about debug token. + /// + public sealed class DebugTokenInfo + { + private string _description; + + public DebugTokenInfo() + { + SystemActions = new string[0]; + Devices = new ulong[0]; + } + + #region Properties + + public string ID + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public Version Version + { + get; + private set; + } + + public string VersionID + { + get; + private set; + } + + public AuthorInfo Author + { + get; + private set; + } + + public string AuthorCertificateHash + { + get; + private set; + } + + public string[] SystemActions + { + get; + private set; + } + + public ulong[] Devices + { + get; + private set; + } + + public DateTime IssueDate + { + get; + private set; + } + + public DateTime ExpiryDate + { + get; + private set; + } + + #endregion + + /// + /// Checks, whether this debug token is build against specified device. + /// + public bool Contains(ulong device) + { + if (device == 0) + return false; + if (Devices == null || Devices.Length == 0) + return false; + + for (int i = 0; i < Devices.Length; i++) + { + if (device == Devices[i]) + return true; + } + + return false; + } + + + public override string ToString() + { + if (_description == null) + _description = GetDescription(); + + return _description; + } + + /// + /// Gets the long description summary of the debug token. + /// + public string ToLongDescription(bool mostImportantOnly) + { + var result = new StringBuilder(); + + if (!mostImportantOnly) + { + result.Append("Name: ").Append(Name).Append(" (").Append(ID).AppendLine(")"); + if (Author != null) + { + result.Append("Author: ").AppendLine(Author.Name); + } + } + + // print dates: + if (ExpiryDate != DateTime.MinValue) + result.Append("Expiry Date: ").AppendLine(ExpiryDate.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")); + if (!mostImportantOnly) + { + if (IssueDate != DateTime.MinValue) + result.Append("Issue Date: ").AppendLine(IssueDate.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")); + result.Append("Version: ").Append(Version).Append(" (ID: ").Append(VersionID).AppendLine(")"); + } + + // print affected devices: + if (mostImportantOnly && Devices.Length > 0) + { + result.Append("Devices: "); + int i = 0; + foreach (var device in Devices) + { + if (i > 0) + result.Append(", "); + result.Append(device.ToString("X")); + i++; + } + result.AppendLine(); + } + + if (mostImportantOnly) + { + if (Author != null) + { + result.Append("Author: ").AppendLine(Author.Name); + result.Append("Author ID: ").AppendLine(Author.ID); + } + + result.AppendLine(); + result.Append("App ID: ").AppendLine(ID); + result.Append("App Name: ").AppendLine(Name); + result.Append("App Version: ").Append(Version).Append(" (").Append(VersionID).AppendLine(")"); + } + + // print system actions allowed: + if (mostImportantOnly && SystemActions.Length > 0) + { + result.AppendLine(); + result.Append("Actions: "); + + int i = 0; + foreach (var action in SystemActions) + { + if (i > 0) + result.Append(", "); + result.Append(action); + i++; + } + result.AppendLine(); + } + + return result.ToString(); + } + + private string GetDescription() + { + var result = new StringBuilder(); + + if (Author != null) + { + result.Append(!string.IsNullOrEmpty(Author.Name) ? Author.Name : Author.ID); + } + result.Append(" ("); + result.Append(ExpiryDate.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")); + + // serialize list of device PINs as hexadecimal values: + if (Devices.Length > 0) + { + result.Append(", "); + for (int i = 0; i < Devices.Length; i++) + { + if (i > 0) + result.Append(","); + result.Append(Devices[i].ToString("X")); + } + } + + result.Append(")"); + return result.ToString(); + } + + /// + /// Creates new instance of the DebugTokenInfo based on specified data, or null if data is invalid. + /// + public static DebugTokenInfo Parse(string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + var items = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + DebugTokenInfo result = new DebugTokenInfo(); + bool isDebugToken = false; + string authorName = null; + string authorID = null; + + foreach (var line in items) + { + string key; + string value; + + if (SplitLine(line, out key, out value)) + { + switch (key) + { + case "package-id": + result.ID = value; + break; + case "package-type": + isDebugToken = string.CompareOrdinal("debug-token", value) == 0; + break; + case "package-name": + result.Name = value; + break; + case "package-version": + result.Version = new Version(value); + break; + case "package-version-id": + result.VersionID = value; + break; + case "package-author": + authorName = value; + break; + case "package-author-id": + authorID = value; + break; + case "package-author-certificate-hash": + result.AuthorCertificateHash = value; + break; + case "debug-token-system-actions": + result.SystemActions = ParseSystemActions(value); + break; + case "debug-token-device-id": + result.Devices = ParseDevices(value); + break; + case "package-issue-date": + result.IssueDate = ParseDate(value); + break; + case "debug-token-expiry-date": + result.ExpiryDate = ParseDate(value); + break; + } + } + } + + if (!string.IsNullOrEmpty(authorID) || !string.IsNullOrEmpty(authorName)) + { + result.Author = new AuthorInfo(authorID, authorName); + } + + return !isDebugToken || string.IsNullOrEmpty(result.ID) || result.Author == null ? null : result; + } + + private static string[] ParseSystemActions(string text) + { + if (string.IsNullOrEmpty(text)) + return new string[0]; + + // convert comma-separated items into an array of strings: + var items = text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < items.Length; i++) + { + items[i] = items[i].Trim(); + } + + return items; + } + + private static ulong[] ParseDevices(string text) + { + if (string.IsNullOrEmpty(text)) + return new ulong[0]; + + // convert comma-separated items into an array of numbers: + var items = text.Split(new[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); + var deviceIDs = new ulong[items.Length]; + + for (int i = 0; i < items.Length; i++) + { + deviceIDs[i] = DeviceInfo.ParseDeviceId(items[i]); + } + + Array.Sort(deviceIDs); + return deviceIDs; + } + + private static DateTime ParseDate(string text) + { + DateTime result; + + if (!string.IsNullOrEmpty(text) && DateTime.TryParse(text, out result)) + return result.ToUniversalTime(); + + return DateTime.MinValue.ToUniversalTime(); + } + + private static bool SplitLine(string line, out string key, out string value) + { + if (string.IsNullOrEmpty(line)) + { + key = null; + value = null; + return false; + } + + // check if following format: : + int separatorIndex = line.IndexOf(": ", StringComparison.CurrentCulture); + if (separatorIndex < 0) + { + key = null; + value = null; + return false; + } + + key = line.Substring(0, separatorIndex).Trim().ToLower(); + value = line.Substring(separatorIndex + 2).Trim(); + return true; + } + } +} diff --git a/src_vs2012/NativeCore/Model/DeveloperDefinition.cs b/src_vs2012/NativeCore/Model/DeveloperDefinition.cs new file mode 100644 index 00000000..af848de0 --- /dev/null +++ b/src_vs2012/NativeCore/Model/DeveloperDefinition.cs @@ -0,0 +1,918 @@ +using System; +using System.IO; +using System.IO.Packaging; +using System.Text; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.Tools; +using Microsoft.Win32; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Short settings about developer doing the development. + /// + public sealed class DeveloperDefinition + { + /// + /// Default name of the certificate file. + /// + public const string DefaultCertificateName = "author.p12"; + private const string DefaultCskTokenName = "bbidtoken.csk"; + private const string DefaultTabletSignerName = "barsigner.db"; + private const string DefaultTabletCskTokenName = "barsigner.csk"; + private const string FieldCertificateFileName = "certificate"; + + private const string FieldCskPassword = "CSKPass"; + private const string FieldCachedAuthorID = "CachedAuthorID"; + private const string FieldCachedAuthorName = "CachedAuthorName"; + + private string _name; + private AuthorInfo _cachedAuthor; + private CskTokenInfo _cskToken; + private CskTokenInfo _cskTabletToken; + + public DeveloperDefinition(string dataPath, string certificatePath, string cskPassword, AuthorInfo authorInfo) + { + if (string.IsNullOrEmpty(dataPath)) + throw new ArgumentNullException("dataPath"); + + DataPath = dataPath; + CertificateFileName = certificatePath ?? DefaultCertificateName; + CskPassword = cskPassword; + _cachedAuthor = authorInfo; + } + + #region Properties + + /// + /// Gets the name of the developer (publisher). + /// + public string Name + { + get + { + if (string.IsNullOrEmpty(_name) && HasPassword) + { + // get the author from certificate: + _name = LoadIssuer(CertificateFullPath, CskPassword); + } + + return _name; + } + private set { _name = value; } + } + + /// + /// Gets the indication, if a name was loaded for this developer (publisher) from a certificate. + /// + public bool HasName + { + get { return !string.IsNullOrEmpty(Name); } + } + + /// + /// Gets the location, where all developer configuration files are stored. + /// + public string DataPath + { + get; + private set; + } + + /// + /// Gets the name of certificate file (author.p12). + /// + public string CertificateFileName + { + get; + private set; + } + + /// + /// Gets the full path to the developers certificate. + /// + public string CertificateFullPath + { + get { return string.IsNullOrEmpty(CertificateFileName) ? null : Path.Combine(DataPath, CertificateFileName); } + } + + /// + /// Gets an indication, if the certificate file exists. + /// + public bool HasCertificate + { + get { return !string.IsNullOrEmpty(CertificateFileName) && File.Exists(CertificateFullPath); } + } + + /// + /// Gets full path to the BlackBerry ID token file (bbidtoken.csk). + /// + public string CskTokenFullPath + { + get { return Path.Combine(DataPath, DefaultCskTokenName); } + } + + /// + /// Gets full path do the BlackBerry Tablet Signer Authority file (barsigner.db). + /// + public string TabletSignerFullPath + { + get { return Path.Combine(DataPath, DefaultTabletSignerName); } + } + + /// + /// Gets full path to the BlackBerry Tablet CSK token file (barsigner.csk). + /// + public string TabletCskTokenFullPath + { + get { return Path.Combine(DataPath, DefaultTabletCskTokenName); } + } + + /// + /// Gets the BlackBerry ID token information. + /// + public CskTokenInfo Token + { + get + { + if (_cskToken == null) + _cskToken = CskTokenInfo.Load(CskTokenFullPath); + + return _cskToken; + } + private set { _cskToken = value; } + } + + /// + /// Gets the BlackBerry Tablet token information. + /// + public CskTokenInfo TabletToken + { + get + { + if (_cskTabletToken == null) + _cskTabletToken = CskTokenInfo.Load(TabletCskTokenFullPath); + + return _cskTabletToken; + } + private set { _cskTabletToken = value; } + } + + /// + /// Gets an indication, if BlackBerry ID token exists. + /// + public bool HasToken + { + get { return File.Exists(CskTokenFullPath) && Token != null; } + } + + /// + /// Gets an indication, if BlackBerry Tablet token exists. + /// + public bool HasTabletToken + { + get { return File.Exists(TabletCskTokenFullPath) && TabletToken != null; } + } + + /// + /// Password set by developer to the certificate. + /// + public string CskPassword + { + get; + private set; + } + + /// + /// Checks, if CskPassword is setup. + /// + public bool HasPassword + { + get { return !string.IsNullOrEmpty(CskPassword); } + } + + /// + /// Checks if developer completed any kind of registration. + /// + public bool IsRegistered + { + get { return IsBB10Registered || IsTabletRegistered; } + } + + /// + /// Checks if developer completed BB10 registration. + /// + public bool IsBB10Registered + { + get { return HasCertificate && File.Exists(CskTokenFullPath); } + } + + /// + /// Checks if developer completed tablet registration. + /// + public bool IsTabletRegistered + { + get + { + return HasCertificate + && File.Exists(TabletCskTokenFullPath) + && File.Exists(TabletSignerFullPath) && GetFileSize(TabletSignerFullPath) > 0; + } + } + + /// + /// Gets the cached info about author (publisher). + /// This is data put directly inside bar-descriptor.xml files and usually obtained, when creating debug-tokens. + /// + public AuthorInfo CachedAuthor + { + get { return _cachedAuthor; } + set + { + if (value == null) + { + DeleteCachedAuthorInfo(); + _cachedAuthor = null; + } + else + { + // is there anything new? + if (_cachedAuthor != null && string.CompareOrdinal(value.ID, _cachedAuthor.ID) == 0 && string.CompareOrdinal(value.Name, _cachedAuthor.Name) == 0) + { + return; + } + + _cachedAuthor = value; + SaveCachedAuthorInfo(value); + } + } + } + + #endregion + + /// + /// Gets the size of the file. + /// + private static long GetFileSize(string path) + { + try + { + var info = new FileInfo(path); + return info.Length; + } + catch + { + return 0; + } + } + + /// + /// Invalidates loaded CSK tokens to force them load from disk again. + /// + public void InvalidateTokens() + { + Token = null; + TabletToken = null; + } + + /// + /// Updates stored CSK password to a new value. + /// + public void UpdatePassword(string password, bool remember) + { + CskPassword = password; + if (remember) + SavePassword(); + } + + /// + /// Tries to reload issuer from the certificate. + /// + public string UpdateName(string password) + { + return Name = LoadIssuer(CertificateFullPath, string.IsNullOrEmpty(password) ? CskPassword : password); + } + + /// + /// Stores password into registry. + /// + public void SavePassword() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + if (CskPassword == null) + CskPassword = string.Empty; + + settings.SetValue(FieldCskPassword, GlobalHelper.Encrypt(CskPassword)); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Checks, if the CSK password is stored in registry. + /// + public bool IsPasswordSaved + { + get + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.OpenSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return false; + + if (CskPassword == null) + CskPassword = string.Empty; + + return settings.GetValue(FieldCskPassword, null) != null; + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + } + + /// + /// Removes password stored inside registry and cached in this class. + /// + public void ClearPassword() + { + DeletePassword(); + CskPassword = null; + } + + /// + /// Removes password stored inside registry. + /// + public static void DeletePassword() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.DeleteValue(FieldCskPassword, false); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Updates path to the certificate inside the registry. + /// + private void SaveCertificatePath() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + if (string.Compare(DefaultCertificateName, CertificateFileName, StringComparison.InvariantCultureIgnoreCase) == 0) + settings.DeleteValue(FieldCertificateFileName, false); + else + settings.SetValue(FieldCertificateFileName, CertificateFileName); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Removes certificate path from registry. + /// + private void DeleteCertificatePath() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.DeleteValue(FieldCertificateFileName, false); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Updates the certificate file name and save it into the registry. + /// + public void UpdateCertificate(string fileName) + { + var folder = Path.GetDirectoryName(fileName); + + if (!string.IsNullOrEmpty(folder)) + throw new ArgumentOutOfRangeException("fileName", "Invalid name, folder is not expected inside, only file name"); + if (!File.Exists(Path.Combine(DataPath, fileName))) + throw new ArgumentOutOfRangeException("fileName", "File doesn't existing in designated certificate storage"); + + ClearPassword(); + CertificateFileName = fileName; + Name = null; + + if (string.Compare(fileName, DefaultCertificateName, StringComparison.InvariantCultureIgnoreCase) == 0) + { + DeleteCertificatePath(); + } + else + { + SaveCertificatePath(); + } + } + + /// + /// Updates the certificate file name and password and saves it into registry if required. + /// + public void UpdateCertificate(string fileName, string password, bool remember) + { + UpdateCertificate(fileName); + UpdatePassword(password, remember); + UpdateName(null); + } + + /// + /// Creates new developer-definition object based on info read from registry and around. + /// + public static DeveloperDefinition Load(string dataPath) + { + if (string.IsNullOrEmpty(dataPath)) + throw new ArgumentNullException("dataPath"); + + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings; + + string certificateFileName = null; + string cskPassword = null; + string authorID = null; + string authorName = null; + AuthorInfo authorInfo = null; + + try + { + settings = registry.OpenSubKey(ConfigDefaults.RegistryPath); + } + catch + { + // no device definition + return null; + } + if (settings == null) + return null; + + // CERTIFICATE + try + { + object xCertificate = settings.GetValue(FieldCertificateFileName); + if (xCertificate != null) + certificateFileName = xCertificate.ToString(); + } + catch + { + } + // set default, if loading failed: + if (string.IsNullOrEmpty(certificateFileName)) + certificateFileName = DefaultCertificateName; + + // PASSWORD + try + { + object xPassword = settings.GetValue(FieldCskPassword); + if (xPassword != null) + cskPassword = GlobalHelper.Decrypt(xPassword.ToString()); + } + catch + { + } + + // CACHED AUTHOR ID + NAME + try + { + object xAuthorID = settings.GetValue(FieldCachedAuthorID); + if (xAuthorID != null) + authorID = xAuthorID.ToString(); + + object xAuthorName = settings.GetValue(FieldCachedAuthorName); + if (xAuthorName != null) + authorName = xAuthorName.ToString(); + } + catch + { + } + + settings.Close(); + registry.Close(); + + // having author info with any value set as non-'null' is OK, as it comes from caches... + if (!string.IsNullOrEmpty(authorID) || !string.IsNullOrEmpty(authorName)) + { + authorInfo = new AuthorInfo(authorID, authorName); + } + + return new DeveloperDefinition(dataPath, certificateFileName, cskPassword, authorInfo); + } + + /// + /// Loads 'issuer' field from the X.509 certificate. + /// + public static string LoadIssuer(string certificateFileName, string password) + { + try + { + if (!File.Exists(certificateFileName) || string.IsNullOrEmpty(password)) + return null; + + /* PH: OK - this did work, but not for WinXP, as this one doesn't support SHA512withECDSA algorithm... + var cert = new X509Certificate(certificateFileName, password); + var issuer = cert.Issuer; + */ + string issuer; + using (var runner = new KeyToolInfoRunner(certificateFileName, password)) + { + // invoke + if (!runner.Execute()) + return null; + if (runner.Info == null) + return null; + + // grab results: + issuer = runner.Info.Issuer; + } + + if (issuer != null && issuer.StartsWith("CN=", StringComparison.InvariantCultureIgnoreCase)) + issuer = issuer.Substring(3).Trim(); + if (issuer != null && issuer.StartsWith("CommonName=", StringComparison.InvariantCultureIgnoreCase)) + issuer = issuer.Substring(11).Trim(); + + return issuer; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to read data from certificate: \"{0}\"", certificateFileName); + return null; + } + } + + /// + /// Removes info about cached author (publisher) from registry. + /// + private static void DeleteCachedAuthorInfo() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.DeleteValue(FieldCachedAuthorID, false); + settings.DeleteValue(FieldCachedAuthorName, false); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Stores info about specified author (publisher) inside registry. + /// + private static void SaveCachedAuthorInfo(AuthorInfo info) + { + if (info == null) + throw new ArgumentNullException("info"); + + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + // id + if (string.IsNullOrEmpty(info.ID)) + settings.DeleteValue(FieldCachedAuthorID, false); + else + settings.SetValue(FieldCachedAuthorID, info.ID); + + // name + if (string.IsNullOrEmpty(info.Name)) + settings.DeleteValue(FieldCachedAuthorName, false); + else + settings.SetValue(FieldCachedAuthorName, info.Name); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Gets the list of files, that are assumed to be a developer profile for signing applications. + /// + private string[] GetProfileFiles() + { + return new[] { CertificateFileName, DefaultCskTokenName, "bbsigner.csk", + "bb_id_rsa", "bb_id_rsa.pub", + + // and files for PlayBook tablet: + DefaultTabletCskTokenName, DefaultTabletSignerName, + "bbt_id_rsa", "bbt_id_rsa.pub"}; + } + + /// + /// Saves all developer profile info into specified file. + /// + public bool BackupProfile(string outputFile) + { + if (string.IsNullOrEmpty(outputFile)) + return false; + + var fileNames = GetProfileFiles(); + + try + { + using (var package = Package.Open(outputFile, FileMode.Create)) + { + foreach (var name in fileNames) + { + Append(package, name, Path.Combine(DataPath, name)); + } + } + + return true; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to export profile to file: \"{0}\"", outputFile); + return false; + } + } + + /// + /// Appends file to the ZIP package. + /// + private static void Append(Package package, string name, string fullPathName) + { + if (File.Exists(fullPathName)) + { + Uri uri = PackUriHelper.CreatePartUri(new Uri(name, UriKind.Relative)); + PackagePart part = package.CreatePart(uri, string.Empty); + + if (part != null) + { + using (var fileStream = new FileStream(fullPathName, FileMode.Open, FileAccess.Read)) + { + CopyStream(fileStream, part.GetStream()); + } + } + } + } + + /// + /// Copy a stream from one stream to another. + /// + private static void CopyStream(Stream source, Stream target) + { + if (source == null) + throw new ArgumentNullException("source"); + if (target == null) + throw new ArgumentNullException("target"); + + var buffer = new byte[0x1000]; + int bytesRead; + + while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) + { + target.Write(buffer, 0, bytesRead); + } + } + + /// + /// Extracts the developer profile. + /// + public bool RestoreProfile(string inputFile) + { + if (string.IsNullOrEmpty(inputFile)) + return false; + + if (File.Exists(inputFile)) + { + string p12FileName = null; + + try + { + // make the password invalid: + DeletePassword(); + Token = null; + + // extract all files that are within the backup package: + using (var package = Package.Open(inputFile, FileMode.Open, FileAccess.ReadWrite)) + { + foreach (var part in package.GetParts()) + { + var name = ExtractFile(part, DataPath); + if (name != null && name.EndsWith(".p12")) + { + p12FileName = Path.GetFileName(name); + } + } + } + + // no certificate found inside? + if (string.IsNullOrEmpty(p12FileName)) + return false; + + // update save it for future reference: + CertificateFileName = p12FileName; + SaveCertificatePath(); + return true; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Impossible to restore profile: \"{0}\"", inputFile); + return false; + } + } + + return false; + } + + /// + /// Extract file under specified directory. + /// + public static string ExtractFile(PackagePart part, string folder) + { + // initially create file under the folder specified + string filePath = part.Uri.OriginalString.Replace('/', Path.DirectorySeparatorChar); + + // remove trailing directory separator: + if (!string.IsNullOrEmpty(filePath) && filePath[0] == Path.DirectorySeparatorChar) + { + filePath = filePath.TrimStart(Path.DirectorySeparatorChar); + } + + filePath = Path.Combine(folder, filePath); + var dirName = Path.GetDirectoryName(filePath); + if (!string.IsNullOrEmpty(dirName)) + { + Directory.CreateDirectory(dirName); + } + + // extract file: + using (var output = File.Create(filePath)) + { + CopyStream(part.GetStream(), output); + } + + return filePath; + } + + /// + /// Writes a BlackBerry ID token file. + /// + public void SaveCskToken(CskTokenInfo token) + { + // update stored token in memory: + Token = token; + + // and on disk: + var fileName = CskTokenFullPath; + + if (File.Exists(fileName)) + File.Delete(fileName); + + if (token.HasContent) + { + File.WriteAllText(fileName, token.Content); + } + } + + /// + /// Delete all files that belong to the developer profile. + /// Removes its password etc. + /// + public void DeleteProfile() + { + var files = GetProfileFiles(); + + foreach (var fileName in files) + { + var fullName = Path.Combine(DataPath, fileName); + if (File.Exists(fullName)) + File.Delete(fullName); + } + + DeleteCertificatePath(); + ClearPassword(); + CertificateFileName = DefaultCertificateName; + Name = null; + Token = null; + } + + /// + /// Removes some profile temporary files, that are not needed anymore, when registration process completed. + /// + public void CleanupProfile() + { + // if there is no certificate file, means all generators failed, + // so remove all other remaining files... + if (!File.Exists(CertificateFullPath)) + { + DeleteProfile(); + } + } + + /// + /// Gets long description in human readable format. + /// + public string ToLongStatusDescription() + { + var result = new StringBuilder(); + + result.AppendLine("Status:"); + result.Append(" * BlackBerry 10 - ").AppendLine(IsBB10Registered ? "Registered" : (IsTabletRegistered ? "using tablet certificates" : "Unregistered")); + if (HasToken) + { + if (Token.IsValid) + result.Append(" > Token expires on ").AppendLine(Token.ValidDateString); + else + result.Append(" > Token expired ").Append(Token.ExpirationDays).AppendLine(" days ago"); + } + result.Append(" * PlayBook - ").AppendLine(IsTabletRegistered ? "Registered" : "Unregistered"); + + if (IsPasswordSaved) + result.AppendLine(" * password is stored"); + + return result.ToString(); + } + + /// + /// Gets short description in human readable format. + /// + public string ToShortStatusDescription() + { + var result = new StringBuilder(); + + result.Append("BB10: ").AppendLine(IsBB10Registered ? "Registered" : (IsTabletRegistered ? "using tablet certificates" : "Unregistered")); + if (HasToken) + { + if (Token.IsValid) + result.Append(" (Token expires on ").Append(Token.ValidDateString).AppendLine(")"); + else + result.Append(" (Token expired ").Append(Token.ExpirationDays).AppendLine(" days ago)"); + } + result.Append("PlayBook: ").Append(IsTabletRegistered ? "Registered" : "Unregistered"); + + return result.ToString(); + } + } +} diff --git a/src_vs2012/NativeCore/Model/DeviceDebugTokenInfo.cs b/src_vs2012/NativeCore/Model/DeviceDebugTokenInfo.cs new file mode 100644 index 00000000..6c408bfc --- /dev/null +++ b/src_vs2012/NativeCore/Model/DeviceDebugTokenInfo.cs @@ -0,0 +1,114 @@ +using System; +using System.Text; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Description of the debug-token stored on the device. + /// + public sealed class DeviceDebugTokenInfo + { + private string _description; + + #region Properties + + public DeviceDebugTokenInfo(string author, DateTime expiryDate, bool isValid, bool isInstalled, string validationErrorMessage, uint validationErrorCode) + { + // error code must be provided with a suitable message: + if (validationErrorCode > 0 && string.IsNullOrEmpty(validationErrorMessage)) + throw new ArgumentOutOfRangeException("validationErrorMessage", "Expected non empty message for non-zero error code"); + + Author = author; + ExpiryDate = expiryDate; + IsValid = isValid; + IsInstalled = isInstalled; + ValidationErrorMessage = validationErrorMessage; + ValidationErrorCode = validationErrorCode; + } + + public string Author + { + get; + private set; + } + + public DateTime ExpiryDate + { + get; + private set; + } + + public bool IsValid + { + get; + private set; + } + + public bool IsInstalled + { + get; + private set; + } + + public string ValidationErrorMessage + { + get; + private set; + } + + public uint ValidationErrorCode + { + get; + private set; + } + + #endregion + + public override string ToString() + { + if (_description == null) + _description = GetDescription(); + + return _description; + } + + /// + /// Gets full info about this object. + /// + public string ToLongDescription() + { + var result = new StringBuilder(); + + if (!string.IsNullOrEmpty(Author)) + result.Append("Author: ").AppendLine(Author); + if (ExpiryDate != DateTime.MinValue) + result.Append("Expiry Date: ").AppendLine(ExpiryDate.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")); + + if (ValidationErrorCode != 0) + { + result.Append("Error Code: ").AppendLine(ValidationErrorCode.ToString()); + result.Append("Error Message: ").AppendLine(ValidationErrorMessage); + } + + return result.ToString(); + } + + private string GetDescription() + { + var result = new StringBuilder(); + + if (ValidationErrorCode > 0) + { + result.Append(ValidationErrorMessage); + result.Append(" (code: ").Append(ValidationErrorCode).Append(")"); + } + else + { + result.Append(Author); + result.Append(" (").Append(ExpiryDate.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")).Append(")"); + } + + return result.ToString(); + } + } +} diff --git a/src_vs2012/NativeCore/Model/DeviceDefinition.cs b/src_vs2012/NativeCore/Model/DeviceDefinition.cs new file mode 100644 index 00000000..6ab21d3a --- /dev/null +++ b/src_vs2012/NativeCore/Model/DeviceDefinition.cs @@ -0,0 +1,453 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Helpers; +using Microsoft.Win32; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Short definition of the device used during development. + /// + public sealed class DeviceDefinition : IComparable + { + private const string FieldDeviceName = "device_name"; + private const string FieldDeviceIP = "device_IP"; + private const string FieldDevicePassword = "device_password"; + private const string FieldSimulatorName = "simulator_name"; + private const string FieldSimulatorIP = "simulator_IP"; + private const string FieldSimulatorPassword = "simulator_password"; + private const string FieldAllDevices = "devices"; + + /// + /// Init constructor. + /// + public DeviceDefinition(string name, string ip, string password, DeviceDefinitionType type) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + + Name = name; + IP = ip.Trim(); + Password = password; + Type = type; + } + + #region Properties + + public string Name + { + get; + private set; + } + + public string IP + { + get; + private set; + } + + public string Password + { + get; + private set; + } + + public DeviceDefinitionType Type + { + get; + private set; + } + + /// + /// Gets non-null short name of this device. + /// + public string ShortName + { + get { return string.IsNullOrEmpty(Name) ? IP : Name; } + } + + /// + /// Gets the name of the processor architecture on that device. + /// + public string Architecture + { + get { return GetArchitectureFriendlyName(Type); } + } + + #endregion + + /// + /// Checks if given device has specified name. + /// + public bool HasIdenticalName(string name) + { + return string.Compare(Name, name, StringComparison.InvariantCultureIgnoreCase) == 0; + } + + /// + /// Checks if given device has specified IP. + /// + public bool HasIdenticalIP(string ip) + { + return string.Compare(IP, ip, StringComparison.InvariantCultureIgnoreCase) == 0; + } + + public int CompareTo(DeviceDefinition other) + { + if (other == null) + return 1; + + if (Type != other.Type) + return other.Type == DeviceDefinitionType.Device ? 1 : -1; + + int result = string.Compare(IP, other.IP, CultureInfo.CurrentCulture, CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase); + if (result != 0) + return result; + + return string.Compare(Name, other.Name, StringComparison.InvariantCultureIgnoreCase); + } + + public override string ToString() + { + if (string.IsNullOrEmpty(Name)) + { + return string.Concat(IP, " (", DeviceHelper.GetTypeToString(Type), ")"); + } + + return string.Concat(Name, " (", IP, ", ", DeviceHelper.GetTypeToString(Type), ")"); + } + + /// + /// Gets the target architecture's friendly name assigned to particular device type. + /// + public static string GetArchitectureFriendlyName(DeviceDefinitionType type) + { + switch (type) + { + case DeviceDefinitionType.Device: + return "ARMv7"; + case DeviceDefinitionType.Simulator: + return "x86"; + default: + throw new InvalidEnumArgumentException("Unsupported enum value (" + type + ")"); + } + } + + /// + /// Gets the target processor architecture assigned to particular device type. + /// + public static string GetArchitecture(DeviceDefinitionType type) + { + switch (type) + { + case DeviceDefinitionType.Device: + return "armle-v7"; + case DeviceDefinitionType.Simulator: + return "x86"; + default: + throw new InvalidEnumArgumentException("Unsupported enum value (" + type + ")"); + } + } + + /// + /// Finds identical device within given collection. + /// + public static DeviceDefinition Find(DeviceDefinition[] targetDevices, DeviceDefinition device) + { + if (device == null || targetDevices == null) + return null; + + if (!string.IsNullOrEmpty(device.Name)) + { + // search by name: + foreach (var d in targetDevices) + { + if (d.Type == device.Type && d.HasIdenticalName(device.Name) && d.HasIdenticalIP(device.IP)) + return d; + } + } + + // in case searching by name failed - try to match by IP: + foreach (var d in targetDevices) + if (d.Type == device.Type && d.HasIdenticalIP(device.IP)) + return d; + + return null; + } + + /// + /// Checks, if specified collection contains device with known IP. + /// + public static bool ContainsWithIP(DeviceDefinition[] devices, string ip) + { + if (string.IsNullOrEmpty(ip)) + return false; + if (devices == null) + return false; + + foreach (var device in devices) + { + if (device.HasIdenticalIP(ip)) + return true; + } + + return false; + } + + /// + /// Finds the index of the device, by comparing the object references. + /// + public static int IndexOf(DeviceDefinition[] targetDevices, DeviceDefinition device) + { + if (device == null || targetDevices == null) + return -1; + + for (int i = 0; i < targetDevices.Length; i++) + { + if (ReferenceEquals(targetDevices[i], device)) + return i; + } + + return -1; + } + + /// + /// Retrieves device definition from the registry. + /// + public static DeviceDefinition LoadDevice() + { + return Load(DeviceDefinitionType.Device); + } + + /// + /// Retrieves simulator definition from the registry. + /// + public static DeviceDefinition LoadSimulator() + { + return Load(DeviceDefinitionType.Simulator); + } + + /// + /// Retrieves device definition from registry. + /// + public static DeviceDefinition Load(DeviceDefinitionType type) + { + if (type != DeviceDefinitionType.Device && type != DeviceDefinitionType.Simulator) + throw new ArgumentOutOfRangeException("type", "Unspported device type"); + + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings; + + string name = null; + string ip = null; + string password = null; + + try + { + settings = registry.OpenSubKey(ConfigDefaults.RegistryPath); + } + catch + { + // no device definition + return null; + } + if (settings == null) + return null; + + // NAME + try + { + object xName = settings.GetValue(type == DeviceDefinitionType.Device ? FieldDeviceName : FieldSimulatorName); + if (xName != null) + name = xName.ToString(); + } + catch + { + } + + + // IP + try + { + object xIP = settings.GetValue(type == DeviceDefinitionType.Device ? FieldDeviceIP : FieldSimulatorIP); + if (xIP != null) + ip = xIP.ToString(); + } + catch + { + } + + // PASSWORD + try + { + object xPassword = settings.GetValue(type == DeviceDefinitionType.Device ? FieldDevicePassword : FieldSimulatorPassword); + if (xPassword != null) + password = GlobalHelper.Decrypt(xPassword.ToString()); + } + catch + { + } + + settings.Close(); + registry.Close(); + + // verify arguments: + if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(password)) + return null; + + return new DeviceDefinition(name, ip, password, type); + } + + /// + /// Removes the info about selected device from the registry. + /// + public static void Delete(DeviceDefinitionType type) + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.DeleteValue(type == DeviceDefinitionType.Device ? FieldDeviceName : FieldSimulatorName, false); + settings.DeleteValue(type == DeviceDefinitionType.Device ? FieldDeviceIP : FieldSimulatorIP, false); + settings.DeleteValue(type == DeviceDefinitionType.Device ? FieldDevicePassword : FieldSimulatorPassword, false); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Saves given data about the device or simulator into the registry. + /// + public void Save() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + if (Name == null) + Name = string.Empty; + if (IP == null) + IP = string.Empty; + if (Password == null) + Password = string.Empty; + + settings.SetValue(Type == DeviceDefinitionType.Device ? FieldDeviceName : FieldSimulatorName, Name); + settings.SetValue(Type == DeviceDefinitionType.Device ? FieldDeviceIP : FieldSimulatorIP, IP); + settings.SetValue(Type == DeviceDefinitionType.Device ? FieldDevicePassword : FieldSimulatorPassword, GlobalHelper.Encrypt(Password)); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Loads info about all devices from registry. + /// + public static DeviceDefinition[] LoadAll() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.OpenSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return new DeviceDefinition[0]; + + return Deserialize((string[])settings.GetValue(FieldAllDevices, null)); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Saves info about all devices inside registry. + /// + public static void SaveAll(IEnumerable devices) + { + string[] devicesInfo = Serialize(devices); + + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.SetValue(FieldAllDevices, devicesInfo, RegistryValueKind.MultiString); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + private static DeviceDefinition[] Deserialize(string[] values) + { + if (values == null || values.Length == 0) + return new DeviceDefinition[0]; + + if ((values.Length % 4) != 0) + throw new ArgumentOutOfRangeException("values"); + + var result = new List(); + for (int i = 0; i < values.Length; i += 4) + { + var device = new DeviceDefinition(string.IsNullOrEmpty(values[i]) ? null : values[i], + values[i + 2], GlobalHelper.Decrypt(values[i + 3]), + DeviceHelper.GetTypeFromString(values[i + 1], false)); + result.Add(device); + } + + return result.ToArray(); + } + + private static string[] Serialize(IEnumerable devices) + { + var result = new List(); + + if (devices != null) + { + foreach (var device in devices) + { + result.Add(device.Name ?? string.Empty); + result.Add(DeviceHelper.GetTypeToString(device.Type)); + result.Add(device.IP); + result.Add(GlobalHelper.Encrypt(device.Password)); + } + } + + return result.ToArray(); + } + } +} diff --git a/src_vs2012/NativeCore/Model/DeviceDefinitionType.cs b/src_vs2012/NativeCore/Model/DeviceDefinitionType.cs new file mode 100644 index 00000000..7a6cec35 --- /dev/null +++ b/src_vs2012/NativeCore/Model/DeviceDefinitionType.cs @@ -0,0 +1,8 @@ +namespace BlackBerry.NativeCore.Model +{ + public enum DeviceDefinitionType + { + Device, + Simulator + } +} diff --git a/src_vs2012/NativeCore/Model/DeviceFamilyType.cs b/src_vs2012/NativeCore/Model/DeviceFamilyType.cs new file mode 100644 index 00000000..602ad7b3 --- /dev/null +++ b/src_vs2012/NativeCore/Model/DeviceFamilyType.cs @@ -0,0 +1,12 @@ +namespace BlackBerry.NativeCore.Model +{ + /// + /// Enumeration describing types of available devices. + /// + public enum DeviceFamilyType + { + Unknown, + Tablet, + Phone + } +} diff --git a/src_vs2012/NativeCore/Model/DeviceInfo.cs b/src_vs2012/NativeCore/Model/DeviceInfo.cs new file mode 100644 index 00000000..5038cfac --- /dev/null +++ b/src_vs2012/NativeCore/Model/DeviceInfo.cs @@ -0,0 +1,574 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Xml; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Detailed info about a physical device received from BlackBerry tools and services. + /// + public sealed class DeviceInfo + { + public DeviceInfo() + { + ScreenResolution = Size.Empty; + IconResolution = Size.Empty; + } + + #region Properties + + public DeviceTheme DefaultTheme + { + get; + private set; + } + + public ulong PIN + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public Version SystemVersion + { + get; + private set; + } + + public string SystemName + { + get; + private set; + } + + public string ModelFamily + { + get; + private set; + } + + public string ModelFullName + { + get; + private set; + } + + public string ModelName + { + get; + private set; + } + + public string ModelNumber + { + get; + private set; + } + + public uint ScreenDPI + { + get; + private set; + } + + public Size ScreenResolution + { + get; + private set; + } + + public Size IconResolution + { + get; + private set; + } + + public DeviceDebugTokenInfo DebugToken + { + get; + private set; + } + + #endregion + + public override string ToString() + { + if (string.IsNullOrEmpty(ModelName)) + { + if (SystemVersion == null) + return Name; + + return string.Concat(Name, " ( OS v", SystemVersion, ")"); + } + + return string.Concat(Name, " (", ModelName, ", OS v", SystemVersion, ")"); + } + + /// + /// Gets the values of all fields. + /// + public string ToLongDescription() + { + var result = new StringBuilder(); + + result.Append("Name: ").AppendLine(Name); + result.Append("PIN: ").AppendLine(PIN.ToString("X")); + result.Append("Model: ").Append(ModelName).Append(" (").Append(ModelNumber).AppendLine(")"); + result.Append("Model Family: ").AppendLine(ModelFamily); + result.Append("System: ").Append(SystemName).Append(" (").Append(SystemVersion).AppendLine(")"); + result.Append("Resolution: ").Append(ScreenResolution.Width).Append("x").Append(ScreenResolution.Height).Append(" (").Append(ScreenDPI).AppendLine("dpi)"); + result.Append("Theme: ").Append(DefaultTheme); + + return result.ToString(); + } + + /// + /// Parses device information out of given PPS text. + /// + public static DeviceInfo Parse(string text, out string error) + { + error = null; + + if (string.IsNullOrEmpty(text)) + { + return null; + } + + var result = new DeviceInfo(); + var lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var sections = new[] { "deviceproperties", "devmode", "versions" }; + int activeSection = -1; + int lastSection = -1; + + string dtAuthor = null; + DateTime dtExpiryDate = DateTime.MinValue; + bool dtValid = false; + bool dtInstalled = false; + string dtErrorMessage = null; + uint dtErrorCode = 0; + + foreach (var line in lines) + { + // is it a runtime error description? + if (line.StartsWith("error:", StringComparison.InvariantCultureIgnoreCase)) + { + // if so - further parsing is not needed + error = line.Substring(6).Trim(); + break; + } + + string name, value; + bool isSection = SplitLine(line, out name, out value); + + // try to dected, which secition we are just entering: + if (isSection) + { + lastSection = activeSection; + activeSection = Array.IndexOf(sections, name); + + if (activeSection == 1) // devmode + { + // clean up debug-token state: + dtAuthor = null; + dtExpiryDate = DateTime.MinValue; + dtValid = false; + dtInstalled = false; + dtErrorMessage = null; + dtErrorCode = 0; + } + else + { + if (lastSection == 1) // was devmode + { + result.DebugToken = new DeviceDebugTokenInfo(dtAuthor, dtExpiryDate, dtValid, dtInstalled, dtErrorMessage, dtErrorCode); + } + } + + continue; + } + + // parse fields within section: + switch (activeSection) + { + case 0: // deviceproperties + switch (name) + { + case "defaultTheme": + result.DefaultTheme = GetTheme(value); + break; + case "devicepin": + result.PIN = ParseDeviceId(value); + break; + case "device_os": + result.SystemName = value; + + // unfortunatelly PlayBook doesn't return full info, as expected, so we set it manually based on specs: + if (string.Compare(value, "BlackBerry PlayBook OS", StringComparison.InvariantCultureIgnoreCase) == 0) + { + if (string.IsNullOrEmpty(result.Name)) + result.Name = "PlayBook"; + if (string.IsNullOrEmpty(result.ModelFamily)) + result.ModelFamily = "Tablet"; // Touch ?? + if (string.IsNullOrEmpty(result.ModelFullName)) + result.ModelFullName = "BlackBerry PlayBook"; + if (string.IsNullOrEmpty(result.ModelName)) + result.ModelName = "PlayBook"; + if (string.IsNullOrEmpty(result.ModelNumber)) + result.ModelNumber = "STL100-0"; // copied from Z10 + if (result.ScreenDPI == 0) + result.ScreenDPI = 167; + if (result.ScreenResolution.IsEmpty) + result.ScreenResolution = new Size(1024, 600); + if (result.IconResolution.IsEmpty) + result.IconResolution = new Size(90, 90); // copied from Z10/Z30/Q10 + } + break; + case "scmbundle": + result.SystemVersion = new Version(value); + break; + case "modelfamily": + result.ModelFamily = value; + break; + case "modelfullname": + result.ModelFullName = value; + break; + case "modelname": + result.ModelName = value; + break; + case "modelnumber": + result.ModelNumber = value; + break; + case "screen_dpi": + result.ScreenDPI = GetNumber(value); + break; + case "screen_res": + result.ScreenResolution = GetResolution(value); + break; + case "icon_res": + result.IconResolution = GetResolution(value); + break; + } + break; + case 1: + switch (name) + { + case "debug_token_author": + dtAuthor = value; + break; + case "debug_token_expiration": + dtExpiryDate = GetDate(value); + break; + case "debug_token_installed": + dtInstalled = GetBool(value); + break; + case "debug_token_valid": + dtValid = GetBool(value); + break; + case "debug_token_validation_error": + dtErrorMessage = value; + break; + case "debug_token_validation_error_code": + dtErrorCode = GetNumber(value); + break; + } + break; + case 2: // versions + switch (name) + { + case "hostname": + result.Name = value; + break; + } + break; + } + } + + if (result.DebugToken == null) + { + if (lastSection == 1) // devmode + { + result.DebugToken = new DeviceDebugTokenInfo(dtAuthor, dtExpiryDate, dtValid, dtInstalled, dtErrorMessage, dtErrorCode); + } + else + { + result.DebugToken = new DeviceDebugTokenInfo(null, DateTime.MinValue, false, false, null, 0); + } + } + + return string.IsNullOrEmpty(error) && result.SystemVersion != null && result.PIN != 0 ? result : null; + } + + private static DateTime GetDate(string text) + { + if (!string.IsNullOrEmpty(text)) + { + DateTime result; + CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-US"); + var formats = new[] { "R", "U", + "ddd MMM dd HH':'mm':'ss 'GMT'zzz yyyy", + "ddd MMMM dd HH':'mm':'ss 'GMT'zzz yyyy", + "ddd MMM d HH':'mm':'ss 'GMT'zzz yyyy", + "ddd MMMM d HH':'mm':'ss 'GMT'zzz yyyy" }; + + foreach (var style in formats) + { + if (DateTime.TryParseExact(text, style, cultureInfo, DateTimeStyles.None, out result)) + return result.ToUniversalTime(); + } + } + + return DateTime.MinValue.ToUniversalTime(); + } + + private static bool GetBool(string text) + { + if (string.IsNullOrEmpty(text)) + return false; + if (string.Compare(text, "true", StringComparison.InvariantCultureIgnoreCase) == 0) + return true; + if (string.CompareOrdinal(text, "1") == 0) + return true; + if (string.Compare(text, "false", StringComparison.InvariantCultureIgnoreCase) == 0) + return false; + if (string.CompareOrdinal(text, "0") == 0) + return false; + + // PH: no reason, but sometimes boolean field is presented as JSON (especially debug-token-valid field)... + if (string.CompareOrdinal(text, "{}") == 0) + return false; + if (string.CompareOrdinal(text, "null") == 0) + return false; + + throw new FormatException("Invalid boolean value"); + } + + private static Size GetResolution(string text) + { + if (string.IsNullOrEmpty(text)) + return Size.Empty; + + int separatorIndex = text.IndexOf('x'); + if (separatorIndex < 0) + return Size.Empty; + + uint width; + uint height; + + if (!uint.TryParse(text.Substring(0, separatorIndex), out width)) + width = 0; + if (!uint.TryParse(text.Substring(separatorIndex + 1), out height)) + height = 0; + + return new Size(width, height); + } + + private static uint GetNumber(string text) + { + uint dpi; + return uint.TryParse(text, out dpi) ? dpi : 0; + } + + /// + /// Converts string representation of PIN into a number. + /// + public static ulong ParseDeviceId(string text) + { + if (string.IsNullOrEmpty(text)) + return 0; + + ulong id; + + if (text.StartsWith("0x") || text.StartsWith("0X")) + { + return ulong.TryParse(text.Substring(2), NumberStyles.AllowHexSpecifier | NumberStyles.AllowLeadingWhite | NumberStyles.AllowLeadingWhite, null, out id) ? id : 0; + } + + return ulong.TryParse(text, NumberStyles.AllowLeadingWhite | NumberStyles.AllowLeadingWhite, null, out id) ? id : 0; + } + + private static DeviceTheme GetTheme(string text) + { + if (string.IsNullOrEmpty(text)) + return DeviceTheme.Unknown; + if (string.Compare(text, "white", StringComparison.InvariantCultureIgnoreCase) == 0) + return DeviceTheme.White; + if (string.Compare(text, "black", StringComparison.InvariantCultureIgnoreCase) == 0) + return DeviceTheme.Black; + + return DeviceTheme.Unknown; + } + + private static bool SplitLine(string line, out string name, out string value) + { + if (string.IsNullOrEmpty(line)) + { + name = null; + value = null; + return false; + } + + // is it a section startup marker? + if (line.StartsWith("@") || line.StartsWith("[n]@")) + { + name = line.Substring(line.IndexOf('@') + 1).Trim(); + value = null; + return true; + } + + // Split the typical PPS field definition of format: :: + // where type part is optional + // and also be aware of some random messages in format: : + int typeStartAt = line.IndexOf(':'); + if (typeStartAt >= 0) + { + int valueStartAt = line.IndexOf(':', typeStartAt + 1); + if (valueStartAt < 0) + { + name = line.Substring(0, typeStartAt); + value = line.Substring(typeStartAt + 1).Trim(); + } + else + { + name = line.Substring(0, typeStartAt); + value = line.Substring(valueStartAt + 1).Trim(); + } + + // remove persistance option qualifier from its name: + if (name.StartsWith("[n]")) + { + name = name.Substring(3); + } + + if (name.Length == 0) + { + name = null; + } + if (value.Length == 0) + { + value = null; + } + } + else + { + name = null; + value = null; + } + + return false; + } + + /// + /// Loads info about devices from XML file, given by the reader. + /// It supports only one format - the one from NDK descriptor. + /// + public static DeviceInfo[] Load(XmlReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + var result = new List(); + DeviceInfo info = null; + bool isAboutIcon = false; + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "device": + info = new DeviceInfo(); + isAboutIcon = false; + break; + case "name": + if (info != null) + info.ModelFullName = info.Name = reader.ReadString(); + break; + case "kind": + if (info != null) + info.ModelFamily = reader.ReadString(); + break; + case "ppi": + if (info != null) + info.ScreenDPI = GetNumber(reader.ReadString()); + break; + case "icon": + if (info != null) + { + isAboutIcon = true; + } + break; + case "width": + if (info != null) + { + if (isAboutIcon) + info.IconResolution = UpdateWidth(reader.ReadString(), info.IconResolution.Height); + else + info.ScreenResolution = UpdateWidth(reader.ReadString(), info.ScreenResolution.Height); + } + break; + case "height": + if (info != null) + { + if (isAboutIcon) + info.IconResolution = UpdateHeight(info.IconResolution.Width, reader.ReadString()); + else + info.ScreenResolution = UpdateHeight(info.ScreenResolution.Width, reader.ReadString()); + } + break; + + } + } + + if (reader.NodeType == XmlNodeType.EndElement) + { + // ok, got full info about the device: + if (reader.Name == "device") + { + if (info != null && !string.IsNullOrEmpty(info.Name)) + { + result.Add(info); + info = null; + } + + continue; + } + + if (reader.Name == "icon") + { + isAboutIcon = false; + continue; + } + + // interesting section has been read, no need to parse further: + if (reader.Name == "devices") + break; + } + } + + return result.ToArray(); + } + + private static Size UpdateWidth(string width, uint height) + { + var value = GetNumber(width); + + return new Size(value, height); + } + + private static Size UpdateHeight(uint width, string height) + { + var value = GetNumber(height); + + return new Size(width, value); + } + } +} diff --git a/src_vs2012/NativeCore/Model/DeviceTheme.cs b/src_vs2012/NativeCore/Model/DeviceTheme.cs new file mode 100644 index 00000000..83b4ab77 --- /dev/null +++ b/src_vs2012/NativeCore/Model/DeviceTheme.cs @@ -0,0 +1,9 @@ +namespace BlackBerry.NativeCore.Model +{ + public enum DeviceTheme + { + Unknown, + Black, + White + } +} diff --git a/src_vs2012/NativeCore/Model/GdbInfo.cs b/src_vs2012/NativeCore/Model/GdbInfo.cs new file mode 100644 index 00000000..ea0e7246 --- /dev/null +++ b/src_vs2012/NativeCore/Model/GdbInfo.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Description of locally installed GDB. + /// + public sealed class GdbInfo + { + /// + /// Init constructor. + /// + public GdbInfo(NdkDefinition ndk, DeviceDefinition device, RuntimeDefinition runtime, IEnumerable additionalLibraryPaths) + { + if (ndk == null) + throw new ArgumentNullException("ndk"); + if (string.IsNullOrEmpty(ndk.HostPath)) + throw new ArgumentOutOfRangeException("ndk"); + if (string.IsNullOrEmpty(ndk.TargetPath)) + throw new ArgumentOutOfRangeException("ndk"); + if (device == null) + throw new ArgumentNullException("device"); + if (string.IsNullOrEmpty(device.IP)) + throw new ArgumentOutOfRangeException("device"); + + NDK = ndk; + Device = device; + Runtime = runtime; + LibraryPaths = CreateLibraryPaths(ndk, runtime, device.Type, additionalLibraryPaths); + Executable = Path.Combine(NDK.HostPath, "usr", "bin", GetName(device.Type)); + Arguments = "--interpreter=mi2"; + } + + /// + /// Init constructor. + /// + public GdbInfo(NdkInfo ndk, DeviceDefinition device, RuntimeDefinition runtime, IEnumerable additionalLibraryPaths) + : this(ndk != null ? ndk.ToDefinition() : null, device, runtime, additionalLibraryPaths) + { + } + + #region Properties + + public NdkDefinition NDK + { + get; + private set; + } + + public DeviceDefinition Device + { + get; + private set; + } + + public RuntimeDefinition Runtime + { + get; + private set; + } + + public string Executable + { + get; + private set; + } + + public string Arguments + { + get; + private set; + } + + public string[] LibraryPaths + { + get; + private set; + } + + #endregion + + private string GetName(DeviceDefinitionType type) + { + switch (type) + { + case DeviceDefinitionType.Device: + return "ntoarm-gdb.exe"; + case DeviceDefinitionType.Simulator: + return "ntox86-gdb.exe"; + default: + throw new ArgumentOutOfRangeException("type"); + } + } + + private static string[] CreateLibraryPaths(NdkDefinition ndk, RuntimeDefinition runtime, DeviceDefinitionType deviceType, IEnumerable additionalLibraryPaths) + { + if (ndk == null) + throw new ArgumentNullException("ndk"); + + // create list of folders with installed libraries: + var libraries = new List(); + string archFolder = GetArchitectureFolder(deviceType); + + // developer-specified paths go first: + if (additionalLibraryPaths != null) + { + libraries.AddRange(additionalLibraryPaths); + } + + // first the libraries from the runtime: + if (runtime != null) + { + libraries.Add(Path.Combine(runtime.Folder, archFolder, "lib")); + libraries.Add(Path.Combine(runtime.Folder, archFolder, "user", "lib")); + libraries.Add(Path.Combine(runtime.Folder, archFolder, "user", "lib", "qt4")); + } + + // then the default ones, that belong to current NDK: + libraries.Add(Path.Combine(ndk.TargetPath, archFolder, "lib")); + libraries.Add(Path.Combine(ndk.TargetPath, archFolder, "usr", "lib")); + return libraries.ToArray(); + } + + private static string GetArchitectureFolder(DeviceDefinitionType type) + { + switch (type) + { + case DeviceDefinitionType.Device: + return "armle-v7"; + case DeviceDefinitionType.Simulator: + return "x86"; + default: + throw new ArgumentOutOfRangeException("type"); + } + } + } +} diff --git a/src_vs2012/NativeCore/Model/ImportProjectInfo.cs b/src_vs2012/NativeCore/Model/ImportProjectInfo.cs new file mode 100644 index 00000000..763f9a03 --- /dev/null +++ b/src_vs2012/NativeCore/Model/ImportProjectInfo.cs @@ -0,0 +1,616 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Description of the Momentics project to import. + /// + public sealed class ImportProjectInfo + { + private static readonly string[] ForbiddenFiles = { "\\.settings", "\\.device", "\\.cproject", "\\.project", "\\.gitignore", "\\.gitmodules", "\\manifest.properties", "\\installedApps.txt", "\\vsndk-compile-ran.flag", ".vcxproj", ".vcxproj.filters", ".suo", ".user" }; + private static readonly string[] ForbiddenDirs = { "\\arm", "\\x86", "\\.settings", "\\.git", "\\.svn", "\\.hg", "\\Device-Debug", "\\Debug", "\\Device-Release", "\\Release", "\\Simulator-Debug", "\\obj", "\\bin" }; + + private const string DefaultBarDescriptorFileName = "bar-descriptor.xml"; + + /// + /// Init constructor. + /// + public ImportProjectInfo(string path, string name, string[] files, string[] defines, string[] dependencies, string[] includeDirectories, bool buildOutputDependsOnTargetArch) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + + Path = path; + Name = name; + Files = files ?? new string[0]; + Defines = defines ?? new string[0]; + Dependencies = dependencies ?? new string[0]; + IncludeDirectories = includeDirectories ?? new string[0]; + BuildOutputDependsOnTargetArch = buildOutputDependsOnTargetArch; + } + + #region Properties + + public string Path + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public string[] Files + { + get; + private set; + } + + public string[] Defines + { + get; + private set; + } + + /// + /// Gets the collection of names of referenced shared libraries. + /// + public string[] Dependencies + { + get; + private set; + } + + /// + /// Gets the collection of additional include directories. + /// + public string[] IncludeDirectories + { + get; + private set; + } + + public bool BuildOutputDependsOnTargetArch + { + get; + private set; + } + + #endregion + + /// + /// Loads info about the Momentics project to import. + /// + public static ImportProjectInfo Load(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + if (!Directory.Exists(path)) + return null; + + /////////// + // Name + + // default name is the name of the directory: + var projectName = System.IO.Path.GetFileName(path); + + var projectFileName = System.IO.Path.Combine(path, ".project"); + if (File.Exists(projectFileName)) + { + string name; + + // if correctly loaded: + if (ReadProjectFile(projectFileName, out name)) + { + projectName = name; + } + } + + /////////// + // Files + + var projectFiles = new List(); + var projectDependencies = new List(); + var projectDefines = new List(); + var projectIncludeDirectories = new List(); + + // is there redefining all manifest file? + var manifestFileName = System.IO.Path.Combine(path, "manifest.properties"); + if (File.Exists(manifestFileName)) + { + string name; + string[] files; + string[] defines; + string[] dependencies; + + if (ReadProjectManifest(manifestFileName, path, out name, out files, out defines, out dependencies)) + { + if (!string.IsNullOrEmpty(name)) + { + projectName = name; + } + + AppendUniquely(projectFiles, files); + AppendUniquely(projectDefines, defines); + AppendUniquely(projectDependencies, dependencies); + } + } + + var cprojectFileName = System.IO.Path.Combine(path, ".cproject"); + if (File.Exists(cprojectFileName)) + { + string[] defines; + string[] dependencies; + string[] includes; + if (ReadCProjectFile(cprojectFileName, out defines, out dependencies, out includes)) + { + AppendUniquely(projectDefines, defines); + AppendUniquely(projectDependencies, dependencies); + AppendUniquely(projectIncludeDirectories, includes); + } + } + + // default list of files is everything from the folder: + if (projectFiles.Count == 0) + { + AppendUniquely(projectFiles, ScanForFiles(path)); + } + + /////////// + // Outputs + + bool projectBuildOutputDependsOnTargetArch = false; + + // is there any 'entry' definition in bar-descriptor.xml that looks like: arm/o.le-v7-g or x86/o-g or similar? + var barDescriptorFileName = System.IO.Path.Combine(path, DefaultBarDescriptorFileName); + + // if it's not in standard location, try to find it among project files: + if (!File.Exists(barDescriptorFileName)) + { + foreach (var fileName in projectFiles) + { + if (IsBarDescriptorFile(fileName)) + { + barDescriptorFileName = fileName; + break; + } + } + } + + if (File.Exists(barDescriptorFileName)) + { + bool outputsBasedOnTargetArch; + if (ReadProjectBarDescriptor(barDescriptorFileName, out outputsBasedOnTargetArch)) + { + projectBuildOutputDependsOnTargetArch = outputsBasedOnTargetArch; + } + } + + return new ImportProjectInfo(path, projectName, projectFiles.ToArray(), projectDefines.ToArray(), projectDependencies.ToArray(), projectIncludeDirectories.ToArray(), projectBuildOutputDependsOnTargetArch); + } + + /// + /// Checks, if specified file refers to bar-descriptor. + /// + public static bool IsBarDescriptorFile(string fileName) + { + return !string.IsNullOrEmpty(fileName) && fileName.EndsWith(System.IO.Path.DirectorySeparatorChar + DefaultBarDescriptorFileName, StringComparison.OrdinalIgnoreCase); + } + + private static void AppendUniquely(List list, IEnumerable newItems) + { + if (newItems != null) + { + foreach (var value in newItems) + { + if (!list.Contains(value)) + { + list.Add(value); + } + } + } + } + + private static bool ReadProjectFile(string projectFileName, out string name) + { + if (string.IsNullOrEmpty(projectFileName)) + throw new ArgumentNullException("projectFileName"); + + try + { + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.Load(projectFileName); + + if (xmlDoc.DocumentElement != null && xmlDoc.DocumentElement.Name == "projectDescription") + { + var nameElement = xmlDoc.DocumentElement["name"]; + if (nameElement != null) + { + name = nameElement.InnerText; + return !string.IsNullOrEmpty(name); + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load .project file: \"{0}\"", projectFileName); + } + + name = null; + return false; + } + + private static bool ReadCProjectFile(string cprojectFileName, out string[] defines, out string[] dependencies, out string[] includeDirectories) + { + if (string.IsNullOrEmpty(cprojectFileName)) + throw new ArgumentNullException("cprojectFileName"); + + var defs = new List(); + var libs = new List(); + var includes = new List(); + + defines = null; + dependencies = null; + includeDirectories = null; + + try + { + var xmlDoc = new XmlDocument(); + xmlDoc.Load(cprojectFileName); + + // process the 'option' items of any configuration: + var options = xmlDoc.GetElementsByTagName("option"); + for (int i = 0; i < options.Count; i++) + { + var node = options[i]; + if (node != null && node.Attributes != null) + { + var attrSuperClass = node.Attributes["superClass"]; + if (attrSuperClass != null) + { + if (string.Compare(attrSuperClass.Value, "com.qnx.qcc.option.linker.libraries", StringComparison.Ordinal) == 0) + { + AddFromNodeList(libs, node.ChildNodes); + } + else + { + if (string.Compare(attrSuperClass.Value, "com.qnx.qcc.option.compiler.defines", StringComparison.Ordinal) == 0) + { + AddFromNodeList(defs, node.ChildNodes); + } + else + { + if (string.Compare(attrSuperClass.Value, "com.qnx.qcc.option.compiler.includePath", StringComparison.Ordinal) == 0) + { + AddFromNodeList(includes, node.ChildNodes); + } + } + } + } + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to read .cproject file: \"{0}\"", cprojectFileName); + return false; + } + + // fix the difference environment variables are named in Momentics: + for (int i = 0; i < includes.Count; i++) + { + includes[i] = includes[i].Replace('{', '(').Replace('}', ')').Replace(System.IO.Path.AltDirectorySeparatorChar, System.IO.Path.DirectorySeparatorChar); + } + + + defines = defs.ToArray(); + dependencies = libs.ToArray(); + includeDirectories = includes.ToArray(); + + return true; + } + + private static void AddFromNodeList(List list, XmlNodeList nodeList) + { + if (nodeList != null) + { + for (int i = 0; i < nodeList.Count; i++) + { + var node = nodeList[i]; + if (node != null && node.Attributes != null) + { + // for non-built-in options: + var attrBuiltIn = node.Attributes["builtIn"]; + if (attrBuiltIn != null && string.Compare(attrBuiltIn.Value, "false", StringComparison.OrdinalIgnoreCase) == 0) + { + var attrValue = node.Attributes["value"]; + if (attrValue != null) + { + if (!list.Contains(attrValue.Value)) + { + list.Add(attrValue.Value); + } + } + } + } + } + } + } + + /// + /// Scans for all supported files recursively inside specified location. + /// + public static string[] ScanForFiles(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + var result = new List(); + ScanForFiles(result, path, true); + + return result.ToArray(); + } + + private static void ScanForFiles(ICollection result, string path, bool root) + { + if (!Directory.Exists(path)) + return; + + string[] files; + try + { + files = Directory.GetFiles(path, "*.*"); + } + catch (UnauthorizedAccessException) + { + return; + } + + foreach (var file in files) + { + // filter a bit root level folder: + if (root) + { + if (IsForbidden(ForbiddenFiles, file)) + { + continue; + } + } + + result.Add(file); + } + + string[] directories; + try + { + directories = Directory.GetDirectories(path, "*.*"); + } + catch (UnauthorizedAccessException) + { + return; + } + + foreach (var subDirectory in directories) + { + // filter a bit root level folder: + if (root) + { + if (IsForbidden(ForbiddenDirs, subDirectory)) + { + continue; + } + } + + ScanForFiles(result, subDirectory, false); + } + } + + private static bool IsForbidden(IEnumerable collection, string path) + { + if (string.IsNullOrEmpty(path)) + return false; + + foreach (var pattern in collection) + { + if (path.EndsWith(pattern, StringComparison.OrdinalIgnoreCase)) + return true; + } + + return false; + } + + private static bool ReadProjectManifest(string manifestFileName, string filesRoot, out string name, out string[] files, out string[] defines, out string[] dependencies) + { + if (string.IsNullOrEmpty(manifestFileName)) + throw new ArgumentNullException("manifestFileName"); + if (string.IsNullOrEmpty(filesRoot)) + throw new ArgumentNullException("filesRoot"); + + char[] separators = { ' ', '\t' }; + var contents = new List(); + var defs = new List(); + var libs = new List(); + var paths = new Dictionary(); + + contents.Add("bar-descriptor.xml"); + + name = null; + files = null; + defines = null; + dependencies = null; + try + { + using (var reader = new StreamReader(manifestFileName)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + // comment? + if (line.Length == 0 || line[0] == '#') + continue; + + // rule? + int separatorIndex = line.IndexOf(':'); + if (separatorIndex > 0) + { + var ruleName = line.Substring(0, separatorIndex).Trim(); + var ruleValue = line.Substring(separatorIndex + 1).Trim(); + + // is it a project name? + if (string.Compare(ruleName, "project.name", StringComparison.OrdinalIgnoreCase) == 0) + { + name = ruleValue; + } + + // is it a referenced library? + if (string.Compare(ruleName, "libs", StringComparison.OrdinalIgnoreCase) == 0) + { + AppendUniquely(libs, ruleValue.Split(separators, StringSplitOptions.RemoveEmptyEntries)); + } + + // is it a define? + if (string.Compare(ruleName, "flags.compiler", StringComparison.OrdinalIgnoreCase) == 0) + { + foreach (var value in ruleValue.Split(separators, StringSplitOptions.RemoveEmptyEntries)) + { + if (value.StartsWith("-D")) + { + var define = value.Substring(2); + if (!defs.Contains(define)) + { + defs.Add(define); + } + } + } + } + + // is it a file, part of the project? + if (string.Compare(ruleName, "icon", StringComparison.OrdinalIgnoreCase) == 0 + || string.Compare(ruleName, "sources", StringComparison.OrdinalIgnoreCase) == 0 + || string.Compare(ruleName, "resources", StringComparison.OrdinalIgnoreCase) == 0 + || string.Compare(ruleName, "readmes", StringComparison.OrdinalIgnoreCase) == 0) + { + contents.AddRange(ruleValue.Split(separators, StringSplitOptions.RemoveEmptyEntries)); + } + + // is it a path definition? + if (ruleName.StartsWith("path.", StringComparison.OrdinalIgnoreCase)) + { + paths[ruleName.Substring(5)] = ruleValue; + } + } + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load manifest file: \"{0}\"", manifestFileName); + return false; + } + + // prepare final results: + var fullPaths = new List(); + + foreach (var contentFileName in contents) + { + var fullFileName = MakeFullFilePath(contentFileName, filesRoot, paths); + if (!string.IsNullOrEmpty(fullFileName) && !fullPaths.Contains(fullFileName)) + { + fullPaths.Add(fullFileName); + } + } + fullPaths.Sort(); + + files = fullPaths.ToArray(); + defines = defs.ToArray(); + dependencies = libs.ToArray(); + return true; + } + + private static string MakeFullFilePath(string fileName, string root, Dictionary paths) + { + if (string.IsNullOrEmpty(fileName)) + return null; + + string fullName; + string pathMapping; + + if (paths != null && paths.TryGetValue(fileName, out pathMapping)) + { + fullName = pathMapping; + } + else + { + fullName = fileName; + } + + if (!System.IO.Path.IsPathRooted(fullName)) + { + if (string.IsNullOrEmpty(root)) + return null; + + fullName = System.IO.Path.Combine(root, fullName); + } + + return File.Exists(fullName) ? fullName : null; + } + + private static bool ReadProjectBarDescriptor(string barDescriptorFileName, out bool buildOutputsDependsOnTargetArch) + { + if (string.IsNullOrEmpty(barDescriptorFileName)) + throw new ArgumentNullException("barDescriptorFileName"); + + buildOutputsDependsOnTargetArch = false; + + try + { + var xmlDoc = new XmlDocument(); + xmlDoc.Load(barDescriptorFileName); + + // get all assets and verify if the 'entry' ones have special output path: + var assets = xmlDoc.GetElementsByTagName("asset"); + for(int i = 0; i < assets.Count; i++) + { + var node = assets[i]; + if (node != null && node.Attributes != null) + { + var attrEntry = node.Attributes["entry"]; + if (attrEntry != null && string.Compare(attrEntry.Value, "true", StringComparison.OrdinalIgnoreCase) == 0) + { + var attrPath = node.Attributes["path"]; + if (attrPath != null) + { + buildOutputsDependsOnTargetArch = IsTargetArchBuildOutput(attrPath.Value); + break; + } + } + } + } + + return true; + } + catch (Exception) + { + return false; + } + } + + private static bool IsTargetArchBuildOutput(string path) + { + return !string.IsNullOrEmpty(path) && + (path.StartsWith("arm/o.le-v7-g/", StringComparison.OrdinalIgnoreCase) || + path.StartsWith("arm/o.le-v7/", StringComparison.OrdinalIgnoreCase) || + path.StartsWith("x86/o-g/", StringComparison.OrdinalIgnoreCase)); + } + } +} diff --git a/src_vs2012/NativeCore/Model/NdkDefinition.cs b/src_vs2012/NativeCore/Model/NdkDefinition.cs new file mode 100644 index 00000000..2eae61a6 --- /dev/null +++ b/src_vs2012/NativeCore/Model/NdkDefinition.cs @@ -0,0 +1,172 @@ +using System; +using System.IO; +using BlackBerry.NativeCore.Helpers; +using Microsoft.Win32; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Short definition of the NDK used during development. + /// + public sealed class NdkDefinition + { + private const string FieldHostPath = "NDKHostPath"; + private const string FieldTargetPath = "NDKTargetPath"; + private const string FieldFamilyType = "NDKFamilyType"; + + #region Properties + + public NdkDefinition(string hostPath, string targetPath, DeviceFamilyType type) + { + if (string.IsNullOrEmpty(hostPath)) + throw new ArgumentNullException("hostPath"); + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + + HostPath = hostPath; + TargetPath = targetPath; + Type = type; + } + + public string HostPath + { + get; + private set; + } + + public string TargetPath + { + get; + private set; + } + + public string ToolsPath + { + get { return string.IsNullOrEmpty(HostPath) ? null : Path.Combine(HostPath, "usr", "bin"); } + } + + public DeviceFamilyType Type + { + get; + private set; + } + + #endregion + + /// + /// Retrieves info about used NDK from registry. + /// + public static NdkDefinition Load() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings; + + string hostPath = null; + string targetPath = null; + DeviceFamilyType type = DeviceFamilyType.Phone; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + } + catch + { + // no plugin info found at all... + return null; + } + if (settings == null) + return null; + + try + { + var xHostPath = settings.GetValue(FieldHostPath); + if (xHostPath != null) + hostPath = Path.GetFullPath(xHostPath.ToString()); + } + catch + { + } + + try + { + var xTargetPath = settings.GetValue(FieldTargetPath); + if (xTargetPath != null) + targetPath = Path.GetFullPath(xTargetPath.ToString()); + } + catch + { + } + + try + { + var xType = settings.GetValue(FieldFamilyType); + if (xType != null) + type = DeviceHelper.GetFamilyTypeFromString(xType.ToString()); + } + catch + { + } + + settings.Close(); + registry.Close(); + + // verify arguments: + if (string.IsNullOrEmpty(hostPath) || string.IsNullOrEmpty(targetPath)) + return null; + + return new NdkDefinition(hostPath, targetPath, type); + } + + /// + /// Removes NDK info from the registry. + /// + public static void Delete() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.DeleteValue(FieldHostPath, false); + settings.DeleteValue(FieldTargetPath, false); + settings.DeleteValue(FieldFamilyType, false); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Saves NDK info into the registry. + /// + public void Save() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.SetValue(FieldHostPath, HostPath); + settings.SetValue(FieldTargetPath, TargetPath); + settings.SetValue(FieldFamilyType, DeviceHelper.GetFamilyTypeToString(Type)); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + } +} diff --git a/src_vs2012/NativeCore/Model/NdkInfo.cs b/src_vs2012/NativeCore/Model/NdkInfo.cs new file mode 100644 index 00000000..71d0f26f --- /dev/null +++ b/src_vs2012/NativeCore/Model/NdkInfo.cs @@ -0,0 +1,687 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Descriptor of a locally installed NDK. + /// + public sealed class NdkInfo : ApiInfo + { + private const string DescriptorFileName = "blackberry-sdk-descriptor.xml"; + + public NdkInfo(string filePath, string name, Version version, string hostPath, string targetPath, DeviceFamilyType type, DeviceInfo[] devices, PermissionInfo[] permissions) + : base(name, version, type) + { + if (string.IsNullOrEmpty(hostPath)) + throw new ArgumentNullException("hostPath"); + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + if (devices == null) + throw new ArgumentNullException("devices"); + if (permissions == null) + throw new ArgumentNullException(""); + + FilePath = filePath; + HostPath = hostPath; + TargetPath = targetPath; + Devices = devices; + Permissions = permissions; + } + + public NdkInfo(string filePath, string name, Version version, string hostPath, string targetPath, DeviceFamilyType type) + : base(name, version, type) + { + if (string.IsNullOrEmpty(hostPath)) + throw new ArgumentNullException("hostPath"); + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + + FilePath = filePath; + HostPath = hostPath; + TargetPath = targetPath; + + //////////////////////// + // and now load devices, based on some heuristics, keeping in mind, that this field can't be never null: + var ndkDescriptor = Path.Combine(targetPath, DescriptorFileName); + DeviceInfo[] devices = LoadDevices(ndkDescriptor); + + // if failed to load devices, try to find one folder above: + if (devices == null) + { + ndkDescriptor = Path.Combine(targetPath, "..", DescriptorFileName); + devices = LoadDevices(ndkDescriptor); + } + + // or another above: + if (devices == null) + { + ndkDescriptor = Path.Combine(targetPath, "..", "..", DescriptorFileName); + devices = LoadDevices(ndkDescriptor); + } + + // load permissions from the same descriptor file as devices were stored in: + if (devices != null) + { + if (devices.Length == 0) + { + // found descriptor file, but was empty... heuristics says - it's a PlayBook + // then even override type, what caller provided + // - there is one case when it can happen - when developer added custom NDK to tablet - and there is no other way to distinguish phone-tablet + Permissions = PermissionInfo.CreatePlayBookList(); + Type = DeviceFamilyType.Tablet; + } + else + { + Permissions = LoadPermissions(ndkDescriptor); + } + } + else + { + // in case no descriptor file was found, use a default list: + Permissions = PermissionInfo.CreateDefaultList(); + } + + // OK, give up, and say it's unknown, if still null: + Devices = devices ?? new DeviceInfo[0]; + Details = ToShortDeviceDescription(); + } + + #region Properties + + public string FilePath + { + get; + private set; + } + + public string HostPath + { + get; + private set; + } + + public string TargetPath + { + get; + private set; + } + + public DeviceInfo[] Devices + { + get; + private set; + } + + public PermissionInfo[] Permissions + { + get; + private set; + } + + public override bool IsInstalled + { + get + { + try + { + return Directory.Exists(HostPath) && Directory.Exists(TargetPath); + } + catch + { + return false; + } + } + } + + public Version CascadesVersion + { + get { return new Version(1, Version.Minor); } + } + + #endregion + + /// + /// Compares two paths, if they are identical. + /// + private static bool HasPath(string pathA, string pathB) + { + if (string.IsNullOrEmpty(pathA) && string.IsNullOrEmpty(pathB)) + return true; + + // assuming that paths we acquired by Path.GetFullPath(...) + return string.Compare(pathA, pathB, StringComparison.InvariantCultureIgnoreCase) == 0; + } + + /// + /// Checks if specified path points to the same folder as TargetPath. + /// + public bool HasTargetPath(string path) + { + return HasPath(TargetPath, path); + } + + /// + /// Checks if given NDK info has identical paths. + /// + public bool Matches(string hostPath, string targetPath) + { + return HasPath(HostPath, hostPath) && HasPath(TargetPath, targetPath); + } + + /// + /// Checks if given NDKs are identical. + /// + public bool Matches(NdkInfo ndk) + { + return HasPath(HostPath, ndk != null ? ndk.HostPath : null) && HasPath(TargetPath, ndk != null ? ndk.TargetPath : null); + } + + /// + /// Gets the long description for this NDK. + /// + public string ToLongDescription() + { + var result = new StringBuilder(); + + result.AppendLine(Name).AppendLine(); + result.AppendLine("Version:"); + result.Append(" - ").AppendLine(Version.ToString()); + result.Append(" - ").AppendLine(Type.ToString()); + + result.AppendLine(); + result.AppendLine("Devices:"); + if (Devices.Length > 0) + { + foreach (var device in Devices) + { + result.Append(" - ").Append(device.ModelFullName).Append(", ").AppendLine(device.ModelFamily); + result.Append(" ") + .Append(device.ScreenDPI) + .Append("ppi, icon: ") + .Append(((int) device.IconResolution.Width).ToString()) + .Append("x") + .AppendLine(((int) device.IconResolution.Height).ToString()); + } + } + else + { + result.AppendLine(" No supported device information found."); + } + + result.AppendLine(); + result.AppendLine("Paths:"); + result.Append(" - host: ").AppendLine(HostPath); + result.Append(" - target: ").AppendLine(TargetPath); +#if DEBUG + result.Append(" - descriptor: ").AppendLine(FilePath); +#endif + + result.AppendLine(); + result.AppendLine("Permissions:"); + if (Permissions.Length > 0) + { + foreach (var permission in Permissions) + { + result.Append(" - ").Append(permission.Name).Append(" (").Append(permission.ID).AppendLine(")"); + } + } + else + { + result.AppendLine(" No available application permissions found."); + } + + return result.ToString(); + } + + private string ToShortDeviceDescription() + { + if (Devices == null || Devices.Length == 0) + return "Device support unknown"; + + var result = new StringBuilder("Supports "); + int i = 0; + + foreach (var device in Devices) + { + if (i > 0) + result.Append(", "); + result.Append(device.ModelFullName); + i++; + } + + return result.ToString(); + } + + /// + /// Loads info about a single NDK from specific config file, given as XML. + /// + public static NdkInfo Load(string fileName, XmlReader reader) + { + if (reader == null) + return null; + + string name = null; + Version version = null; + string hostPath = null; + string targetPath = null; + DeviceFamilyType type = DeviceFamilyType.Phone; + bool allowTypeOverride = true; + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "name": + name = reader.ReadString(); + break; + case "version": + version = new Version(reader.ReadString()); + break; + case "host": + hostPath = Path.GetFullPath(reader.ReadString()); + break; + case "target": + targetPath = Path.GetFullPath(reader.ReadString()); + break; + case "edition": + type = DeviceHelper.GetFamilyTypeFromString(reader.ReadString()); + allowTypeOverride = false; + break; + } + } + + if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "installation") + { + if (!string.IsNullOrEmpty(targetPath) && !string.IsNullOrEmpty(hostPath)) + { + // is it a PlayBook NDK, which has no 'version' field? + if (version == null && !string.IsNullOrEmpty(name)) + { + if (allowTypeOverride) + { + type = DeviceFamilyType.Tablet; + } + + // try first to load info about installation: + var installInfoPath = Path.Combine(targetPath, "..", "..", "install", "info.txt"); + if (File.Exists(installInfoPath)) + { + try + { + version = GetVersionFromInstallationInfo(File.ReadAllLines(installInfoPath)); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to read installation info from file: \"{0}\"", installInfoPath); + } + } + + // if that failed, maybe there is a version inside the folder? + if (version == null) + { + version = GetVersionFromFolderName(name); + } + + // ok, give up, assign anything: + if (version == null) + { + version = CreateTabletInfo().Version; + } + } + + // try to define info about the installation: + return new NdkInfo(fileName, name, version, hostPath, targetPath, type); + } + + return null; + } + } + + return null; + } + + private static DeviceInfo[] LoadDevices(string ndkDescriptorFileName) + { + try + { + if (!File.Exists(ndkDescriptorFileName)) + return null; + + // try to load info about supported devices by the NDK: + using (var fileReader = new StreamReader(ndkDescriptorFileName, Encoding.UTF8)) + { + using (var descReader = XmlReader.Create(fileReader)) + { + return DeviceInfo.Load(descReader); + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load device list from NDK descriptor file: \"{0}\"", ndkDescriptorFileName); + return null; + } + } + + private static PermissionInfo[] LoadPermissions(string ndkDescriptorFileName) + { + try + { + if (!File.Exists(ndkDescriptorFileName)) + return null; + + // try to load info about application permissions from the NDK: + using (var fileReader = new StreamReader(ndkDescriptorFileName, Encoding.UTF8)) + { + using (var descReader = XmlReader.Create(fileReader)) + { + return PermissionInfo.Load(descReader); + } + } + + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load permissions from NDK descriptor file: \"{0}\"", ndkDescriptorFileName); + return null; + } + } + + /// + /// Loads info about all installed NDKs. + /// + public static NdkInfo[] Load(params string[] globalNdkConfigFolders) + { + if (globalNdkConfigFolders == null) + throw new ArgumentNullException("globalNdkConfigFolders"); + + var result = new List(); + + // list all configuration files, across all known folders: + foreach (var folder in globalNdkConfigFolders) + { + if (Directory.Exists(folder)) + { + try + { + var files = Directory.GetFiles(folder, "*.xml", SearchOption.AllDirectories); + + foreach (var file in files) + { + try + { + // read them: + using (var fileReader = new StreamReader(file, Encoding.UTF8)) + { + using (var reader = XmlReader.Create(fileReader)) + { + var info = Load(file, reader); + if (info != null && info.IsInstalled) + { + var existingIndex = IndexOf(result, info); + + // and store only unique ones: + // (if NDK info exist with exactly the same paths, prefer to keep the one with longer name) + if (existingIndex >= 0) + { + var existingItem = result[existingIndex]; + if (existingItem.Name != null && info.Name != null && existingItem.Name.Length < info.Name.Length) + { + result.RemoveAt(existingIndex); + result.Add(info); + } + } + else + { + result.Add(info); + } + } + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to open configuration file: \"{0}\"", file); + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load info about configuration files from folder: \"{0}\"", folder); + } + } + } + + result.Sort(); + return result.ToArray(); + } + + /// + /// Returns an index of a given NdkInfo inside a collection. + /// The search is based by matching few critical properties of an object. + /// + public static int IndexOf(IEnumerable list, NdkInfo info) + { + if (info != null && list != null) + { + int i = 0; + foreach (var item in list) + { + if (item.Matches(info)) + return i; + i++; + } + } + return -1; + } + + /// + /// Try to find an NDK definition somewhere in specified folder or around. + /// + public static NdkInfo Scan(string folder) + { + if (string.IsNullOrEmpty(folder)) + return null; + + if (!Directory.Exists(folder)) + return null; + + // is it a target folder directly? + NdkInfo info = ScanByTargetFolder(folder); + if (info != null) + return info; + + // is it a root folder? + var targetDirs = Directory.GetDirectories(folder, "target*"); + if (targetDirs.Length != 0) + { + // get the first folder with a descriptor: + foreach (var target in targetDirs) + { + info = ScanByTargetFolder(target); + if (info != null) + return info; + } + } + + // is it a host folder? + var parentDir = Path.GetDirectoryName(folder); + if (string.IsNullOrEmpty(parentDir)) + return null; + + targetDirs = Directory.GetDirectories(parentDir, "target*"); + if (targetDirs.Length == 0) + return null; + + // get first folder with a descriptor: + foreach (var target in targetDirs) + { + info = ScanByTargetFolder(targetDirs[0]); + if (info != null) + return info; + } + + return null; + } + + private static NdkInfo ScanByTargetFolder(string folder) + { + var parentDir = Path.GetDirectoryName(folder); + if (string.IsNullOrEmpty(parentDir)) + return null; + + var devicesDescriptorFileName = Path.Combine(folder, DescriptorFileName); + if (File.Exists(devicesDescriptorFileName)) + { + // find host folder + var hostDirs = Directory.GetDirectories(parentDir, "host*"); + if (hostDirs.Length == 0) + return null; + + // extract version out of the current folder name + var version = GetVersionFromFolderName(Path.GetFileName(folder)); + var type = DeviceFamilyType.Phone; + + if (version == null) + { + // is there an installation folder with version (used by PlayBook NDKs)? + var installInfoPath = Path.Combine(folder, "..", "install", "info.txt"); + if (File.Exists(installInfoPath)) + { + try + { + version = GetVersionFromInstallationInfo(File.ReadAllLines(installInfoPath)); + type = DeviceFamilyType.Tablet; + } + catch (Exception ex) + { + type = DeviceFamilyType.Unknown; + TraceLog.WriteException(ex, "Unable to read installation info from file: \"{0}\"", installInfoPath); + } + } + + if (version == null) + version = new Version(10, 0, 1); + } + + var prefix = type == DeviceFamilyType.Tablet ? "BlackBerry Native SDK for Tablet OS " : "BlackBerry Local SDK "; + return new NdkInfo(null, string.Concat(prefix, version, " /", DateTime.Now.ToString("yyyy-MM-dd"), "/"), + version, Path.Combine(hostDirs[0], "win32", "x86"), Path.Combine(folder, "qnx6"), type); + } + + return null; + } + + private static Version GetVersionFromInstallationInfo(string[] lines) + { + if (lines == null || lines.Length == 0) + return null; + + // find the line, that describes the target version: + foreach (var line in lines) + { + if (line.StartsWith("target", StringComparison.OrdinalIgnoreCase)) + { + var index = line.IndexOf('='); + string versionString; + if (index < 0) + versionString = line.Substring(7).Trim(); // one char after 'target' assumed to be separator + else + versionString = line.Substring(index + 1).Trim(); + + return string.IsNullOrEmpty(versionString) ? null : new Version(versionString); + } + } + + return null; + } + + public bool Save(string outputDirectory) + { + if (string.IsNullOrEmpty(outputDirectory)) + throw new ArgumentNullException("outputDirectory"); + + // make sure, the output directory exists: + try + { + Directory.CreateDirectory(outputDirectory); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to create directory for NDK info cache"); + return false; + } + + // normalize file name: + var fileName = new StringBuilder(string.IsNullOrEmpty(Name) ? "vsplugin_target_" + Version + DateTime.Now.ToString("yyyy-MM-dd_HH_mm_ss") + ".xml" : Name + ".xml"); + + for (int i = 0; i < fileName.Length; i++) + { + char c = fileName[i]; + if (!(char.IsLetterOrDigit(c) || c == '_' || c == '-' || c == '.')) + { + fileName[i] = '_'; + } + } + + // generate content: + const string content = @" + + + {0} + {1} + {2} + {3} + {4} + + + + + +"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(content); + + string name = Name ?? string.Empty; + string version = Version.ToString(); + string hostPath = HostPath.Replace('\\', '/'); + string targetPath = TargetPath.Replace('\\', '/'); + + var inst = doc.DocumentElement["installation"]; + if (inst != null) + { + inst["name"].InnerText = name; + inst["version"].InnerText = version; + inst["host"].InnerText = hostPath; + inst["target"].InnerText = targetPath; + inst["edition"].InnerText = DeviceHelper.GetFamilyTypeToString(Type); // VS-Plugin extension + } + else + { + throw new FormatException("Invalid data to process"); + } + + // store it: + var fullFilePath = Path.Combine(outputDirectory, fileName.ToString()); + doc.Save(fullFilePath); + FilePath = fullFilePath; + return true; + } + + /// + /// Creates the shimmed definition instance. + /// + public NdkDefinition ToDefinition() + { + return new NdkDefinition(HostPath, TargetPath, Type); + } + } +} diff --git a/src_vs2012/NativeCore/Model/PermissionInfo.cs b/src_vs2012/NativeCore/Model/PermissionInfo.cs new file mode 100644 index 00000000..5dac79c5 --- /dev/null +++ b/src_vs2012/NativeCore/Model/PermissionInfo.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Xml; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Descriptor of permissions, that are allowed to be set by the application compiled against specified NDK. + /// + [DebuggerDisplay("{ID}: {Description}")] + public sealed class PermissionInfo + { + private PermissionInfo() + { + } + + public PermissionInfo(string id, string name, string description) + { + if (string.IsNullOrEmpty(id)) + throw new ArgumentNullException("id"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + + ID = id; + Name = name; + Description = description ?? string.Empty; + } + + #region Properties + + public string ID + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public string Description + { + get; + private set; + } + + #endregion + + public override string ToString() + { + return Description; + } + + /// + /// Creates the default set of permissions for BlackBerry 10 application. + /// + public static PermissionInfo[] CreateDefaultList() + { + var result = new List(); + + result.Add(new PermissionInfo("bbm_connect", "BlackBerry Messenger", "Allows this app to connect to the BBM Social Platform to access BBM contact lists and user profiles, invite BBM contacts to download your app, initiate BBM chats and share content from within your app, or stream data between apps in real time.")); + result.Add(new PermissionInfo("access_pimdomain_calendars", "Calendar", "Allows this app to access the calendar on the device. This access includes viewing, adding, and deleting calendar appointments.")); + result.Add(new PermissionInfo("use_camera", "Camera", "Allows this app to take pictures, record video, and use the flash.")); + result.Add(new PermissionInfo("use_camera_desktop", "Capture Screen", "Allows this app to take screen shots, share your screen, and take videos of your screen.")); + result.Add(new PermissionInfo("access_pimdomain_contacts", "Contacts", "Allows this app to access the contacts stored on the device. This access includes viewing, creating, and deleting the contacts.")); + result.Add(new PermissionInfo("read_device_identifying_information", "Device Identifying Information", "Allows this app to access device identifiers such as serial number and PIN.")); + result.Add(new PermissionInfo("access_pimdomain_messages", "Email and PIN Message", "Allows this app to access the email and PIN messages stored on the device. This access includes viewing, creating, sending, and deleting the messages.")); + result.Add(new PermissionInfo("use_gamepad", "Gamepad", "Allows this app to support platform Gamepad functionality.")); + result.Add(new PermissionInfo("access_internet", "Internet", "Allows this app to use Wi-fi, wired, or other connections to a destination that is not local on the user's device.")); + result.Add(new PermissionInfo("access_location_services", "Location", "Allows this app to access the device’s current or saved locations.")); + result.Add(new PermissionInfo("record_audio", "Microphone", "Allows this app to record sound using the microphone.")); + result.Add(new PermissionInfo("read_personally_identifiable_information", "My Contact Info", "Allows the app to access your contact info, such as your name (where available), and the email address you use as your BlackBerry ID username.")); + result.Add(new PermissionInfo("access_pimdomain_notebooks", "Notebooks", "Allows this app to access the content stored in the notebooks on the device. This access includes adding and deleting entries and content.")); + result.Add(new PermissionInfo("access_notify_settings_control", "Notification Control", "Allows this app to modify global notification settings.")); + result.Add(new PermissionInfo("access_phone", "Phone", "Determine when a user is on a phone call. This access includes access to the phone number assigned to the device and the BlackBerry ID of the user.")); + result.Add(new PermissionInfo("control_phone", "Phone Control", "Allows this app to merge calls, use the dialpad during calls, or end calls.")); + result.Add(new PermissionInfo("post_notification", "Post Notifications", "Post a notification to the notifications area of the screen.")); + result.Add(new PermissionInfo("_sys_use_consumer_push", "Consumer Push", "Allows this app to use the Push Service with the BlackBerry Internet Service. This access allows the app to receive and request push messages. To use the Push Service with the BlackBerry Internet Service, you must register with Research In Motion. When you register, you receive a confirmation email message that contains information that your application needs to receive and request push messages. For more information about registering, visit https://developer.blackberry.com/services/push/. If you're using the Push Service with the BlackBerry Enterprise Server or the BlackBerry Device Service, you don't need to register with BlackBerry.")); + result.Add(new PermissionInfo("_sys_run_headless", "Run in Background", "Allows an app to run as a invokable headless service without a UI. By default the service runs for a finite amount of time.")); + result.Add(new PermissionInfo("_sys_run_headless_nostop", "Run in Background Continuously", "Allows an app to run as a long running headless service. Used in conjunction with _sys_run_headless.")); + result.Add(new PermissionInfo("run_when_backgrounded", "Run as Active Frame", "Allows background processing. Without this permission, the app is stopped when the user switches focus to another app. Apps that use this permission are rigorously reviewed for acceptance to BlackBerry App World storefront for their use of power.")); + result.Add(new PermissionInfo("access_shared", "Shared Files", "Allows this app to access pictures, music, documents, and other files stored on the user's device, at a remote storage provider, on a media card, or in the cloud.")); + result.Add(new PermissionInfo("access_sms_mms", "Text Messages", "Allows this app to access the text messages stored on the device. The access includes viewing, creating, sending, and deleting text messages.")); + result.Add(new PermissionInfo("narrow_landscape_exit", "Narrow Swipe Up", "Disables the application close gesture. Designed for games.")); + result.Add(new PermissionInfo("access_wifi_public", "WiFi Connection", "Allows the app to receive Wi-Fi event notifications such as Wi-Fi scan results or changes in the Wi-Fi connection state. This permission also allows limited Wi-Fi control for hotspot aggregator applications that manage network selection and the authentication to a Wi-Fi Hotspot. This permission does not allow the app the ability to force a connection to a specific network profile when there are other available networks that have a higher priority configured on the device. It is not necessary to configure this permission if you only want to retrieve or query information about existing Wi-Fi connections.")); + + return result.ToArray(); + } + + /// + /// Creates a list of permissions designed for PlayBook applications. + /// + public static PermissionInfo[] CreatePlayBookList() + { + var result = new List(); + + result.Add(new PermissionInfo("access_shared", "Files", "Read and write files that are shared between all applications run by the current user.")); + result.Add(new PermissionInfo("record_audio", "Microphone", "Access the audio stream from the microphone.")); + result.Add(new PermissionInfo("read_geolocation", "GPS Location", "Allows this app to access the current GPS location of the device.")); + result.Add(new PermissionInfo("use_camera", "Camera", "Capture images and video using the cameras.")); + result.Add(new PermissionInfo("access_internet", "Internet", "Use a Wi-Fi, wired, or other connection to a destination that is not local.")); + result.Add(new PermissionInfo("play_audio", "Play Sounds", "Play an audio stream.")); + result.Add(new PermissionInfo("post_notification", "Post Notification", "Post a notification to the notifications area of the screen.")); + result.Add(new PermissionInfo("set_audio_volume", "Set Audio Volume", "Change the volume of an audio stream being played.")); + result.Add(new PermissionInfo("read_device_identifying_information", "Device Identifying Information", "Access unique device identifying information (e.g. PIN).")); + + return result.ToArray(); + } + + /// + /// Loads info about permissions from XML file, given by the reader. + /// It supports only one format - the one from NDK descriptor. + /// + public static PermissionInfo[] Load(XmlReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + var result = new List(); + PermissionInfo info = null; + bool canRead = false; + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "permissions": + canRead = true; + break; + case "permission": + if (canRead) + info = new PermissionInfo(); + break; + case "id": + if (info != null) + info.ID = reader.ReadString(); + break; + case "name": + if (info != null) + info.Name = reader.ReadString(); + break; + case "description": + if (info != null) + info.Description = reader.ReadString(); + break; + + // ignore all the other fields, if given + } + } + + if (reader.NodeType == XmlNodeType.EndElement) + { + // ok, got full info about the device: + if (reader.Name == "permission") + { + if (info != null && !string.IsNullOrEmpty(info.ID)) + { + result.Add(info); + info = null; + } + + continue; + } + + // interesting section has been read, no need to parse further: + if (reader.Name == "permissions") + break; + } + } + + return result.ToArray(); + } + } +} diff --git a/src_vs2012/NativeCore/Model/RuntimeDefinition.cs b/src_vs2012/NativeCore/Model/RuntimeDefinition.cs new file mode 100644 index 00000000..e7a5ad5c --- /dev/null +++ b/src_vs2012/NativeCore/Model/RuntimeDefinition.cs @@ -0,0 +1,121 @@ +using System; +using Microsoft.Win32; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Short definition of the runtime libraries used during development. + /// + public sealed class RuntimeDefinition + { + private const string FieldPath = "NDKRemotePath"; + + public RuntimeDefinition(string folder) + { + if (string.IsNullOrEmpty(folder)) + throw new ArgumentNullException("folder"); + + Folder = folder; + } + + #region Properties + + public string Folder + { + get; + private set; + } + + #endregion + + /// + /// Retrieves info about used runtime libraries from registry. + /// + public static RuntimeDefinition Load() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings; + + string folder = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + } + catch + { + // no plugin info found at all... + return null; + } + if (settings == null) + return null; + + try + { + var xFolder = settings.GetValue(FieldPath); + if (xFolder != null) + folder = System.IO.Path.GetFullPath(xFolder.ToString()); + } + catch + { + } + + settings.Close(); + registry.Close(); + + // verify arguments: + if (string.IsNullOrEmpty(folder)) + return null; + + return new RuntimeDefinition(folder); + } + + /// + /// Removes runtime libraries info from the registry. + /// + public static void Delete() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.DeleteValue(FieldPath, false); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + + /// + /// Saves runtime libraries info into the registry. + /// + public void Save() + { + RegistryKey registry = Registry.CurrentUser; + RegistryKey settings = null; + + try + { + settings = registry.CreateSubKey(ConfigDefaults.RegistryPath); + if (settings == null) + return; + + settings.SetValue(FieldPath, Folder); + } + finally + { + if (settings != null) + settings.Close(); + registry.Close(); + } + } + } +} diff --git a/src_vs2012/NativeCore/Model/RuntimeInfo.cs b/src_vs2012/NativeCore/Model/RuntimeInfo.cs new file mode 100644 index 00000000..35286d2e --- /dev/null +++ b/src_vs2012/NativeCore/Model/RuntimeInfo.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Description of locally installed runtime libraries. + /// + public sealed class RuntimeInfo : ApiInfo + { + public RuntimeInfo(string folder, string name, Version version) + : base(name, version, DeviceFamilyType.Phone) + { + Folder = folder; + Details = Version.ToString(); + } + + #region Properties + + /// + /// Gets the local path, where the runtime libraries are installed. + /// + public string Folder + { + get; + private set; + } + + public override bool IsInstalled + { + get { return !string.IsNullOrEmpty(Folder) && Directory.Exists(Folder); } + } + + #endregion + + /// + /// Gets an indication, if current runtime points to the same location. + /// + public bool Matches(string folder) + { + return string.CompareOrdinal(folder, Folder) == 0; + } + + /// + /// Gets an indication, if current runtime points to the same location. + /// + public bool Matches(RuntimeInfo info) + { + if (info == null) + return false; + + return string.CompareOrdinal(info.Folder, Folder) == 0 + && info.Version == Version; + } + + /// + /// Creates the shimmed definition instance. + /// + public RuntimeDefinition ToDefinition() + { + return new RuntimeDefinition(Folder); + } + + /// + /// Loads descriptions of installed runtimes from specified folders. + /// + public static RuntimeInfo[] Load(params string[] globalRuntimeConfigFolders) + { + if (globalRuntimeConfigFolders == null) + throw new ArgumentNullException("globalRuntimeConfigFolders"); + + var result = new List(); + + foreach (var folder in globalRuntimeConfigFolders) + { + if (Directory.Exists(folder)) + { + try + { + string[] runtimeDirectories = Directory.GetDirectories(folder); + + foreach (string runtimeDirectory in runtimeDirectories) + { + if (runtimeDirectory.Contains("runtime_")) + { + var name = Path.GetFileName(runtimeDirectory); // 'runtime_xx_yy_zz'... + var version = GetVersionFromFolderName(name); + + if (version != null) + { + var runtimeInfo = new RuntimeInfo(runtimeDirectory, string.Concat("Runtime Libraries for ", version), version); + + result.Add(runtimeInfo); + } + else + { + TraceLog.WarnLine("Unable to find runtime libraries version number in folder: \"{0}\"", runtimeDirectory); + } + } + } + + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load info about runtime libraries from folder: \"{0}\"", folder); + } + } + } + + result.Sort(); + return result.ToArray(); + } + } +} diff --git a/src_vs2012/NativeCore/Model/SimulatorInfo.cs b/src_vs2012/NativeCore/Model/SimulatorInfo.cs new file mode 100644 index 00000000..04026d49 --- /dev/null +++ b/src_vs2012/NativeCore/Model/SimulatorInfo.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Description of locally installed simulator. + /// + public sealed class SimulatorInfo : ApiInfo + { + public SimulatorInfo(string folder, string name, Version version) + : base(name, version, DeviceFamilyType.Phone) + { + Folder = folder; + Details = Version.ToString(); + } + + #region Properties + + public string Folder + { + get; + private set; + } + + public override bool IsInstalled + { + get { return !string.IsNullOrEmpty(Folder) && Directory.Exists(Folder); } + } + + #endregion + + /// + /// Loads descriptions of installed simulators from specified folders. + /// + public static SimulatorInfo[] Load(params string[] globalSimulatorConfigFolders) + { + if (globalSimulatorConfigFolders == null) + throw new ArgumentNullException("globalSimulatorConfigFolders"); + + var result = new List(); + + foreach (var folder in globalSimulatorConfigFolders) + { + if (Directory.Exists(folder)) + { + try + { + string[] simulatorDirectories = Directory.GetFiles(folder, "*.vmxf", SearchOption.AllDirectories); + + foreach (string simDirectory in simulatorDirectories) + { + if (simDirectory.Contains("simulator_")) + { + var name = Path.GetDirectoryName(simDirectory); // 'simulator_xx_yy_zz'... + var version = GetVersionFromFolderName(name); + + if (version != null) + { + var simulatorInfo = new SimulatorInfo(name, string.Concat("BlackBerry Simulator ", version.Major, ".", version.Minor), version); + + result.Add(simulatorInfo); + } + else + { + TraceLog.WarnLine("Unable to find simulator version number in folder: \"{0}\"", simDirectory); + } + } + } + + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load info about simulators from folder: \"{0}\"", folder); + } + } + } + + result.Sort(); + return result.ToArray(); + } + } +} diff --git a/src_vs2012/NativeCore/Model/Size.cs b/src_vs2012/NativeCore/Model/Size.cs new file mode 100644 index 00000000..ef746624 --- /dev/null +++ b/src_vs2012/NativeCore/Model/Size.cs @@ -0,0 +1,78 @@ +using System; + +namespace BlackBerry.NativeCore.Model +{ + /// + /// Class describing 2-dimensional space. + /// + public sealed class Size : IEquatable + { + public static readonly Size Empty = new Size(0, 0); + + /// + /// Init constructor. + /// + public Size(uint width, uint height) + { + Width = width; + Height = height; + } + + #region Properties + + /// + /// Gets the width value. + /// + public uint Width + { + get; + private set; + } + + /// + /// Gets the height value. + /// + public uint Height + { + get; + private set; + } + + /// + /// Checks, wheather there is any dimension defined. + /// + public bool IsEmpty + { + get { return Width == 0 && Height == 0; } + } + + #endregion + + public override int GetHashCode() + { + unchecked + { + return ((int)Width * 397) ^ (int)Height; + } + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is Size && Equals((Size) obj); + } + + public bool Equals(Size other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Width == other.Width && Height == other.Height; + } + + public override string ToString() + { + return string.Concat(Width, "x", Height); + } + } +} diff --git a/src_vs2012/NativeCore/NativeMethods.cs b/src_vs2012/NativeCore/NativeMethods.cs new file mode 100644 index 00000000..49fa513a --- /dev/null +++ b/src_vs2012/NativeCore/NativeMethods.cs @@ -0,0 +1,119 @@ +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace BlackBerry.NativeCore +{ + /// + /// Class collecting P/Invoke definitions. + /// + static class NativeMethods + { + /// + /// Indicates type of the Windows Exe binary (x86 or x64) or not executable at all. + /// + /// Full path to the file to check + /// If file is binary the bitness of the app is indicated by lpBinaryType value. + /// True if the file is binary false otherwise + [DllImport("kernel32.dll", CharSet=CharSet.Auto)] + public static extern bool GetBinaryType([MarshalAs(UnmanagedType.LPTStr)] string applicationName, out uint binaryType); + + /// + /// Interface to unmanaged code for getting the ShortPathName for a given directory. + /// + /// Path to be converted + /// Returned ShortPathName + /// Length of the ShortPathName + /// + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + private static extern int GetShortPathName( + [MarshalAs(UnmanagedType.LPTStr)] + string path, + [MarshalAs(UnmanagedType.LPTStr)] + StringBuilder shortPath, + int shortPathLength); + + /// GDB works with short path names only, which requires converting the path names to/from long ones. This function + /// returns the long path name for a given short one. + /// Short path name. + /// Returns this long path name. + /// Length of this long path name. + /// + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + private static extern int GetLongPathName( + [MarshalAs(UnmanagedType.LPTStr)] + string path, + [MarshalAs(UnmanagedType.LPTStr)] + StringBuilder longPath, + int longPathLength); + + /// + /// Gets the short version of specified path. + /// + public static string GetShortPathName(string path) + { + if (string.IsNullOrEmpty(path)) + return string.Empty; + + const int size = 1024; + var buffer = new StringBuilder(size); + + do + { + int result = GetShortPathName(path, buffer, buffer.Capacity); + + // did the call failed to convert the path? + if (result == 0) + return null; + // was the buffer too small: + if (result == buffer.Capacity) + { + buffer.Capacity += size; + continue; + } + + return buffer.ToString(0, result); + } while (false); + + return null; + } + + /// + /// Gets the long version of specified path. + /// + public static string GetLongPathName(string path) + { + if (string.IsNullOrEmpty(path)) + return string.Empty; + + // is it really a short name? + if (path.IndexOf('~') < 0) + return path; + + // expand to full-path: + const int size = 1024; + var buffer = new StringBuilder(size); + + do + { + int result = GetLongPathName(path, buffer, buffer.Capacity); + + // did the call failed to convert the path? + if (result == 0) + return null; + // was the buffer too small: + if (result == buffer.Capacity) + { + buffer.Capacity += size; + continue; + } + + if (Path.DirectorySeparatorChar != '/') + buffer.Replace('/', Path.DirectorySeparatorChar); + return buffer.ToString(0, result); + } while (false); + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/Properties/AssemblyInfo.cs b/src_vs2012/NativeCore/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..84bd5737 --- /dev/null +++ b/src_vs2012/NativeCore/Properties/AssemblyInfo.cs @@ -0,0 +1,43 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +using BlackBerry.NativeCore; + +[assembly: AssemblyTitle("BlackBerry Native SDK Core Module")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("BlackBerry")] +[assembly: AssemblyProduct("BlackBerry.NativeCore")] +[assembly: AssemblyCopyright("Copyright © BlackBerry 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5126a3ae-b370-4b45-873b-4b7ea5764092")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion(ConfigDefaults.VersionString)] +[assembly: AssemblyFileVersion(ConfigDefaults.VersionString)] + +#if DEBUG +[assembly: InternalsVisibleTo("IntegrationTests")] +[assembly: InternalsVisibleTo("UnitTests")] +#endif diff --git a/src_vs2012/NativeCore/QConn/HResult.cs b/src_vs2012/NativeCore/QConn/HResult.cs new file mode 100644 index 00000000..9f791adb --- /dev/null +++ b/src_vs2012/NativeCore/QConn/HResult.cs @@ -0,0 +1,14 @@ +namespace BlackBerry.NativeCore.QConn +{ + public enum HResult + { + OK, + Abort, + InvalidData, + InvalidFrameCode, + InvalidRedirect, + Fail, + BadLogin, + BufferTooSmall + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/CapturedLogsEventArgs.cs b/src_vs2012/NativeCore/QConn/Model/CapturedLogsEventArgs.cs new file mode 100644 index 00000000..92b85886 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/CapturedLogsEventArgs.cs @@ -0,0 +1,31 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Arguments passed along with captured logs. + /// + public sealed class CapturedLogsEventArgs : EventArgs + { + /// + /// Init constructor. + /// + public CapturedLogsEventArgs(TargetLogEntry[] entries) + { + if (entries == null || entries.Length == 0) + throw new ArgumentNullException("entries"); + + Entries = entries; + } + + #region Properties + + public TargetLogEntry[] Entries + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/DataReaderBigEndian.cs b/src_vs2012/NativeCore/QConn/Model/DataReaderBigEndian.cs new file mode 100644 index 00000000..4ab49913 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/DataReaderBigEndian.cs @@ -0,0 +1,55 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Class providing reading functionality of strings and numbers extracted from row byte stream of QDataSource. + /// It uses little-endian arithmetic. But looks like there is no device nor simulator using it yet. + /// PH: TODO: Left stubs for future implementation. + /// + sealed class DataReaderBigEndian : IDataReader + { + private readonly QDataSource _source; + + /// + /// Init constructor. + /// + public DataReaderBigEndian(QDataSource source) + { + if (source == null) + throw new ArgumentNullException("source"); + + _source = source; + } + + public int ReadInt32() + { + throw new NotImplementedException(); + } + + public uint ReadUInt32() + { + throw new NotImplementedException(); + } + + public ulong ReadUInt64() + { + throw new NotImplementedException(); + } + + public byte[] ReadBytes(int length) + { + throw new NotImplementedException(); + } + + public void Skip(int bytes) + { + throw new NotImplementedException(); + } + + public string ReadString(uint maxLength, char terminatorChar) + { + throw new NotImplementedException(); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/DataReaderLittleEndian.cs b/src_vs2012/NativeCore/QConn/Model/DataReaderLittleEndian.cs new file mode 100644 index 00000000..2514a08e --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/DataReaderLittleEndian.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Class providing reading functionality of strings and numbers extracted from row byte stream of QDataSource. + /// It uses little-endian arithmetic. Both the device and simulator are using this convention. + /// + sealed class DataReaderLittleEndian : IDataReader + { + private readonly QDataSource _source; + private byte[] _data; + private int _at; + private bool _finished; + + /// + /// Init constructor. + /// + public DataReaderLittleEndian(QDataSource source) + { + if (source == null) + throw new ArgumentNullException("source"); + + _source = source; + LoadNextDataBuffer(); + } + + private void LoadNextDataBuffer() + { + _finished = _source.Receive(int.MaxValue, out _data) != HResult.OK || _data.Length == 0; + _at = 0; + } + + private void VerifyData() + { + if (_finished) + throw new EndOfStreamException("Failed to read all available data"); + + if (_at >= _data.Length) + { + LoadNextDataBuffer(); + if (_finished) + throw new EndOfStreamException("Failed to read all available data"); + } + } + + public int ReadInt32() + { + VerifyData(); + + var at = _at; + _at += 4; + return (int)BitHelper.LittleEndian_ToUInt32(_data, at); + } + + public uint ReadUInt32() + { + VerifyData(); + + var at = _at; + _at += 4; + return BitHelper.LittleEndian_ToUInt32(_data, at); + } + + public ulong ReadUInt64() + { + VerifyData(); + + var at = _at; + _at += 8; + return BitHelper.LittleEndian_ToUInt64(_data, at); + } + + public byte[] ReadBytes(int length) + { + if (length <= 0) + throw new ArgumentOutOfRangeException("length"); + + VerifyData(); + + var result = new byte[length]; + + // is the current buffer big enough to provide the data: + if (_at + length <= _data.Length) + { + Array.Copy(_data, _at, result, 0, length); + _at += length; + + return result; + } + + // copy data from the current buffer: + int resultAt = _data.Length - _at; + Array.Copy(_data, _at, result, 0, resultAt); + length -= resultAt; + _at = _data.Length; + + do + { + // load next: + LoadNextDataBuffer(); + if (_finished) + throw new QConnException("Unable to load requested amount of data"); + + // and copy the next chunk of data: + int toRead = (_data.Length <= length) ? _data.Length : length; + Array.Copy(_data, 0, result, resultAt, toRead); + resultAt += toRead; + length -= toRead; + _at = toRead; + + } while (length > 0); + + return result; + } + + public void Skip(int bytes) + { + if (bytes == 0) + return; + + _at += bytes; + if (_at > _data.Length) + { + int skip = _at - _data.Length; + + VerifyData(); + Skip(skip); + } + } + + public string ReadString(uint maxLength, char terminatorChar) + { + if (maxLength == 0) + return string.Empty; + + VerifyData(); + + List buffers = null; + var at = _at; + int i = _at; + + for (; maxLength > 0; i++, maxLength--) + { + if (i == _data.Length) + { + if (buffers == null) + buffers = new List(); + + var chunk = new byte[i - at]; + Array.Copy(_data, at, chunk, 0, i - at); + buffers.Add(chunk); + + LoadNextDataBuffer(); + i = 0; + at = 0; + } + + if (_data[i] == terminatorChar) + { + _at = i + 1; // also skip the terminator + return GetString(buffers, _data, at, i - at); + } + } + + _at = i; + return GetString(buffers, _data, at, _data.Length - at); + } + + private static string GetString(List buffers, byte[] lastChunk, int lastAt, int lastLength) + { + if (buffers == null) + { + return Encoding.UTF8.GetString(lastChunk, lastAt, lastLength); + } + + Debug.Assert(lastAt == 0); // enforcing lastAt == 0! + return Encoding.UTF8.GetString(BitHelper.Combine(buffers, lastChunk, lastLength)); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/DecryptedChallenge.cs b/src_vs2012/NativeCore/QConn/Model/DecryptedChallenge.cs new file mode 100644 index 00000000..1302becf --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/DecryptedChallenge.cs @@ -0,0 +1,77 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Result of decryption received encryption-challenge. + /// + sealed class DecryptedChallenge + { + /// + /// Init constructor. + /// + public DecryptedChallenge(byte[] decryptedBlob, byte[] signature) + { + if (decryptedBlob == null || decryptedBlob.Length == 0) + throw new ArgumentNullException("decryptedBlob"); + if (signature == null || signature.Length == 0) + throw new ArgumentNullException("signature"); + + // and store: + DecryptedBlob = decryptedBlob; + Signature = signature; + SessionKey = GetChallengeItem(2); + } + + #region Properties + + public byte[] DecryptedBlob + { + get; + private set; + } + + public byte[] Signature + { + get; + private set; + } + + public byte[] SessionKey + { + get; + private set; + } + + #endregion + + private byte[] GetChallengeItem(byte id) + { + int i = 0; + + // record schema: + // - length - byte + // - id - byte + // - payload - length-bytes + + // iterate though all records to find one with matching ID: + while (i < DecryptedBlob.Length - 1) + { + byte length = DecryptedBlob[i]; + byte itemID = DecryptedBlob[i + 1]; + + if (itemID == id) + { + var result = new byte[length]; + Array.Copy(DecryptedBlob, i + 2, result, 0, length); + return result; + } + + i += 2; + i += length; + } + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/EncryptionChallenge.cs b/src_vs2012/NativeCore/QConn/Model/EncryptionChallenge.cs new file mode 100644 index 00000000..41aff3cc --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/EncryptionChallenge.cs @@ -0,0 +1,171 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Class describing encryption challenge. + /// + sealed class EncryptionChallenge + { + /// + /// Init constructor. + /// + public EncryptionChallenge(byte[] challenge) + { + if (challenge == null || challenge.Length == 0) + throw new ArgumentNullException("challenge"); + + // read header fields: + Length = BitHelper.LittleEndian_ToUInt16(challenge, 0); + Version = BitHelper.LittleEndian_ToUInt16(challenge, 2); + int sourceLength = BitHelper.LittleEndian_ToUInt16(challenge, 4); + SessionKeyLength = BitHelper.LittleEndian_ToUInt16(challenge, 6); + SessionKeyType = BitHelper.LittleEndian_ToUInt16(challenge, 8); + int containerLength = BitHelper.LittleEndian_ToUInt16(challenge, 10); + ContainerPrimitive = BitHelper.LittleEndian_ToUInt16(challenge, 12); + ContainerType = BitHelper.LittleEndian_ToUInt16(challenge, 14); + ExpectedSignatureLength = BitHelper.LittleEndian_ToUInt16(challenge, 16); + ExpectedSignatureType = BitHelper.LittleEndian_ToUInt16(challenge, 18); + ContainerKeyVersion = BitHelper.LittleEndian_ToUInt32(challenge, 20); + + // and read payload blobs: + SourceName = Encoding.UTF8.GetString(challenge, 24, sourceLength); + + EncryptedBlob = new byte[containerLength]; + Array.Copy(challenge, 24 + SourceName.Length, EncryptedBlob, 0, EncryptedBlob.Length); + } + + #region Properties + + public int Length + { + get; + private set; + } + + public ushort Version + { + get; + private set; + } + + public string SourceName + { + get; + private set; + } + + public int SessionKeyLength + { + get; + private set; + } + + public ushort SessionKeyType + { + get; + private set; + } + + public ushort ContainerPrimitive + { + get; + private set; + } + + public ushort ContainerType + { + get; + private set; + } + + public int ExpectedSignatureLength + { + get; + private set; + } + + public int ExpectedSignatureType + { + get; + private set; + } + + public uint ContainerKeyVersion + { + get; + private set; + } + + public byte[] EncryptedBlob + { + get; + private set; + } + + #endregion + + /// + /// Decripts encryption-challenge data and provides signatures for response. + /// + public DecryptedChallenge Decrypt(RSAParameters publicKey, RSAParameters privateKey) + { + byte[] QCONNDOOR_PERMISSIONS = { 3, 4, 0x76, 0x83, 1 }; + + // decrypt message: + byte[] decryptedChallengeBlob; + using (var rsa = new RSACryptoServiceProvider(1024)) + { + rsa.PersistKeyInCsp = false; + rsa.ImportParameters(privateKey); + decryptedChallengeBlob = rsa.Decrypt(EncryptedBlob, false); + } + + // calculate its hash: + var buffer = new byte[decryptedChallengeBlob.Length + QCONNDOOR_PERMISSIONS.Length]; + BitHelper.Copy(buffer, 0, decryptedChallengeBlob, QCONNDOOR_PERMISSIONS); + decryptedChallengeBlob = buffer; + + // get signature of the hash: + byte[] signature; + + // PH: HINT: In Java to actually pass the encryption-challenge + // calculated hash was prefixed with some magic EMSA_SHA1_HASH and encrypted + // using private key. However RSA in C# doesn't support private key encryption + // and somehow just signing the hash from decrypted-blob is sufficient to pass. + // Strange, but works as tested on PlayBook, Z10, Z30 and at least doesn't require + // anymore fun with BigIntegers. + using (var rsa = new RSACryptoServiceProvider(1024)) + { + rsa.PersistKeyInCsp = false; + rsa.ImportParameters(privateKey); + + using (var sha = new SHA1CryptoServiceProvider()) + { + signature = rsa.SignData(decryptedChallengeBlob, sha); + } + } + + if (signature.Length != ExpectedSignatureLength) + { + throw new Exception("Generated signature does not match expected signature length: " + signature.Length); + } + + /* + QTraceLog.PrintArray("blob", EncryptedBlob); + QTraceLog.PrintArray("privateKeyModulusBytes", privateRsaKeyInfo.Modulus); + QTraceLog.PrintArray("privateKeyExponentBytes", privateRsaKeyInfo.D); + QTraceLog.PrintArray("publicKeyModulusBytes", publicRsaKeyInfo.Modulus); + QTraceLog.PrintArray("publicKeyExponentBytes", publicRsaKeyInfo.Exponent); + + QTraceLog.PrintArray("decryptedChallengeBlob", decryptedChallengeBlob); + QTraceLog.PrintArray("signature", signature); + */ + + return new DecryptedChallenge(decryptedChallengeBlob, signature); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/Endianess.cs b/src_vs2012/NativeCore/QConn/Model/Endianess.cs new file mode 100644 index 00000000..c9f82f96 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/Endianess.cs @@ -0,0 +1,12 @@ +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Sescription of the endianess on the target. + /// + public enum Endianess + { + Unknown, + LittleEndian, + BigEndian + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/IDataReader.cs b/src_vs2012/NativeCore/QConn/Model/IDataReader.cs new file mode 100644 index 00000000..c3a8bfe5 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/IDataReader.cs @@ -0,0 +1,16 @@ +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Interface definition of the reader. + /// + public interface IDataReader + { + int ReadInt32(); + uint ReadUInt32(); + ulong ReadUInt64(); + byte[] ReadBytes(int length); + + void Skip(int bytes); + string ReadString(uint maxLength, char terminatorChar); + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/SystemInfoProcess.cs b/src_vs2012/NativeCore/QConn/Model/SystemInfoProcess.cs new file mode 100644 index 00000000..532c336e --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/SystemInfoProcess.cs @@ -0,0 +1,29 @@ +using BlackBerry.NativeCore.Debugger.Model; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Info about process running on the device. + /// + public sealed class SystemInfoProcess : ProcessInfo + { + /// + /// Init constructor. + /// + public SystemInfoProcess(uint id, uint parentID, string executablePath) + : base(id, executablePath) + { + ParentID = parentID; + } + + #region Properties + + public uint ParentID + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/TargetFile.cs b/src_vs2012/NativeCore/QConn/Model/TargetFile.cs new file mode 100644 index 00000000..379217a9 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/TargetFile.cs @@ -0,0 +1,348 @@ +using System; +using System.Globalization; +using System.IO; +using System.Text; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Class providing information about a target path. + /// + public class TargetFile : IComparable + { + internal const uint ModeOpenNone = 0; + internal const uint ModeOpenReadOnly = 1; + internal const uint ModeOpenWriteOnly = 2; + internal const uint ModeOpenReadWrite = ModeOpenReadOnly | ModeOpenWriteOnly; + + internal const uint TypeMask = 0xFFFF0FFF; + private const uint TypeCharacterDevice = 0x2000; + internal const uint TypeDirectory = 0x4000; + private const uint TypeNamedPipe = 0x5000; + private const uint TypeBlockDevice = 0x6000; + private const uint TypeRegularFile = 0x8000; + private const uint TypeSymlink = 0xA000; + private const uint TypeSocket = 0xC000; + + internal const uint ModePermissionsAll = 0xFFF; + internal const uint ModePermissionDefault = 0x1FF; + + /// + /// Init constructor. + /// + public TargetFile(uint mode, ulong size, uint flags, string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + Mode = mode; + Size = size; + Flags = flags; + CreationTime = DateTime.MinValue; + Path = path; + Name = PathHelper.ExtractName(path); + Extension = System.IO.Path.GetExtension(Name); + + UpdateFormatting(); + UpdateAccess(); + } + + /// + /// Init constructor. + /// It will create a 'stub' for files/folders we don't have access on the device. + /// + public TargetFile(string path, string name, bool isDirectory) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + Mode = isDirectory ? TypeDirectory : 0; + CreationTime = DateTime.MinValue; + NoAccess = true; + Path = path; + Name = string.IsNullOrEmpty(name) ? PathHelper.ExtractName(path) : name; + Extension = System.IO.Path.GetExtension(Name); + + UpdateFormatting(); + } + + /// + /// Init constructor. + /// Creates proper info about local file. + /// + public TargetFile(FileSystemInfo info) + { + if (info == null) + throw new ArgumentNullException("info"); + + Path = info.FullName; + Name = info.Name; + Extension = info.Extension; + + if (info.Exists) + { + bool isDirectory = (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory; + + CreationTime = info.CreationTime; + Size = isDirectory ? 0 : (ulong) ((FileInfo) info).Length; + Mode = (isDirectory ? TypeDirectory : TypeRegularFile) | ModePermissionsAll; + Flags = (info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly ? ModeOpenReadOnly : ModeOpenReadWrite; + } + else + { + CreationTime = DateTime.MinValue; + NoAccess = true; + } + + UpdateFormatting(); + UpdateAccess(); + } + + #region Properties + + public uint Mode + { + get; + private set; + } + + public uint Permissions + { + get { return Mode & ModePermissionsAll; } + } + + public uint Type + { + get { return Mode & 0xF000; } + } + + public string FormattedPermissions + { + get; + private set; + } + + public char FormattedType + { + get; + private set; + } + + public ulong Size + { + get; + private set; + } + + public uint Flags + { + get; + private set; + } + + public uint UserID + { + get; + private set; + } + + public uint GroupID + { + get; + private set; + } + + public DateTime CreationTime + { + get; + private set; + } + + public string Path + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public string Extension + { + get; + private set; + } + + public bool IsFile + { + get { return Type == TypeRegularFile; } + } + + public bool IsDirectory + { + get { return Type == TypeDirectory; } + } + + public bool IsSymlink + { + get { return Type == TypeSymlink; } + } + + /// + /// Gets an indication, if specified object describes 'something', we had no access to. + /// That's why it was impossible to load info and all properties are invalid. + /// + public bool NoAccess + { + get; + private set; + } + + #endregion + + #region IComparable Implementation + + public int CompareTo(TargetFile other) + { + if (other == null) + return 1; + + // folders should be first on the list: + if (IsDirectory) + { + if (other.IsDirectory) + return string.Compare(Name, other.Name, StringComparison.CurrentCulture); + return -1; + } + + if (!IsDirectory && other.IsDirectory) + return 1; + + return string.Compare(Name, other.Name, StringComparison.CurrentCulture); + } + + #endregion + + public override string ToString() + { + return string.Concat(Path, " (", FormattedPermissions, ")"); + } + + internal void Update(uint userID, uint groupID, DateTime creationTime, uint mode, ulong size) + { + UserID = userID; + GroupID = groupID; + CreationTime = creationTime; + Mode = mode; + Size = size; + UpdateFormatting(); + UpdateAccess(); + } + + internal void Update(string name) + { + if (!string.IsNullOrEmpty(name)) + { + Name = name; + } + } + + private void UpdateFormatting() + { + if (Extension != null) + Extension = Extension.ToLower(CultureInfo.CurrentCulture); + + if (NoAccess) + { + FormattedPermissions = "N/A"; + FormattedType = '-'; + } + else + { + FormattedType = GetTypeLetter(Type); + + StringBuilder result = new StringBuilder(); + + // append type: + result.Append(FormattedType); + + // append permissions (user/group/all): + const string AllPermissions = "xwr"; + uint permissions = Permissions; + int permissionIndex = 0; + + for (int i = 0; i < 9; i++) + { + result.Insert(1, (permissions & 1) == 1 ? AllPermissions[permissionIndex] : '-'); + + permissions >>= 1; + permissionIndex = (permissionIndex + 1) % AllPermissions.Length; + } + + FormattedPermissions = result.ToString(); + } + } + + private static char GetTypeLetter(uint type) + { + switch (type) + { + case TypeCharacterDevice: + return 'c'; + case TypeDirectory: + return 'd'; + case TypeNamedPipe: + return 'p'; + case TypeBlockDevice: + return 'b'; + case TypeRegularFile: + return '-'; + case TypeSymlink: + return 'l'; + case TypeSocket: + return 's'; + default: + throw new ArgumentOutOfRangeException("type", "Unrecognized file type (not a file, link nor folder)"); + } + } + + private void UpdateAccess() + { + NoAccess = NoAccess || (Type == TypeCharacterDevice); + } + + #region Path Management + + /// + /// Creates a path to item with a specified name (file or folder). + /// + public string CreateItemPath(string name) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + + return PathHelper.MakePath(Path, name); + } + + /// + /// Creates new path assuming that current item should change its name. + /// + public string CreateRenamedPath(string newName) + { + if (string.IsNullOrEmpty(newName)) + throw new ArgumentNullException("newName"); + + if (newName[0] == '/' || newName[0] == '\\') + { + return newName; + } + return PathHelper.MakePath(PathHelper.ExtractDirectory(Path), newName); + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/TargetFileDescriptor.cs b/src_vs2012/NativeCore/QConn/Model/TargetFileDescriptor.cs new file mode 100644 index 00000000..553384d6 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/TargetFileDescriptor.cs @@ -0,0 +1,89 @@ +using System; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Internal class wrapping the management of the handle used by target's File-System Service. + /// + sealed class TargetFileDescriptor : TargetFile, IDisposable + { + private TargetServiceFile _service; + + /// + /// Init constructor. + /// + public TargetFileDescriptor(TargetServiceFile service, string handle, uint mode, ulong size, uint flags, string path) + : base(mode, size, flags, path) + { + if (service == null) + throw new ArgumentNullException("service"); + + _service = service; + Handle = handle; + } + + ~TargetFileDescriptor() + { + Dispose(false); + } + + #region Properties + + public string Handle + { + get; + private set; + } + + public bool CanRead + { + get { return (Flags & ModeOpenReadOnly) == ModeOpenReadOnly; } + } + + public bool CanWrite + { + get { return (Flags & ModeOpenWriteOnly) == ModeOpenWriteOnly; } + } + + public bool IsClosed + { + get { return _service == null || string.IsNullOrEmpty(Handle); } + } + + #endregion + + #region IDisposable Implementation + + public void Close() + { + Dispose(); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (_service != null) + { + // ask the parental service to release the handle (it expects the Closed() to be called during service request): + _service.Close(this); + } + } + + #endregion + + /// + /// Notifies this instance, that the handle was released and is no more valid. + /// + internal void Closed() + { + _service = null; + Handle = null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/TargetLogEntry.cs b/src_vs2012/NativeCore/QConn/Model/TargetLogEntry.cs new file mode 100644 index 00000000..f58a4510 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/TargetLogEntry.cs @@ -0,0 +1,275 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using BlackBerry.NativeCore.Debugger.Model; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Log entry description. + /// + [DebuggerDisplay("{Message}")] + public sealed class TargetLogEntry + { + public enum LogType + { + Console, + SLog2 + } + + /// + /// Init constructor. + /// + private TargetLogEntry(LogType type, uint pid, string message) + { + Type = type; + PID = pid; + Message = message ?? string.Empty; + } + + /// + /// Init constructor. + /// + private TargetLogEntry(LogType type, uint pid, string appID, string bufferSet, string message) + { + Type = type; + PID = pid; + AppID = appID; + BufferSet = bufferSet; + Message = message ?? string.Empty; + } + + #region Properties + + /// + /// Gets the process ID issuing the log entry. + /// + public uint PID + { + get; + private set; + } + + public LogType Type + { + get; + private set; + } + + public string AppID + { + get; + private set; + } + + public string BufferSet + { + get; + private set; + } + + public string Message + { + get; + private set; + } + + #endregion + + /// + /// Converts the raw console outputs into featured log-class collection. + /// + public static TargetLogEntry[] ParseConsole(ProcessInfo process, string[] nativeLogEntries) + { + if (process == null) + throw new ArgumentNullException("process"); + + if (nativeLogEntries != null && nativeLogEntries.Length > 0) + { + var result = new TargetLogEntry[nativeLogEntries.Length]; + + for (int i = 0; i < nativeLogEntries.Length; i++) + { + result[i] = new TargetLogEntry(LogType.Console, process.ID, nativeLogEntries[i]); + } + + return result; + } + + return null; + } + + /// + /// Converts raw slog2 outputs into featured log-class collection. + /// + public static TargetLogEntry[] ParseSLog2(string[] nativeLogEntries) + { + if (nativeLogEntries != null && nativeLogEntries.Length > 0) + { + var result = new List(); + TargetLogEntry lastEntry = null; + + foreach (var nativeEntry in nativeLogEntries) + { + // ignore empty lines: + if (string.IsNullOrEmpty(nativeEntry)) + continue; + + var parsedEntry = ParseSLog2Entry(nativeEntry); + + if (parsedEntry != null) + { + lastEntry = parsedEntry; + result.Add(parsedEntry); + } + else + { + // is it a part of multiline message (like dump of PPS parameters, where each line is not prefixed with slog header): + if (lastEntry != null) + { + lastEntry.Message += Environment.NewLine + nativeEntry; + } + else + { + // or it's just orphan text (let the upper layer care about it): + result.Add(new TargetLogEntry(LogType.SLog2, 0, nativeEntry)); + } + } + } + + return result.Count > 0 ? result.ToArray() : null; + } + + return null; + } + + /// + /// Parses single line of slog2, which typically looks like following: + /// + /// Dec 04 03:05:54.970 com.codetitans.FallingBlocks.testDev_llingBlocksb07fdb40.383152370 default 8900 5 PPS helper destructor + /// + /// + private static TargetLogEntry ParseSLog2Entry(string nativeEntry) + { + int i; + + // skip month: + i = nativeEntry.IndexOf(' ', 0); + if (i < 0) + return null; + + // skip day: + i = nativeEntry.IndexOf(' ', i + 1); + if (i < 0) + return null; + + // skip time: + i = nativeEntry.IndexOf(' ', i + 1); + if (i < 0) + return null; + + // skip all white-chars: + if (SkipSpaces(nativeEntry, ref i)) + return null; + + // read the application-id + process-id: + int idEndAt = nativeEntry.IndexOf(' ', i + 1); + if (idEndAt < 0) + return null; + + string sandboxInfo = nativeEntry.Substring(i, idEndAt - i); + if (string.IsNullOrEmpty(sandboxInfo)) + return null; + + // jump to the beginning of the buffer name: + i = idEndAt; + if (SkipSpaces(nativeEntry, ref i)) + return null; + + int bufferSetStartAt = i; + int bufferSetEndAt = nativeEntry.IndexOf(' ', i + 1); + if (bufferSetEndAt < 0) + return null; + + i = bufferSetEndAt; + if (nativeEntry[bufferSetEndAt - 1] == '*') + bufferSetEndAt--; + + string bufferSetID = nativeEntry.Substring(bufferSetStartAt, bufferSetEndAt - bufferSetStartAt); + + // PH: this means, there is no bufferSet and we already read the first number + if (bufferSetID == "0") + { + bufferSetID = "default"; + } + else + { + // skip spaces till the first number: + if (SkipSpaces(nativeEntry, ref i)) + return null; + + // skip the first number: + i = nativeEntry.IndexOf(' ', i + 1); + if (i < 0) + return null; + } + + // move to the second number: + if (SkipSpaces(nativeEntry, ref i)) + return null; + + // skip the second number: + i = nativeEntry.IndexOf(' ', i + 1); + if (i < 0) + return null; + + // message is prefixed with two spaces: + if (i < nativeEntry.Length - 2) + i += 2; + + string message = nativeEntry.Substring(i); + string appID; + uint processID = SplitToProcessAndAppID(sandboxInfo, out appID); + return new TargetLogEntry(LogType.SLog2, processID, appID, bufferSetID, message); + } + + private static bool SkipSpaces(string text, ref int i) + { + while (i < text.Length && char.IsWhiteSpace(text[i])) + i++; + if (i == text.Length) + return true; + return false; + } + + private static uint SplitToProcessAndAppID(string text, out string appID) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException("text"); + + // card apps can spawn multiple instances of the same application + // then they share the same appID-base part, but end with ".." + int i = text.Length - 1; + int instanceSuffix = char.IsDigit(text[i]) && text[i - 1] == '.' && text[i - 2] == '.' ? 3 : 0; + int processIdStartAt = text.LastIndexOf('.', i - instanceSuffix); + + if (processIdStartAt < 0) + { + appID = text; + return 0; + } + + string processIdText = text.Substring(processIdStartAt + 1, i - instanceSuffix - processIdStartAt); + uint id; + + if (uint.TryParse(processIdText, out id)) + { + appID = text.Substring(0, processIdStartAt); + return id; + } + + appID = text; + return 0; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/TargetProcess.cs b/src_vs2012/NativeCore/QConn/Model/TargetProcess.cs new file mode 100644 index 00000000..c2025ef6 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/TargetProcess.cs @@ -0,0 +1,254 @@ +using System; +using System.Threading; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Class providing information about manually started process. + /// + public class TargetProcess : IDisposable + { + private TargetServiceLauncher _service; + private QConnConnection _connection; + private QDataSource _dataSource; + private bool _isSuspended; + private Thread _monitoringThread; + + public event EventHandler Finished; + + /// + /// Init constructor. + /// + public TargetProcess(TargetServiceLauncher service, QConnConnection connection, uint pid, bool suspended) + { + if (service == null) + throw new ArgumentNullException("service"); + if (connection == null) + throw new ArgumentNullException("connection"); + + _service = service; + _connection = connection; + PID = pid; + _isSuspended = suspended; + _monitoringThread = new Thread(MonitorProcessOutputs); + + StartOutputMonitoring(); + } + + ~TargetProcess() + { + Dispose(false); + } + + #region Properties + + /// + /// Checks, whether the specified command is suspended and expects Continue() to be called. + /// + public bool IsSuspended + { + get { return !_isSuspended; } + } + + /// + /// Gets an indication, if process already finished or connection was lost. + /// + public bool IsFinished + { + get { return _monitoringThread == null; } + } + + /// + /// Gets the ID of the process on target device. + /// + public uint PID + { + get; + private set; + } + + /// + /// Gets the exit code for this process. + /// + public uint ExitCode + { + get { return _service != null ? _service.GetExitCode(this) : uint.MaxValue; } + } + + #endregion + + /// + /// Resumes suspended process. + /// + public void Continue() + { + if (!_isSuspended) + throw new QConnException("Process with ID: " + PID + " is not suspended"); + + _connection.Send("continue"); + _isSuspended = false; + + StartOutputMonitoring(); + } + + /// + /// Waits until the process finishes. + /// + public void Join() + { + if (_monitoringThread != null) + { + _monitoringThread.Join(); + } + } + + #region IDisposable Implementation + + /// + /// Disposing used resources. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _service = null; + if (_connection != null) + { + _connection.Dispose(); + _connection = null; + } + + if (_dataSource != null) + { + _dataSource.Dispose(); + _dataSource = null; + } + + if (_monitoringThread != null) + { + _monitoringThread.Join(); + } + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + + private void StartOutputMonitoring() + { + // ignore this method, if process is suspended: + if (_isSuspended) + return; + + _dataSource = _connection.DetachDataSource(); + _dataSource.ReceiveTimeout = Timeout.Infinite; + _dataSource.SendTimeout = Timeout.Infinite; + _connection = null; // won't be needed anymore and was already disposed by the detach call + + _monitoringThread.Start(); + } + + private void MonitorProcessOutputs() + { + try + { + // wait until the process is started: + while (_isSuspended) + { + Thread.Sleep(500); + } + + // and then monitor its outputs: + ReadOutputs(); + } + catch (ThreadAbortException) + { + } + + // done... + _monitoringThread = null; + + if (Finished != null) + { + Finished(this, EventArgs.Empty); + } + + Dispose(); + } + + /// + /// Reads raw binary data from running processes output-stream. + /// + private void ReadOutputs() + { + ProcessOutputInitialize(); + + while (true) + { + if (_dataSource == null) + { + QTraceLog.WriteLine("!! Disposed data-source encountered"); + return; + } + + byte[] data; + var result = _dataSource.Receive(int.MaxValue, out data); + switch (result) + { + case HResult.OK: + + if (data != null && data.Length > 0) + { + // new data arrived, process it somehow: + if (ProcessOutputData(result, data)) + { + ProcessOutputDone(); + return; + } + } + break; + default: + QTraceLog.WriteLine("Finishing monitoring remote process outputs, result: " + result); + ProcessOutputDone(); + return; + } + } + } + + #region Virtual Methods + + /// + /// Method called once, when preparing to receive running processes output stream. + /// + protected virtual void ProcessOutputInitialize() + { + } + + /// + /// Method called in a loop to perform actions over received output data. + /// + protected virtual bool ProcessOutputData(HResult result, byte[] data) + { + return false; + } + + /// + /// Method called once, when cleaning up after running process terminated and no output data will be delivered. + /// + protected virtual void ProcessOutputDone() + { + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/TargetProcessSLog2Info.cs b/src_vs2012/NativeCore/QConn/Model/TargetProcessSLog2Info.cs new file mode 100644 index 00000000..9d3112f1 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/TargetProcessSLog2Info.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Text; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Class providing extra functionalities around running slog2info on a target device. + /// + public sealed class TargetProcessSLog2Info : TargetProcess + { + private byte[] _lastLine; + + public event EventHandler Captured; + + /// + /// Init constructor. + /// + public TargetProcessSLog2Info(TargetServiceLauncher service, QConnConnection connection, uint pid, bool suspended) + : base(service, connection, pid, suspended) + { + } + + #region IDisposable Implementation + + /// + /// Disposing used resources. + /// + protected override void Dispose(bool disposing) + { + Captured = null; + base.Dispose(disposing); + } + + #endregion + + #region Processing Console Output + + protected override void ProcessOutputInitialize() + { + _lastLine = null; + } + + protected override bool ProcessOutputData(HResult result, byte[] data) + { + if (Captured != null) + { + // new data arrived, split it into lines of text: + var logEntries = ReadLines(data, ref _lastLine); + + // then parse and forward them: + var targetLogs = TargetLogEntry.ParseSLog2(logEntries); + + if (targetLogs != null) + { + Captured(this, new CapturedLogsEventArgs(targetLogs)); + } + } + + return false; + } + + private string[] ReadLines(byte[] data, ref byte[] lastLine) + { + if (data == null || data.Length == 0) + return null; + + var result = new List(); + int lineStart = -1; + + for (int i = 0; i < data.Length; i++) + { + if (data[i] == 10) // '\n' + { + // is it the first line? + if (lineStart < 0) + { + AddString(result, GetString(lastLine, data, lineStart + 1, i)); + lastLine = null; + } + else + { + AddString(result, GetString(null, data, lineStart + 1, i - lineStart - 1)); + } + + // move the end of line marker: + lineStart = i + 1 < data.Length && data[i + 1] == 13 ? i + 1 : i; + } + } + + // the end of the message is not a properly finished new line: + if (lineStart < 0 || lineStart != data.Length - 1) + { + lastLine = BitHelper.Combine(lastLine, data, lineStart + 1, data.Length - lineStart - 1); + } + + return result.Count > 0 ? result.ToArray() : null; + } + + private void AddString(List result, string message) + { + if (message == null) + return; + + if (result.Count == 0 || string.Compare(result[result.Count - 1], message, StringComparison.Ordinal) != 0) + { + result.Add(message); + } + } + + private string GetString(byte[] lineStart, byte[] data, int dataFrom, int dataLength) + { + return Encoding.UTF8.GetString(BitHelper.Combine(lineStart, data, dataFrom, dataLength)); + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/TargetSystemType.cs b/src_vs2012/NativeCore/QConn/Model/TargetSystemType.cs new file mode 100644 index 00000000..e30174d7 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/TargetSystemType.cs @@ -0,0 +1,11 @@ +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Type of operating system. + /// + public enum TargetSystemType + { + Unknown, + Neutrino /* nto */ + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/Token.cs b/src_vs2012/NativeCore/QConn/Model/Token.cs new file mode 100644 index 00000000..3b5b792c --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/Token.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Part of the response received from a TargetFileService. + /// + public sealed class Token + { + private readonly string _token; + + /// + /// Init constructor. + /// + /// + public Token(string token) + { + if (token != null && token.Length >= 2 && token[0] == '"' && token[token.Length - 1] == '"') + _token = token.Substring(1, token.Length - 2); + else + _token = token ?? string.Empty; + } + + #region Properties + + /// + /// Gets the UInt32 value of the token. + /// + public uint UInt32Value + { + get { return uint.Parse(_token, NumberStyles.HexNumber); } + } + + /// + /// Gets the UInt64 value of the token. + /// + public ulong UInt64Value + { + get { return ulong.Parse(_token, NumberStyles.HexNumber); } + } + + /// + /// Gets the string value of the token (wrapping '"' will be removed). + /// + public string StringValue + { + get { return _token; } + } + + #endregion + + public override string ToString() + { + return _token; + } + + /// + /// Returns an array of tokens parsed from specified string. Each token ends with ':' delimiter. + /// + public static Token[] Parse(string text) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException("text"); + + var result = new List(); + bool isInString = false; + int startAt = 0; + + for (int i = 0; i < text.Length; i++) + { + if (text[i] == '"') + { + isInString = !isInString; + } + else + if (!isInString && text[i] == ':') + { + // ok, found end of token: + result.Add(new Token(text.Substring(startAt, i - startAt))); + startAt = i + 1; + } + } + + // and add the closing token, that has no delimiter: + result.Add(new Token(text.Substring(startAt, text.Length - startAt))); + return result.ToArray(); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/TransferOperation.cs b/src_vs2012/NativeCore/QConn/Model/TransferOperation.cs new file mode 100644 index 00000000..95404b2c --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/TransferOperation.cs @@ -0,0 +1,13 @@ +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Description of the transfer performed to or from the target. + /// + public enum TransferOperation + { + Unknown, + Buffering, + Downloading, + Uploading + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/VisitorCompletionEventArgs.cs b/src_vs2012/NativeCore/QConn/Model/VisitorCompletionEventArgs.cs new file mode 100644 index 00000000..757ee3ed --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/VisitorCompletionEventArgs.cs @@ -0,0 +1,41 @@ +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Arguments passed along with visitor transfer completion event. + /// + public sealed class VisitorCompletionEventArgs : VisitorEventArgs + { + /// + /// Init constructor. + /// + public VisitorCompletionEventArgs(object tag, TransferOperation operation, bool wasCancelled, int fileCount) + : base(tag) + { + Operation = operation; + WasCancelled = wasCancelled; + FileCount = fileCount; + } + + #region Properties + + public TransferOperation Operation + { + get; + private set; + } + + public bool WasCancelled + { + get; + private set; + } + + public int FileCount + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/VisitorEventArgs.cs b/src_vs2012/NativeCore/QConn/Model/VisitorEventArgs.cs new file mode 100644 index 00000000..52313142 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/VisitorEventArgs.cs @@ -0,0 +1,28 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Arguments passed along with visitor events. + /// + public class VisitorEventArgs : EventArgs + { + /// + /// Init constructor. + /// + public VisitorEventArgs(object tag) + { + Tag = tag; + } + + #region Properties + + public object Tag + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/VisitorFailureEventArgs.cs b/src_vs2012/NativeCore/QConn/Model/VisitorFailureEventArgs.cs new file mode 100644 index 00000000..b8940771 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/VisitorFailureEventArgs.cs @@ -0,0 +1,63 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Arguments passed along with a failure transfer event. + /// + public sealed class VisitorFailureEventArgs : VisitorEventArgs + { + /// + /// Init constructor. + /// + public VisitorFailureEventArgs(TargetFile descriptor, Exception exception, string message, object tag) + : base(tag) + { + if (string.IsNullOrEmpty(message)) + throw new ArgumentNullException("message"); + + Descriptor = descriptor; + Exception = exception; + Message = message; + } + + #region Properties + + public TargetFile Descriptor + { + get; + private set; + } + + public Exception Exception + { + get; + private set; + } + + public string Message + { + get; + private set; + } + + public string UltimateMassage + { + get + { + if (Exception != null) + return Exception.Message; + return Message; + } + } + + #endregion + + public override string ToString() + { + if (Exception != null) + return Exception.Message + Environment.NewLine + Message; + return Message; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Model/VisitorProgressChangedEventArgs.cs b/src_vs2012/NativeCore/QConn/Model/VisitorProgressChangedEventArgs.cs new file mode 100644 index 00000000..bbfbcd71 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Model/VisitorProgressChangedEventArgs.cs @@ -0,0 +1,72 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Model +{ + /// + /// Arguments passed when monitoring visitor's progress. + /// + public sealed class VisitorProgressChangedEventArgs : VisitorEventArgs + { + /// + /// Init constructor. + /// + public VisitorProgressChangedEventArgs(TargetFile source, string destination, string relativeDestination, ulong transferredBytes, int progress, TransferOperation operation, object tag) + : base(tag) + { + if (source == null) + throw new ArgumentNullException("source"); + if (string.IsNullOrEmpty(destination)) + throw new ArgumentNullException("destination"); + + Source = source; + Destination = destination; + Name = string.IsNullOrEmpty(relativeDestination) ? destination : relativeDestination; + TransferredBytes = transferredBytes; + Progress = progress; + Operation = operation; + } + + #region Properties + + public TargetFile Source + { + get; + private set; + } + + public string Destination + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public ulong TransferredBytes + { + get; + private set; + } + + /// + /// Gets progress indication (0-100). + /// + public int Progress + { + get; + private set; + } + + public TransferOperation Operation + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/QConnAuthenticationEventArgs.cs b/src_vs2012/NativeCore/QConn/QConnAuthenticationEventArgs.cs new file mode 100644 index 00000000..f45df80c --- /dev/null +++ b/src_vs2012/NativeCore/QConn/QConnAuthenticationEventArgs.cs @@ -0,0 +1,38 @@ +using System; + +namespace BlackBerry.NativeCore.QConn +{ + /// + /// Arguments passed along with QConnDoor authentication status changes. + /// + public sealed class QConnAuthenticationEventArgs : EventArgs + { + /// + /// Init constructor. + /// + public QConnAuthenticationEventArgs(QConnDoor service, bool isAuthenticated) + { + if (service == null) + throw new ArgumentNullException("service"); + + Service = service; + IsAuthenticated = isAuthenticated; + } + + #region Properties + + public QConnDoor Service + { + get; + private set; + } + + public bool IsAuthenticated + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/QConnClient.cs b/src_vs2012/NativeCore/QConn/QConnClient.cs new file mode 100644 index 00000000..3ea5181b --- /dev/null +++ b/src_vs2012/NativeCore/QConn/QConnClient.cs @@ -0,0 +1,363 @@ +using System; +using System.Collections.Generic; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn +{ + /// + /// Client to the QConn service running on target. + /// It requires QConnDoor to authorize secure connection, before this one can access it. + /// This class allows to perform some basic functionalities on target like: + /// * read info + /// * list/start/kill processes + /// * transfer files. + /// + public sealed class QConnClient : IDisposable + { + /// + /// Default port the QConn service is running on the target. + /// + public const int DefaultPort = 8000; + + /// + /// Default constructor. + /// + public QConnClient() + { + Services = new TargetService[0]; + } + + ~QConnClient() + { + Dispose(false); + } + + #region Properties + + public Endianess Endian + { + get; + private set; + } + + public TargetSystemType System + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public string Locale + { + get; + private set; + } + + public Version Version + { + get; + private set; + } + + public TargetService[] Services + { + get; + private set; + } + + public TargetServiceSysInfo SysInfoService + { + get; + private set; + } + + public TargetServiceControl ControlService + { + get; + private set; + } + + public TargetServiceFile FileService + { + get; + private set; + } + + public TargetServiceConsoleLog ConsoleLogService + { + get; + private set; + } + + public TargetServiceLauncher LauncherService + { + get; + private set; + } + + #endregion + + /// + /// Loads info about the target. + /// + public void Load(string host) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + + Load(host, DefaultPort, 0); + } + + /// + /// Loads info about the target and initializes properties. + /// + public void Load(string host, int port, int timeout) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + + using (var connection = new QConnConnection(host, port, timeout)) + { + // get info about the target: + var response = connection.Send("info"); + if (string.IsNullOrEmpty(response)) + throw new QConnException("Unable to load QConn info"); + + ParseInfoProperties(GetProperties(response)); + if (Endian == Endianess.Unknown) + throw new QConnException("Unable to determin endianess of the target"); + if (Version == null) + throw new QConnException("Unable to determin QConn version"); + + // list all available services: + response = connection.Send("service ?"); + if (string.IsNullOrEmpty(response)) + throw new QConnException("Unable to load QConn services"); + + string[] serviceNames = ParseServices(response.StartsWith("services: ") ? response.Substring(10) : response); + Services = CreateDefaultServices(connection, serviceNames, host, port); + } + } + + private TargetService[] CreateDefaultServices(QConnConnection connection, string[] serviceNames, string host, int port) + { + List services = new List(); + + FileService = null; + ConsoleLogService = null; + if (HasService(serviceNames, "file")) + { + FileService = new TargetServiceFile(GetServiceVersion(connection, "file"), new QConnConnection(host, port, "file", Endian)); + ConsoleLogService = new TargetServiceConsoleLog(FileService); + services.Add(FileService); + services.Add(ConsoleLogService); + } + + ControlService = null; + if (HasService(serviceNames, "cntl")) + { + ControlService = new TargetServiceControl(GetServiceVersion(connection, "cntl"), new QConnConnection(host, port, "cntl", Endian)); + services.Add(ControlService); + } + + SysInfoService = null; + if (HasService(serviceNames, "sinfo")) + { + SysInfoService = new TargetServiceSysInfo(GetServiceVersion(connection, "sinfo"), new QConnConnection(host, port, "sinfo", Endian)); + services.Add(SysInfoService); + } + + LauncherService = null; + if (HasService(serviceNames, "launcher")) + { + LauncherService = new TargetServiceLauncher(GetServiceVersion(connection, "launcher"), new QConnConnection(host, port, "launcher", Endian)); + services.Add(LauncherService); + } + + return services.ToArray(); + } + + private Version GetServiceVersion(QConnConnection connection, string name) + { + var version = connection.Send("version " + name); + if (string.IsNullOrEmpty(version)) + throw new QConnException("Unable to load version of \"" + name + "\" service"); + + uint numberVersion; + if (uint.TryParse(version, out numberVersion)) + { + var result = new Version((int)((numberVersion & 0xFF00) >> 8), (int)(numberVersion & 0xFF)); + QTraceLog.WriteLine("Loaded '{0}' version: {1} ({2})", name, result, version); + + return result; + } + + QTraceLog.WriteLine("Loaded '{0}' version: {1}", name, version); + throw new QConnException("Unable to parse version of \"" + name + "\" service"); + } + + /// + /// Checks, if given string belongs to collection. + /// + private static bool HasService(IEnumerable services, string name) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (services == null) + return false; + + foreach (var serviceName in services) + { + if (string.Compare(serviceName, name, StringComparison.OrdinalIgnoreCase) == 0) + return true; + } + + return false; + } + + private static string[] ParseServices(string text) + { + if (string.IsNullOrEmpty(text)) + return new string[0]; + + return text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + } + + private void ParseInfoProperties(Dictionary properties) + { + if (properties == null) + throw new ArgumentNullException("properties"); + + if (properties.ContainsKey("ENDIAN")) + { + Endian = ParseEndian(properties["ENDIAN"]); + } + if (properties.ContainsKey("OS")) + { + System = ParseSystem(properties["OS"]); + } + if (properties.ContainsKey("QCONN_VERSION")) + { + Version = ParseVersion(properties["QCONN_VERSION"]); + } + if (properties.ContainsKey("LOCALE")) + { + Locale = properties["LOCALE"]; + } + if (properties.ContainsKey("HOSTNAME")) + { + Name = properties["HOSTNAME"]; + } + } + + private static Version ParseVersion(string text) + { + if (string.IsNullOrEmpty(text)) + return null; + + // find second '.' + int i1 = text.IndexOf('.'); + if (i1 < 0) + return new Version(text + ".0"); // to force: x.0 + + int i2 = text.IndexOf('.', i1 + 1); + if (i2 < 0) + return new Version(text); + + return new Version(text.Substring(0, i2)); + } + + private static TargetSystemType ParseSystem(string text) + { + if (string.IsNullOrEmpty(text)) + return TargetSystemType.Unknown; + + if (string.Compare("nto", text, StringComparison.OrdinalIgnoreCase) == 0) + return TargetSystemType.Neutrino; + + return TargetSystemType.Unknown; + } + + private static Endianess ParseEndian(string text) + { + if (string.IsNullOrEmpty(text)) + return Endianess.Unknown; + + if (string.Compare("le", text, StringComparison.OrdinalIgnoreCase) == 0) + return Endianess.LittleEndian; + if (string.Compare("be", text, StringComparison.OrdinalIgnoreCase) == 0) + return Endianess.BigEndian; + + return Endianess.Unknown; + } + + /// + /// Converts space separated list of key=value items to dictionary. + /// + private static Dictionary GetProperties(string text) + { + if (string.IsNullOrEmpty(text)) + throw new ArgumentNullException("text"); + + var result = new Dictionary(); + var items = text.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var line in items) + { + int index = line.IndexOf('='); + if (index >= 0) + { + var key = line.Substring(0, index); + var value = line.Substring(index + 1); + result[key] = value; + } + } + + return result; + } + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + if (Services.Length > 0) + { + var servicesCopy = Services; + Services = new TargetService[0]; + + foreach (var s in servicesCopy) + { + s.Dispose(); + } + + SysInfoService = null; + ControlService = null; + FileService = null; + ConsoleLogService = null; + LauncherService = null; + } + } + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/QConnConnection.cs b/src_vs2012/NativeCore/QConn/QConnConnection.cs new file mode 100644 index 00000000..12df1ef0 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/QConnConnection.cs @@ -0,0 +1,435 @@ +using System; +using System.Text; +using BlackBerry.NativeCore.QConn.Model; + +namespace BlackBerry.NativeCore.QConn +{ + /// + /// Class responsible for keeping the connection and sending/receiving messages to/from QConn service running on target. + /// This service seeems to be just TELNET. + /// + public sealed class QConnConnection : IDisposable, ICloneable + { + private readonly string _host; + private readonly int _port; + private QDataSource _source; + private readonly Endianess _endian; + private readonly string _serviceName; + + /// + /// Init constructor. + /// + public QConnConnection(string host, int port, int timeout) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + + _host = host; + _port = port; + _source = new QDataSource(); + _endian = Endianess.Unknown; + + Open(timeout); + } + + /// + /// Init constructor. + /// + public QConnConnection(string host, int port, string serviceName, Endianess endian) + : this(host, port, 0, serviceName, endian) + { + } + + /// + /// Init constructor. + /// + public QConnConnection(string host, int port, int chunkSize, string serviceName, Endianess endian) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + + _host = host; + _port = port; + _source = new QDataSource(chunkSize); // chunkSize == 0 will fallback to default + _endian = endian; + _serviceName = serviceName; + } + + ~QConnConnection() + { + Dispose(false); + } + + #region Properties + + public bool IsConnected + { + get { return _source != null && _source.IsConnected; } + } + + public int SendTimeout + { + get { return _source != null ? _source.SendTimeout : 0; } + set + { + if (_source != null) + { + _source.SendTimeout = value; + } + } + } + + public int ReceiveTimeout + { + get { return _source != null ? _source.ReceiveTimeout : 0; } + set + { + if (_source != null) + { + _source.ReceiveTimeout = value; + } + } + } + + #endregion + + /// + /// Creates a new object that is a copy of the current instance. + /// + public object Clone() + { + if (_source == null) + throw new ObjectDisposedException("QConnConnection"); + + return Clone(_source.ChunkSize); + } + + /// + /// Creates a new object that is a copy of the current instance. + /// + public object Clone(int chunkSize) + { + if (_source == null) + throw new ObjectDisposedException("QConnConnection"); + + return new QConnConnection(_host, _port, chunkSize, _serviceName, _endian); + } + + /// + /// Opens the connection to target. + /// + public void Open() + { + Open(0); + } + + /// + /// Opens the connection to target. + /// + public void Open(int timeout) + { + if (_source == null) + throw new ObjectDisposedException("QConnConnection"); + + // no need to do anything, if already connected + if (IsConnected) + { + return; + } + + var status = _source.Connect(_host, _port, timeout); + if (status != HResult.OK) + throw new QConnException("Unable to connect to QConn service (" + status + ")"); + + // receive presentation info: + int length; + var response = Receive(out length); + if (string.IsNullOrEmpty(response) || string.CompareOrdinal(response, "QCONN") != 0) + throw new QConnException("Invalid service running on target"); + + // PH: HACK: strange, but looks like + // the initial invitation *sometimes* is split into two responses, + // where the second one is only 3-byte control instruction, that translates + // to an empty string, what we can simply ignore... + if (length < 10) + { + response = Receive(out length); + } + + if (!string.IsNullOrEmpty(_serviceName)) + { + response = Send("service " + _serviceName); + } + } + + /// + /// Closes connection to target. + /// + public void Close() + { + if (_source == null) + throw new ObjectDisposedException("QConnConnection"); + + var status = _source.Close(); + if (status != HResult.OK) + throw new QConnException("Unable to close connection to QConn service (" + status + ")"); + } + + #region Send-Receive + + /// + /// Sends a command that expects a string response. + /// It also does some response validation. + /// + public string Send(string command) + { + return Send(command, null, 0, 0, true); + } + + /// + /// Sends a command that expects a string response. + /// It also does some response validation. + /// + public string Post(string command) + { + return Send(command, null, 0, 0, false); + } + + /// + /// Sends a command with data attached that expects a string response. + /// It also does some response validation. + /// + public string Send(string command, byte[] data, int offset, int length, bool validateResponse) + { + if (_source == null) + throw new ObjectDisposedException("QConnConnection"); + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + if (data != null && offset >= data.Length) + throw new ArgumentOutOfRangeException("offset"); + if (data != null && length + offset > data.Length) + throw new ArgumentOutOfRangeException("length"); + if (data == null && length != 0) + throw new ArgumentOutOfRangeException("length"); + + Open(); + + // send request: + var serializedCommand = SerializeCommand(command, data, offset, length); + var status = _source.Send(serializedCommand); + if (status != HResult.OK) + { + throw new QConnException("Unable to send command \"" + command + "\""); + } + + // receive response: + int responseLength; + var response = Receive(out responseLength); + + // verify response: + if (string.IsNullOrEmpty(response)) + { + if (validateResponse) + throw new QConnException("Unknown response for command \"" + command + "\""); + return response; + } + + if (response.StartsWith("error ", StringComparison.OrdinalIgnoreCase)) + { + throw new QConnException("Command \"" + command + "\" finished with error: " + response.Substring(6)); + } + + return response; + } + + private static byte[] SerializeCommand(string command, byte[] data, int offset, int length) + { + var totalSize = Encoding.UTF8.GetByteCount(command) + 2 + length; + var result = new byte[totalSize]; + + // serialize command: + int resultOffset = Encoding.UTF8.GetBytes(command, 0, command.Length, result, 0); + + // serialize end of header: + result[resultOffset++] = 13; // \r + result[resultOffset++] = 10; // \n + + // serialize additional data: + if (data != null) + { + Array.Copy(data, offset, result, resultOffset, length); + } + + return result; + } + + /// + /// Sends a command that will parse raw response. + /// + public IDataReader Request(string command) + { + if (_source == null) + throw new ObjectDisposedException("QConnConnection"); + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + Open(); + + // send request: + var status = _source.Send(SerializeCommand(command, null, 0, 0)); + if (status != HResult.OK) + { + throw new QConnException("Unable to send command \"" + command + "\""); + } + + // get response as proper stream-reader object with given endianess support: + if (_endian == Endianess.LittleEndian) + return new DataReaderLittleEndian(_source); + return new DataReaderBigEndian(_source); + } + + private string Receive(out int length) + { + // read all data: + byte[] data; + + do + { + var status = _source.Receive(int.MaxValue, out data); + length = data.Length; + + //QTraceLog.WriteLine("Received response: {0} ({1})", data.Length, status); + + if (status != HResult.OK) + return null; + } while (length == 2 && data[0] == '\r' && data[1] == '\n'); + + return ResponseToString(data); + } + + /// + /// Removes the data-source from current connection and disposes it. + /// This is a dedicated method for accessing remote process outputs/inputs directly (see: TargetProcess) and nothing else is suppose to use it. + /// + internal QDataSource DetachDataSource() + { + // get response as proper stream-reader object with given endianess support: + var result = _source; + _source = null; + + // this will make the connection object useless, throwing ObjectAlreadyDisposed() exceptions an each usage... + Dispose(); + return result; + } + + /// + /// Converts raw response to string object, removing all controls chars and any types of TELNET negotiations. + /// + private static string ResponseToString(byte[] data) + { + const byte IAC = 255; + const byte DONT = 254; + const byte DO = 253; + const byte WONT = 252; + const byte WILL = 251; + const byte SB = 250; + const byte SE = 240; + + int length = 0; + + int state = 0; + for (int i = 0; i < data.Length && (state != 0 || i == 0 || data[i - 1] != 10); i++) + { + byte c = data[i]; + + switch (state) + { + case 0: + if (c == IAC) + { + state = 1; + } + else + { + data[length++] = data[i]; + } + break; + case 1: + switch (c) + { + case IAC: + data[length++] = data[i]; + state = 0; + break; + case WILL: + case WONT: + case DO: + case DONT: + state = 2; + break; + case SB: + state = 3; + break; + default: + state = 0; + break; + } + break; + case 2: + state = 0; + break; + case 3: + if (c == IAC) + { + state = 4; + } + break; + case 4: + if (c == SE) + { + state = 0; + } + else + { + state = 3; + } + break; + } + } + + // remove the "\r\n" from the end of the text: + if (length >= 2 && data[length - 2] == 13 && data[length - 1] == 10) + length -= 2; + + return length > 0 ? Encoding.UTF8.GetString(data, 0, length) : string.Empty; + } + + #endregion + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + if (_source != null) + { + _source.Dispose(); + _source = null; + } + } + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/QConnDoor.cs b/src_vs2012/NativeCore/QConn/QConnDoor.cs new file mode 100644 index 00000000..fab91f9a --- /dev/null +++ b/src_vs2012/NativeCore/QConn/QConnDoor.cs @@ -0,0 +1,561 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Threading; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Requests; +using BlackBerry.NativeCore.QConn.Response; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.QConn +{ + /// + /// Manager class that connects securely with a target device and allows several unsecured connections. + /// It requires a public SSH key (4kB) and a device password. + /// + public sealed class QConnDoor : IDisposable + { + /// + /// Default port the service is operating on the device. + /// + public const int DefaultPort = 4455; + /// + /// Default interval for sending keep-alive command. + /// + public const int DefaultKeepAliveInterval = 5000; + private const int DefaultResponseSize = 255; + + private QDataSource _source; + private readonly object _lock; + private Timer _keepAliveTimer; + private bool _isAuthenticated; + private bool _didNotified; + + /// + /// Event raised each time status of an encrypted-channel to target is changed. + /// + public event EventHandler Authenticated; + + /// + /// Default constructor. + /// + public QConnDoor() + { + _source = new QDataSource(); + _lock = new object(); + } + + ~QConnDoor() + { + Dispose(false); + } + + #region Properties + + /// + /// Gets an indication, if connection to target has been established. + /// + public bool IsConnected + { + get { return _source != null && _source.IsConnected; } + } + + /// + /// Gets an indication, if secured communication channel has been established to the device and SSH keys are transmitted. + /// + public bool IsAuthenticated + { + get { return IsConnected && _isAuthenticated; } + } + + /// + /// Gets or sets the event dispatcher responsible for thread managment of raised events. + /// + public IEventDispatcher EventDispatcher + { + get; + set; + } + + #endregion + + /// + /// Closes connection with current target. + /// + public void Close() + { + if (_source == null) + throw new ObjectDisposedException("QConnDoor"); + + KeepAlive(0); // stop keep-alive timer + + if (!_source.IsConnected) + { + NotifyAuthenticationChanged(false); + return; + } + + // request a close of the connection on target: + Send(new SecureTargetCloseRequest()); + // ignore the result of CLOSE-request... + + // close connection: + var result = _source.Close(); + QTraceLog.WriteLine("Disconnected from target {0}", _source); + + NotifyAuthenticationChanged(false); + if (result != HResult.OK) + throw new SecureTargetConnectionException(HResult.Fail, "Unable to close connection with target"); + + _didNotified = false; + } + + /// + /// Authenticates on a target. + /// + public void Open(string host, int port, string password, string sshPublicKeyFileName) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (string.IsNullOrEmpty(sshPublicKeyFileName)) + throw new ArgumentNullException("sshPublicKeyFileName"); + + Open(host, port, password, File.ReadAllBytes(sshPublicKeyFileName)); + } + + /// + /// Authenticates on a target. + /// + public void Open(string host, string password, string sshPublicKeyFileName) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (string.IsNullOrEmpty(sshPublicKeyFileName)) + throw new ArgumentNullException("sshPublicKeyFileName"); + + Open(host, DefaultPort, password, File.ReadAllBytes(sshPublicKeyFileName)); + } + + /// + /// Authenticates on a target. + /// + public void Open(string host, int port, string password, byte[] sshKey) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (sshKey == null || sshKey.Length == 0) + throw new ArgumentNullException("sshKey"); + + if (_source == null) + throw new ObjectDisposedException("QConnDoor"); + + // is already connected? + if (IsAuthenticated) + return; + + var result = _source.Connect(host, port, 0); + if (result != HResult.OK) + { + QTraceLog.WriteLine("Failed to connect to target"); + throw new SecureTargetConnectionException(result, string.Concat("Unable to connect to target ", host, ":", port)); + } + + // try to initialize communication: + Execute(new SecureTargetHelloRequest()); + + RSAParameters publicKey; + RSAParameters privateKey; + + using (var rsa = new RSACryptoServiceProvider(1024)) + { + try + { + // don't store any keys in persistent storages of current Windows account: + rsa.PersistKeyInCsp = false; + + publicKey = rsa.ExportParameters(false); + privateKey = rsa.ExportParameters(true); + // more info about parameters and their meaning is here: + // http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters%28v=vs.90%29.aspx + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Unable to generate encryption keys"); + throw new SecureTargetConnectionException(HResult.Fail, "Unable to generate encryption key"); + } + } + + // initialize encryption negotiation: + var response = Execute(new SecureTargetChallengeRequest(publicKey.Modulus)); + + var encryptedChallenge = response as SecureTargetEncryptedChallengeResponse; + if (encryptedChallenge == null) + { + QTraceLog.WriteLine("Unexpected response for encryption challenge"); + throw new SecureTargetConnectionException(HResult.Fail, "Unexpected response for encryption challenge"); + } + + if (encryptedChallenge.Challenge.ExpectedSignatureType != 1) + { + throw new Exception("Invalid signature type in encryption challenge: 0x" + encryptedChallenge.Challenge.ExpectedSignatureType.ToString("X4")); + } + + // decrypt the message: + var decryptedChallenge = encryptedChallenge.Challenge.Decrypt(publicKey, privateKey); + if (decryptedChallenge == null) + { + throw new SecureTargetConnectionException(HResult.Fail, "Unable to decipher encryption challenge data"); + } + + if (encryptedChallenge.Challenge.ExpectedSignatureLength != decryptedChallenge.Signature.Length) + { + throw new Exception("Invalid signature length in encryption challenge: " + encryptedChallenge.Challenge.ExpectedSignatureLength); + } + + // confirm encrypted channel: + response = Execute(new SecureTargetDecryptedChallengeRequest(decryptedChallenge.DecryptedBlob, decryptedChallenge.Signature, decryptedChallenge.SessionKey)); + + if (!(response is SecureTargetFeedbackNoPasswordRequired)) + { + // prepare for sending password and ssh-public-key: + response = Execute(new SecureTargetAuthenticateChallengeRequest()); + + var authenticateResponse = response as SecureTargetAuthenticateChallengeResponse; + if (authenticateResponse == null) + { + throw new SecureTargetConnectionException(HResult.InvalidFrameCode, "Authentication negotiation failed"); + } + + // send password-hash: + Execute(new SecureTargetAuthenticateRequest(password, authenticateResponse.Algorithm, authenticateResponse.Iterations, authenticateResponse.Salt, authenticateResponse.Challenge, + decryptedChallenge.SessionKey)); + QTraceLog.WriteLine("Successfully authenticated with target credentials."); + } + + // send ssh-key: + QTraceLog.WriteLine("Sending ssh key to target"); + Execute(new SecureTargetSendSshPublicKeyRequest(sshKey, decryptedChallenge.SessionKey)); + + // and start all services on target: + Execute(new SecureTargetStartServicesRequest()); + + QTraceLog.WriteLine("Successfully connected. This application must remain running in order to use debug tools. Exiting the application will terminate this connection."); + NotifyAuthenticationChanged(true); + } + + /// + /// Asynchronously tries to authenticate on a target. + /// + public void OpenAsync(string host, string password, string sshPublicKeyFileName) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (string.IsNullOrEmpty(sshPublicKeyFileName)) + throw new ArgumentNullException("sshPublicKeyFileName"); + + OpenAsync(host, DefaultPort, password, File.ReadAllBytes(sshPublicKeyFileName)); + } + + /// + /// Asynchronously tries to authenticate on a target. + /// + public void OpenAsync(string host, int port, string password, byte[] sshKey) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (sshKey == null || sshKey.Length == 0) + throw new ArgumentNullException("sshKey"); + + if (_source == null) + throw new ObjectDisposedException("QConnDoor"); + + // is already connected? + if (IsAuthenticated) + return; + + var action = new Action(Open); + action.BeginInvoke(host, port, password, sshKey, OpenAsyncCompleted, action); + } + + private void OpenAsyncCompleted(IAsyncResult ar) + { + var action = (Action)ar.AsyncState; + + try + { + action.EndInvoke(ar); + } + catch + { + NotifyAuthenticationChanged(false); + } + } + + /// + /// Sends single keep-alive request to the target. + /// Without it the secured and unsecured connections will be automatically closed by the target. + /// Suggestion is to transmit this request each 5sec. + /// See overloaded method, where you can specify the interval to have it sent automatically. + /// + public void KeepAlive() + { + if (_source == null) + throw new ObjectDisposedException("QConnDoor"); + if (!IsAuthenticated) + throw new SecureTargetConnectionException(HResult.Fail, "Not authenticated to target, call Connect() first"); + + var response = InternalSendKeepAlive(); + VerifyResponse(response); + + QTraceLog.WriteLine("Keep-alive confirmed from {0} - [OK]", _source); + } + + /// + /// Starts a timer issuing a keep-alive request to the target on given internals. + /// It will stop only, if connection is closed or when this method is invoked with zero. + /// + /// Number of milliseconds the keep-alive request should be issued + public void KeepAlive(uint millisecInterval) + { + if (_source == null) + throw new ObjectDisposedException("QConnDoor"); + + // stop the timer, if running: + if (millisecInterval == 0) + { + lock (_lock) + { + if (_keepAliveTimer != null) + { + _keepAliveTimer.Dispose(); + _keepAliveTimer = null; + } + } + + return; + } + + if (!IsAuthenticated) + throw new SecureTargetConnectionException(HResult.Fail, "Not authenticated to target, call Connect() first"); + + // start or update the timer: + lock (_lock) + { + if (_keepAliveTimer == null) + _keepAliveTimer = new Timer(OnAliveTick, this, millisecInterval, millisecInterval); + else + _keepAliveTimer.Change(0, millisecInterval); + } + } + + private void OnAliveTick(object state) + { + var response = InternalSendKeepAlive(); + + // did the delivery failed? + if (response == null || response.Status != HResult.OK) + { + // stop the timer, as no more needed: + lock (_lock) + { + if (_keepAliveTimer != null) + { + _keepAliveTimer.Dispose(); + _keepAliveTimer = null; + } + } + + // and notify about failure: + QTraceLog.WriteLine("Failed to deliver keep-alive request to target {0} ({1})", _source, response != null ? response.ToString() : "Connection already closed"); + NotifyAuthenticationChanged(false); + } + else + { + QTraceLog.WriteLine("Keep-alive confirmed from {0} - [OK]", _source); + } + } + + /// + /// Sends keep-alive request to the target and returns its response. + /// + private SecureTargetResult InternalSendKeepAlive() + { + if (!IsAuthenticated) + return null; + + QTraceLog.WriteLine("Sending keep-alive"); + + try + { + Send(new SecureTargetKeepAliveRequest()); + return Receive(); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Unable to send keep-alive request"); + return null; + } + } + + /// + /// Sends specified requests, waits for response and verifies it. + /// + private SecureTargetResult Execute(SecureTargetRequest request) + { + Send(request); + var response = Receive(); + + VerifyResponse(response); + return response; + } + + private void Send(SecureTargetRequest request) + { + if (request == null) + throw new ArgumentNullException("request"); + if (_source == null) + throw new ObjectDisposedException("QConnDoor"); + + _source.Send(request.GetData()); + } + + private SecureTargetResult Receive() + { + if (_source == null) + throw new ObjectDisposedException("QConnDoor"); + + byte[] result; + var status = _source.Receive(DefaultResponseSize, out result); + + if (result != null && result.Length > 0) + { + ushort packetLength = BitHelper.BigEndian_ToUInt16(result, 0); + + // PH: HINT: don't know why, but on PlayBook packageLength doesn't correctly + // define the number of bytes received, that's why we compare it with buffer; + // on Z10 and Z30 the packageLength equals returned result.Length + if (packetLength > DefaultResponseSize) + { + QTraceLog.WriteLine("Packet length larger than buffer, expected size: " + packetLength); + return new SecureTargetResult(result, HResult.BufferTooSmall); + } + } + + // interpret response: + return SecureTargetResult.Load(result, status); + } + + /// + /// Verifies correctness of the response and throws appropriate exception if needed. + /// + private void VerifyResponse(SecureTargetResult result) + { + // received anything? + if (result == null) + { + throw new SecureTargetConnectionException(HResult.Abort, "No response received in expected time"); + } + + // does the protocol version match? + var versionMismatch = result as SecureTargetFeedbackMismatchedVersion; + if (versionMismatch != null) + { + throw new SecureTargetConnectionException(result.Status, versionMismatch.Message); + } + + // request was rejected? + var rejected = result as SecureTargetFeedbackRejected; + if (rejected != null) + { + throw new SecureTargetConnectionException(result.Status, "Connection refused: " + rejected.Reason); + } + + // received correctly formatted response? + if (result.Status != HResult.OK) + { + // unknown response? + var response = result as SecureTargetResponse; + if (response != null && result.Status == HResult.InvalidFrameCode) + { + throw new SecureTargetConnectionException(result.Status, "The target returned an improper response code: " + response.Code); + } + + throw new SecureTargetConnectionException(result.Status, "A network error occurred while communicating with the target."); + } + + // all was OK... finally! + } + + private void NotifyAuthenticationChanged(bool isAuthenticated) + { + if (isAuthenticated != _isAuthenticated || !_didNotified) + { + _didNotified = true; + _isAuthenticated = isAuthenticated; + + // notify using dispatcher or just by calling handlers from the same thread: + var dispatcher = EventDispatcher; + if (dispatcher != null) + { + dispatcher.Invoke(Authenticated, this, new QConnAuthenticationEventArgs(this, _isAuthenticated)); + } + else + { + var handler = Authenticated; + if (handler != null) + { + handler(this, new QConnAuthenticationEventArgs(this, _isAuthenticated)); + } + } + } + } + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + // stop sending keep-alive: + if (_keepAliveTimer != null) + { + _keepAliveTimer.Dispose(); + _keepAliveTimer = null; + } + + // release data-source: + if (_source != null) + { + Close(); + _source = null; + } + + // clear handlers: + Authenticated = null; + } + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/QConnException.cs b/src_vs2012/NativeCore/QConn/QConnException.cs new file mode 100644 index 00000000..3744ba08 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/QConnException.cs @@ -0,0 +1,18 @@ +using System; + +namespace BlackBerry.NativeCore.QConn +{ + /// + /// Exception thrown by QConnClient, in case of any errors. + /// + public sealed class QConnException : Exception + { + /// + /// Init constructor. + /// + public QConnException(string message) + : base(message) + { + } + } +} diff --git a/src_vs2012/NativeCore/QConn/QDataSource.cs b/src_vs2012/NativeCore/QConn/QDataSource.cs new file mode 100644 index 00000000..9ace409b --- /dev/null +++ b/src_vs2012/NativeCore/QConn/QDataSource.cs @@ -0,0 +1,353 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn +{ + /// + /// Class transmitting data to and back from QNX services on the device. + /// + public sealed class QDataSource : IDisposable + { + private const string DefaultDescription = "Disconnected"; + private const int Timeout = 10000; + private const int DefaultChunkSize = 512; + + private Socket _socket; + private byte[] _buffer; + private readonly int _chunkSize; + private string _description; + + /// + /// Default constructor. + /// + public QDataSource() + { + _chunkSize = DefaultChunkSize; + _description = DefaultDescription; + } + + /// + /// Init constructor. + /// Defines the chunk size, data from socket is read. + /// + public QDataSource(int chunkSize) + { + if (chunkSize < 0) + throw new ArgumentOutOfRangeException("chunkSize"); + _chunkSize = chunkSize == 0 ? DefaultChunkSize : chunkSize; + _description = DefaultDescription; + } + + ~QDataSource() + { + Dispose(false); + } + + #region Properties + + public bool IsConnected + { + get { return _socket != null && _socket.Connected; } + } + + /// + /// Gets the size of the data read chunk. + /// + public int ChunkSize + { + get { return _chunkSize; } + } + + /// + /// Gets or sets the sending data timeout. + /// Caution: any negative value will disable the timeout. + /// + public int SendTimeout + { + get { return _socket != null ? _socket.SendTimeout : 0; } + set + { + if (_socket != null) + { + _socket.SendTimeout = value == 0 ? Timeout : (value < 0 ? System.Threading.Timeout.Infinite: value); + } + } + } + + /// + /// Gets or sets the receiving data timeout. + /// Caution: any negative value will disable the timeout. + /// + public int ReceiveTimeout + { + get { return _socket != null ? _socket.ReceiveTimeout : 0; } + set + { + if (_socket != null) + { + _socket.ReceiveTimeout = value == 0 ? Timeout : (value < 0 ? System.Threading.Timeout.Infinite : value); + } + } + } + + #endregion + + /// + /// Establish data connection with a target. + /// + public HResult Connect(string host, int port, int timeout) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException("host"); + + bool connected = IsConnected; + if (!connected) + { + try + { + _description = DefaultDescription; + _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _socket.SendTimeout = Timeout; + _socket.ReceiveTimeout = Timeout; + _socket.DontFragment = true; + _socket.NoDelay = true; // don't combine small TCP packets into one, just send them immediately as data to transmit was given + + // don't want to use synchronous version of _socket.Connect(host, port) as this will block for undefined amount of seconds + //_socket.Connect(host, port); + + if (timeout <= 0) + { + timeout = Timeout; + } + + var asyncResult = _socket.BeginConnect(host, port, null, null); + var success = asyncResult.AsyncWaitHandle.WaitOne(timeout, true); + + if (!success) + { + _socket.Dispose(); + _description = DefaultDescription; + QTraceLog.WriteLine("Unable to establish connection to: {0}:{1} with timeout {2} ms", host, port, timeout); + return HResult.Fail; + } + + // make sure, the object is listed on the finalizers thread, + // in case multiple times connection was opened and closed... + GC.ReRegisterForFinalize(this); + _description = host; + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Unable to establish connection to: {0}:{1}", host, port); + return HResult.Fail; + } + } + + return HResult.OK; + } + + /// + /// Closes the data connection. + /// + public HResult Close() + { + Dispose(true); + return HResult.OK; + } + + /// + /// Sends data to the target. + /// + public HResult Send(byte[] data) + { + if (data == null) + throw new ArgumentNullException("data"); + + if (!IsConnected) + { + QTraceLog.WriteLine("Attempt to write to closed source"); + return HResult.Fail; + } + + // allocate new temp buffer for data: + if (_buffer == null) + { + _buffer = new byte[_chunkSize]; + } + + try + { + // remove any available data from 'previous' requests: + while (_socket.Available > 0) + { + _socket.Receive(_buffer); + } + + // issue new request: + int sent = _socket.Send(data); + if (sent < 0) + { + QTraceLog.WriteLine("Unable to send data"); + return HResult.Fail; + } + if (sent != data.Length) + { + QTraceLog.WriteLine("Invalid number of bytes send ({0} instead of {1})", sent, data.Length); + return HResult.Fail; + } + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Failed to send data"); + Close(); + return HResult.Fail; + } + + return HResult.OK; + } + + /// + /// Reads specified amount of available data from target. + /// MaxLength parameter serves only as a suggestion here. It might happen, + /// that result will be smaller than maxLength, but for sure, it won't return a bigger buffer. + /// + /// That's why there are two possible usages: + /// - to call this method with int.MaxValue to just read *all* available data + /// - or with small value, to only get, what is currently needed for processing and leave the rest for next Receive() request. + /// + public HResult Receive(int maxLength, out byte[] result) + { + if (!IsConnected) + { + QTraceLog.WriteLine("Attempt to read data from closed source"); + result = new byte[0]; + return HResult.Fail; + } + + // allocate new temp buffer for data: + if (_buffer == null) + { + _buffer = new byte[_chunkSize]; + } + + // PH: hint: + // The idea of following code is to try at least once to perform a read of the data from the socket. + // Then it will loop and simply stop, when there is nothing more available. + // + // There are few optimizations implemented. Reading is done in chunks. If somehow the expected maxLength + // equals the chunk size, the local array will be returned (to avoid copying) and forget. + // In any other case, the result data is a new array filled with data copied from buffer and previously read chunks. + try + { + int totalLength = 0; + int length; + List extraBytes = null; + + while (true) + { + length = _socket.Receive(_buffer, 0, _buffer.Length, SocketFlags.None); + + // reading failed? + if (length < 0 || _socket == null) + { + break; + } + + totalLength += length; + + // read enough or whole data? + if (totalLength >= maxLength || _buffer.Length != length || (_socket != null && _socket.Available == 0)) + { + break; + } + + // store read data and alloc new buffer for next chunk: + if (extraBytes == null) + { + extraBytes = new List(); + } + extraBytes.Add(_buffer); + _buffer = new byte[_chunkSize]; + } + + // read the data correctly? + if (length <= 0) + { + if (extraBytes == null) + { + QTraceLog.WriteLine("Unable to read data"); + result = new byte[0]; + return HResult.Fail; + } + + // last buffer reading failed, then combine all other extra bytes: + result = BitHelper.Combine(extraBytes, null, 0); + } + else + { + // did we read exactly, what was expected? + if (length == totalLength && length == _buffer.Length && extraBytes == null) + { + result = _buffer; + _buffer = null; + } + else + { + // or just combine all results: + result = BitHelper.Combine(extraBytes, _buffer, length); + } + } + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Failed to read data"); + result = new byte[0]; + return HResult.Fail; + } + + return HResult.OK; + } + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + Dispose(true); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + if (_socket != null) + { + try + { + _socket.Close(); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Unable to close connection"); + } + + _socket = null; + } + _buffer = null; + } + } + + #endregion + + public override string ToString() + { + return _description; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetAuthenticateChallengeRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetAuthenticateChallengeRequest.cs new file mode 100644 index 00000000..a71eb476 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetAuthenticateChallengeRequest.cs @@ -0,0 +1,21 @@ +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request to initiate password and SSH-public key exchange. + /// + sealed class SecureTargetAuthenticateChallengeRequest : SecureTargetRequest + { + /// + /// Default constructor. + /// + public SecureTargetAuthenticateChallengeRequest() + : base(8) + { + } + + protected override byte[] GetPayload() + { + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetAuthenticateRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetAuthenticateRequest.cs new file mode 100644 index 00000000..e1e79b35 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetAuthenticateRequest.cs @@ -0,0 +1,120 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request to send password to the target. + /// + sealed class SecureTargetAuthenticateRequest : SecureTargetEncryptedRequest + { + /// + /// Init constructor. + /// + public SecureTargetAuthenticateRequest(string devicePassword, uint algorithm, uint iterations, byte[] salt, byte[] challenge, byte[] sessionKey) + : base(10, sessionKey) + { + if (string.IsNullOrEmpty(devicePassword)) + throw new ArgumentNullException("devicePassword"); + if (salt == null || salt.Length == 0) + throw new ArgumentNullException("salt"); + + var hashedPassword = SecurePassword(Encoding.UTF8.GetBytes(devicePassword), algorithm, iterations, salt, challenge); + HashedPassword = Encoding.UTF8.GetBytes(BitHelper.Enconde(hashedPassword)); + } + + #region Properties + + public byte[] HashedPassword + { + get; + private set; + } + + #endregion + + protected override byte[] GetUnencryptedPayload() + { + var payload = new Byte[2 + HashedPassword.Length]; + + BitHelper.BigEndian_Set(payload, 0, (ushort)HashedPassword.Length); + Array.Copy(HashedPassword, 0, payload, 2, HashedPassword.Length); + + return payload; + } + + private static byte[] SHA1(byte[] data) + { + using (var sha = new SHA1CryptoServiceProvider()) + { + return sha.ComputeHash(data); + } + } + + private static byte[] SHA512(byte[] data) + { + using (var sha = new SHA512CryptoServiceProvider()) + { + return sha.ComputeHash(data); + } + } + + private static byte[] SecurePassword(byte[] password, uint algorithm, uint iterations, byte[] salt, byte[] challenge) + { + byte[] hash; + + if (algorithm == 0) + { + // SHA1 + hash = SHA1(password); + } + else + { + hash = CalculateHashV2(password, algorithm, iterations, salt); + } + + // apply challenge: + if (challenge.Length > 0) + { + var buffer = new byte[challenge.Length + hash.Length]; + BitHelper.Copy(buffer, 0, challenge, hash); + if (algorithm == 0) + { + hash = SHA1(buffer); + } + else + { + hash = CalculateHashV2(buffer, algorithm, iterations, salt); + } + } + + return hash; + } + + private static byte[] CalculateHashV2(byte[] password, uint algorithm, uint iterations, byte[] salt) + { + uint count = 0; + + byte[] hashedData = password; + do + { + var buffer = new byte[4 + salt.Length + hashedData.Length]; + BitHelper.LittleEndian_Set(buffer, 0, count); + BitHelper.Copy(buffer, 4, salt, hashedData); + + if (algorithm == 1) + { + hashedData = SHA1(buffer); + } + else if (algorithm == 2) + { + hashedData = SHA512(buffer); + } + count++; + } while (count < iterations); + return hashedData; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetChallengeRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetChallengeRequest.cs new file mode 100644 index 00000000..3c212176 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetChallengeRequest.cs @@ -0,0 +1,43 @@ +using System; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request to initiate session-key and exchange of RSA public key with target. + /// + sealed class SecureTargetChallengeRequest : SecureTargetRequest + { + /// + /// Init constructor. + /// + public SecureTargetChallengeRequest(byte[] publicRsaKey) + : base(3) + { + if (publicRsaKey == null || publicRsaKey.Length == 0) + throw new ArgumentNullException("publicRsaKey"); + + PublicRsaKey = publicRsaKey; + } + + #region Properties + + public byte[] PublicRsaKey + { + get; + private set; + } + + #endregion + + protected override byte[] GetPayload() + { + var payload = new byte[2 + PublicRsaKey.Length]; + + BitHelper.BigEndian_Set(payload, 0, (ushort) PublicRsaKey.Length); + Array.Copy(PublicRsaKey, 0, payload, 2, PublicRsaKey.Length); + + return payload; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetCloseRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetCloseRequest.cs new file mode 100644 index 00000000..f7348f5f --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetCloseRequest.cs @@ -0,0 +1,22 @@ +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request to close the communication channel on target side. + /// + sealed class SecureTargetCloseRequest : SecureTargetRequest + { + /// + /// Default constructor. + /// + public SecureTargetCloseRequest() + : base(12) + { + } + + protected override byte[] GetPayload() + { + // nothing extra to send to target + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetDecryptedChallengeRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetDecryptedChallengeRequest.cs new file mode 100644 index 00000000..3e952c7e --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetDecryptedChallengeRequest.cs @@ -0,0 +1,53 @@ +using System; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request confirming used RSA keys and establishing secured communication channel. + /// + sealed class SecureTargetDecryptedChallengeRequest : SecureTargetEncryptedRequest + { + /// + /// Init constructor. + /// + public SecureTargetDecryptedChallengeRequest(byte[] decryptedBlob, byte[] signature, byte[] sessionKey) + : base(5, sessionKey) + { + if (decryptedBlob == null || decryptedBlob.Length == 0) + throw new ArgumentNullException("decryptedBlob"); + if (signature == null || signature.Length == 0) + throw new ArgumentNullException("signature"); + + DecryptedBlob = decryptedBlob; + Signature = signature; + } + + #region Properties + + public byte[] DecryptedBlob + { + get; + private set; + } + + public byte[] Signature + { + get; + private set; + } + + #endregion + + protected override byte[] GetUnencryptedPayload() + { + var result = new byte[12 + DecryptedBlob.Length + Signature.Length]; + + BitHelper.BigEndian_Set(result, 0, (ushort) (4 + DecryptedBlob.Length + Signature.Length)); + BitHelper.BigEndian_Set(result, 2, (ushort) DecryptedBlob.Length); + BitHelper.BigEndian_Set(result, 4, (ushort) Signature.Length); + BitHelper.Copy(result, 6, DecryptedBlob, Signature); + return result; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetEncryptedRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetEncryptedRequest.cs new file mode 100644 index 00000000..6071c047 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetEncryptedRequest.cs @@ -0,0 +1,93 @@ +using System; +using System.Security.Cryptography; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Base class for encrypted requests. + /// + abstract class SecureTargetEncryptedRequest : SecureTargetRequest + { + private byte[] _cachedPayload; + + /// + /// Init constructor. + /// + public SecureTargetEncryptedRequest(ushort code, byte[] sessionKey) + : base(code) + { + if (sessionKey == null || sessionKey.Length == 0) + throw new ArgumentNullException("sessionKey"); + + SessionKey = sessionKey; + } + + #region Properties + + public byte[] SessionKey + { + get; + private set; + } + + #endregion + + protected override byte[] GetPayload() + { + // return cached value: + if (_cachedPayload != null) + return _cachedPayload; + + // encrypt payload: + byte[] unencryptedPayload = GetUnencryptedPayload(); + if (unencryptedPayload == null) + throw new Exception("Missing payload to encrypt"); + + byte[] iv; + byte[] encryptedPayload = Encrypt(unencryptedPayload, out iv); + + // and prepare the data to send: + var result = _cachedPayload = new byte[4 + iv.Length + encryptedPayload.Length]; + + BitHelper.BigEndian_Set(result, 0, (ushort)encryptedPayload.Length); + BitHelper.BigEndian_Set(result, 2, (ushort)unencryptedPayload.Length); + BitHelper.Copy(result, 4, iv, encryptedPayload); + return result; + } + + private byte[] Encrypt(byte[] payload, out byte[] iv) + { + byte[] result; + + using (var cipher = new RijndaelManaged()) + { + cipher.Mode = CipherMode.CBC; + cipher.Padding = PaddingMode.PKCS7; + cipher.Key = SessionKey; + cipher.GenerateIV(); + iv = cipher.IV; + + using (var encryptor = cipher.CreateEncryptor()) + { + result = encryptor.TransformFinalBlock(payload, 0, payload.Length); + } + } + + /* + QTraceLog.PrintArray("payload", payload); + QTraceLog.PrintArray("key", SessionKey); + QTraceLog.PrintArray("iv", iv); + QTraceLog.PrintArray("result", result); + */ + + return result; + } + + /// + /// Gets the payload that should be encrypted before send. + /// + /// + protected abstract byte[] GetUnencryptedPayload(); + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetHelloRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetHelloRequest.cs new file mode 100644 index 00000000..40e219cd --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetHelloRequest.cs @@ -0,0 +1,22 @@ +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Initial request. + /// + sealed class SecureTargetHelloRequest : SecureTargetRequest + { + /// + /// Default constructor. + /// + public SecureTargetHelloRequest() + : base(1) + { + } + + protected override byte[] GetPayload() + { + // nothing extra to send to target + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetKeepAliveRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetKeepAliveRequest.cs new file mode 100644 index 00000000..cfb426c9 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetKeepAliveRequest.cs @@ -0,0 +1,21 @@ +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request to notify target that the secure connection is still alive and in use. + /// + internal class SecureTargetKeepAliveRequest : SecureTargetRequest + { + /// + /// Default constructor. + /// + public SecureTargetKeepAliveRequest() + : base(6) + { + } + + protected override byte[] GetPayload() + { + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetRequest.cs new file mode 100644 index 00000000..7ab26c93 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetRequest.cs @@ -0,0 +1,82 @@ +using System; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Base class for all requests send by QConnDoor to target device. + /// They are all supposed to open another secure communication channel. + /// + abstract class SecureTargetRequest + { + private const ushort TargetVersion = 2; + + /// + /// Init constructor. + /// + public SecureTargetRequest(ushort version, ushort code) + { + Version = version; + Code = code; + } + + /// + /// Init constructor. + /// + public SecureTargetRequest(ushort code) + { + Version = TargetVersion; + Code = code; + } + + #region Properties + + /// + /// Gets the version of the protocol. + /// + public ushort Version + { + get; + private set; + } + + /// + /// Gets the command code of the request. + /// + public ushort Code + { + get; + private set; + } + + #endregion + + /// + /// Gets data to send to target. + /// + public byte[] GetData() + { + byte[] payload = GetPayload(); + ushort payloadSize = payload != null ? (ushort) payload.Length : (ushort) 0; + + // prepare header: + var data = new byte[payloadSize + 6]; + BitHelper.BigEndian_Set(data, 0, (ushort) data.Length); + BitHelper.BigEndian_Set(data, 2, Version); + BitHelper.BigEndian_Set(data, 4, Code); + + // copy the payload, if given: + if (payload != null && payloadSize > 0) + { + Array.Copy(payload, 0, data, 6, payloadSize); + } + + return data; + } + + /// + /// Gets the payload to send inside the request to target. + /// + protected abstract byte[] GetPayload(); + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetSendSshPublicKeyRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetSendSshPublicKeyRequest.cs new file mode 100644 index 00000000..33e17e61 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetSendSshPublicKeyRequest.cs @@ -0,0 +1,46 @@ +using System; +using System.Text; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request to transfer SSH public key to the target. + /// + sealed class SecureTargetSendSshPublicKeyRequest : SecureTargetEncryptedRequest + { + /// + /// Init constructor. + /// + public SecureTargetSendSshPublicKeyRequest(byte[] sshKey, byte[] sessionKey) + : base(7, sessionKey) + { + if (sshKey == null || sshKey.Length == 0) + throw new ArgumentNullException("sshKey"); + + // key, can not contain spaces at the end, otherwise it will be rejected: + var key = Encoding.UTF8.GetString(sshKey).Trim(); + SshKey = Encoding.UTF8.GetBytes(key); + } + + #region Properties + + public byte[] SshKey + { + get; + private set; + } + + #endregion + + protected override byte[] GetUnencryptedPayload() + { + var payload = new byte[2 + SshKey.Length]; + + BitHelper.BigEndian_Set(payload, 0, (ushort)SshKey.Length); + Array.Copy(SshKey, 0, payload, 2, SshKey.Length); + + return payload; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Requests/SecureTargetStartServicesRequest.cs b/src_vs2012/NativeCore/QConn/Requests/SecureTargetStartServicesRequest.cs new file mode 100644 index 00000000..96e529d3 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Requests/SecureTargetStartServicesRequest.cs @@ -0,0 +1,21 @@ +namespace BlackBerry.NativeCore.QConn.Requests +{ + /// + /// Request to start other dependant services. + /// + sealed class SecureTargetStartServicesRequest : SecureTargetRequest + { + /// + /// Default constructor. + /// + public SecureTargetStartServicesRequest() + : base(11) + { + } + + protected override byte[] GetPayload() + { + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetAuthenticateChallengeResponse.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetAuthenticateChallengeResponse.cs new file mode 100644 index 00000000..b118f543 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetAuthenticateChallengeResponse.cs @@ -0,0 +1,52 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Response to authentication request, informing about the way password should be prepared before transmitted to target. + /// + sealed class SecureTargetAuthenticateChallengeResponse : SecureTargetResponse + { + /// + /// Init constructor. + /// + public SecureTargetAuthenticateChallengeResponse(byte[] data, ushort version, ushort code, uint algorithm, uint iterations, byte[] salt, byte[] challenge) + : base(data, version, code) + { + if (salt == null || salt.Length == 0) + throw new ArgumentNullException("salt"); + Algorithm = algorithm; + Iterations = iterations; + Salt = salt; + Challenge = challenge; + } + + #region Properties + + public uint Algorithm + { + get; + private set; + } + + public uint Iterations + { + get; + private set; + } + + public byte[] Salt + { + get; + private set; + } + + public byte[] Challenge + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetEncryptedChallengeResponse.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetEncryptedChallengeResponse.cs new file mode 100644 index 00000000..83dbd7d6 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetEncryptedChallengeResponse.cs @@ -0,0 +1,33 @@ +using System; +using BlackBerry.NativeCore.QConn.Model; + +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Response to an initial encryption challenge request. + /// + sealed class SecureTargetEncryptedChallengeResponse : SecureTargetResponse + { + /// + /// Init constructor. + /// + public SecureTargetEncryptedChallengeResponse(byte[] data, ushort version, ushort code, byte[] challengeResponse) + : base(data, version, code) + { + if (challengeResponse == null || challengeResponse.Length == 0) + throw new ArgumentNullException("challengeResponse"); + + Challenge = new EncryptionChallenge(challengeResponse); + } + + #region Properties + + public EncryptionChallenge Challenge + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedback.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedback.cs new file mode 100644 index 00000000..7b6d9b97 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedback.cs @@ -0,0 +1,27 @@ +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Base class for all types of feedback responses from QConnDoor service running on target. + /// + class SecureTargetFeedback : SecureTargetResponse + { + /// + /// Init constructor. + /// + public SecureTargetFeedback(byte[] data, HResult status, ushort version, ushort code, ushort feedbackCode) + : base(data, status, version, code) + { + FeedbackCode = feedbackCode; + } + + #region Properties + + public ushort FeedbackCode + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackMismatchedVersion.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackMismatchedVersion.cs new file mode 100644 index 00000000..30b0bbde --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackMismatchedVersion.cs @@ -0,0 +1,26 @@ +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Result informing that target supports different version of the QConnDoor service protocol. + /// + sealed class SecureTargetFeedbackMismatchedVersion : SecureTargetFeedback + { + /// + /// Init constructor. + /// + public SecureTargetFeedbackMismatchedVersion(byte[] data, ushort version, ushort code, ushort feedbackCode, string message) + : base(data, HResult.InvalidData, version, code, feedbackCode) + { + } + + #region Properties + + public string Message + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackNoPasswordRequired.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackNoPasswordRequired.cs new file mode 100644 index 00000000..b2a86f46 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackNoPasswordRequired.cs @@ -0,0 +1,16 @@ +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Result informing that target doesn't require password. + /// + sealed class SecureTargetFeedbackNoPasswordRequired : SecureTargetFeedback + { + /// + /// Init constructor. + /// + public SecureTargetFeedbackNoPasswordRequired(byte[] data, ushort version, ushort code, ushort feedbackCode) + : base(data, HResult.OK, version, code, feedbackCode) + { + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackOK.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackOK.cs new file mode 100644 index 00000000..de4e7c87 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackOK.cs @@ -0,0 +1,16 @@ +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Successfull result about last request. + /// + sealed class SecureTargetFeedbackOK : SecureTargetFeedback + { + /// + /// Init constructor. + /// + public SecureTargetFeedbackOK(byte[] data, ushort version, ushort code, ushort feedbackCode) + : base(data, HResult.OK, version, code, feedbackCode) + { + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackRejected.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackRejected.cs new file mode 100644 index 00000000..824bda13 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetFeedbackRejected.cs @@ -0,0 +1,37 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Negative result about last request. + /// + sealed class SecureTargetFeedbackRejected : SecureTargetFeedback + { + /// + /// Init constructor. + /// + public SecureTargetFeedbackRejected(byte[] data, ushort version, ushort code, ushort feedbackCode, string reason) + : base(data, HResult.Fail, version, code, feedbackCode) + { + if (string.IsNullOrEmpty(reason)) + throw new ArgumentNullException("reason"); + + Reason = reason; + } + + #region Properties + + public string Reason + { + get; + private set; + } + + #endregion + + public override string ToString() + { + return Reason; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetResponse.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetResponse.cs new file mode 100644 index 00000000..d8cf4885 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetResponse.cs @@ -0,0 +1,44 @@ +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Base class for all types for correct responses received from QConnDoor service running on target. + /// + class SecureTargetResponse : SecureTargetResult + { + /// + /// Init constructor. + /// + public SecureTargetResponse(byte[] data, ushort version, ushort code) + : base(data, HResult.OK) + { + Version = version; + Code = code; + } + + /// + /// Init constructor. + /// + public SecureTargetResponse(byte[] data, HResult status, ushort version, ushort code) + : base(data, status) + { + Version = version; + Code = code; + } + + #region Properties + + public ushort Version + { + get; + private set; + } + + public ushort Code + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Response/SecureTargetResult.cs b/src_vs2012/NativeCore/QConn/Response/SecureTargetResult.cs new file mode 100644 index 00000000..dd3b9b0f --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Response/SecureTargetResult.cs @@ -0,0 +1,134 @@ +using System; +using System.Text; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; + +namespace BlackBerry.NativeCore.QConn.Response +{ + /// + /// Base class for all results received from QConnDoor service on the target. + /// + class SecureTargetResult + { + /// + /// Init constructor. + /// + public SecureTargetResult(byte[] data, HResult status) + { + if (data == null) + throw new ArgumentNullException("data"); + + Data = data; + Status = status; + } + + #region Properties + + public byte[] Data + { + get; + private set; + } + + public HResult Status + { + get; + private set; + } + + #endregion + + /// + /// Returns a string that represents the current object. + /// + public override string ToString() + { + return Status.ToString(); + } + + /// + /// Loads response from specified array of bytes. + /// + public static SecureTargetResult Load(byte[] result, HResult status) + { + if (status != HResult.OK) + return new SecureTargetResult(result, status); + if (result == null || result.Length < 6) + { + QTraceLog.WriteLine("Packet length was too small: " + (result != null ? result.Length : 0)); + return new SecureTargetResult(result, HResult.InvalidData); + } + + try + { + ushort packageLength = BitHelper.BigEndian_ToUInt16(result, 0); + ushort version = BitHelper.BigEndian_ToUInt16(result, 2); + ushort code = BitHelper.BigEndian_ToUInt16(result, 4); + + // verify response code: + switch (code) + { + case 2: + { + ushort feedbackCode = BitHelper.BigEndian_ToUInt16(result, 6); + ushort feedbackLength = BitHelper.BigEndian_ToUInt16(result, 8); + switch (feedbackCode) + { + case 0: + return new SecureTargetFeedbackOK(result, version, code, feedbackCode); + case 10: + var message = GetString(result, 10, feedbackLength); + return new SecureTargetFeedbackMismatchedVersion(result, version, code, feedbackCode, message); + case 17: + return new SecureTargetFeedbackNoPasswordRequired(result, version, code, feedbackCode); + default: + var reason = GetString(result, 10, feedbackLength); + return new SecureTargetFeedbackRejected(result, version, code, feedbackCode, reason); + + } + } + case 4: + { + var challenge = new byte[packageLength - 6]; + // this is tricky, as packageLenght might be different from result.Lenght on PlayBook, + // so we allocate more bytes, but copying will just leave them zeroed + Array.Copy(result, 6, challenge, 0, result.Length - 6); + + return new SecureTargetEncryptedChallengeResponse(result, version, code, challenge); + } + case 9: + { + uint algorithm = BitHelper.BigEndian_ToUInt32(result, 6); + uint iterations = BitHelper.BigEndian_ToUInt32(result, 10); + ushort saltLength = BitHelper.BigEndian_ToUInt16(result, 14); + ushort challengeLength = BitHelper.BigEndian_ToUInt16(result, 16); + + var salt = new byte[saltLength]; + var challenge = new byte[challengeLength]; + + Array.Copy(result, 18, salt, 0, salt.Length); + Array.Copy(result, 18 + salt.Length, challenge, 0, challenge.Length); + + return new SecureTargetAuthenticateChallengeResponse(result, version, code, algorithm, iterations, salt, challenge); + } + default: + { + QTraceLog.WriteLine("Invalid code received in target response: " + code); + return new SecureTargetResponse(result, HResult.InvalidFrameCode, version, code); + } + } + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Impossible to interpret response data"); + } + return new SecureTargetResult(result, HResult.InvalidData); + } + + private static string GetString(byte[] data, int at, int length) + { + // PH: strings end with '\0'-char + return Encoding.UTF8.GetString(data, at, length > 0 ? length - 1 : 0); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/SecureTargetConnectionException.cs b/src_vs2012/NativeCore/QConn/SecureTargetConnectionException.cs new file mode 100644 index 00000000..a58f114f --- /dev/null +++ b/src_vs2012/NativeCore/QConn/SecureTargetConnectionException.cs @@ -0,0 +1,26 @@ +using System; + +namespace BlackBerry.NativeCore.QConn +{ + /// + /// Exception thrown in case of errors, while establishing secure QConnDoor connection. + /// + public sealed class SecureTargetConnectionException : Exception + { + public SecureTargetConnectionException(HResult status, string message) + : base(message) + { + Status = status; + } + + #region Properties + + public HResult Status + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Services/TargetService.cs b/src_vs2012/NativeCore/QConn/Services/TargetService.cs new file mode 100644 index 00000000..e0b37a7b --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Services/TargetService.cs @@ -0,0 +1,107 @@ +using System; + +namespace BlackBerry.NativeCore.QConn.Services +{ + /// + /// Base class for operational service exposed by QConn. + /// It can be: + /// * process manager + /// * file manager + /// * profiler + /// * ... + /// + public abstract class TargetService : IDisposable + { + private QConnConnection _connection; + + /// + /// Init constructor. + /// + protected TargetService(Version version, QConnConnection connection) + { + if (version == null) + throw new ArgumentNullException("version"); + if (connection == null) + throw new ArgumentNullException("connection"); + + Version = version; + _connection = connection; + } + + #region Properties + + /// + /// Gets the version of the service. + /// + public Version Version + { + get; + private set; + } + + public QConnConnection Connection + { + get + { + if (_connection == null) + throw new ObjectDisposedException("TargetService"); + return _connection; + } + } + + protected bool IsDisposed + { + get { return _connection == null; } + } + + #endregion + + /// + /// Initializes a connection to a service. + /// + public void Open() + { + if (_connection == null) + throw new ObjectDisposedException("TargetService"); + + _connection.Open(); + } + + /// + /// Closes the connection to a service and releases all resources. + /// + public void Close() + { + if (_connection == null) + throw new ObjectDisposedException("TargetService"); + + if (_connection.IsConnected) + { + _connection.Close(); + } + } + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_connection != null) + { + _connection.Dispose(); + _connection = null; + } + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Services/TargetServiceConsoleLog.cs b/src_vs2012/NativeCore/QConn/Services/TargetServiceConsoleLog.cs new file mode 100644 index 00000000..da4fdf69 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Services/TargetServiceConsoleLog.cs @@ -0,0 +1,560 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Model; + +namespace BlackBerry.NativeCore.QConn.Services +{ + /// + /// Artificial service helping in capturing runtime console logs for processes. + /// It simply continuously reads log files and passes its content via dedicated event. + /// + public sealed class TargetServiceConsoleLog : TargetService + { + #region Internal Classes + + /// + /// Helper class storing current state of log file to read. + /// + sealed class LogMonitorStatus : IDisposable + { + private ulong _readBytes; + private readonly List _chunks; + + public event EventHandler Finished; + + /// + /// Init constructor. + /// + public LogMonitorStatus(TargetServiceFile fileService, string path, TargetFileDescriptor handle, ProcessInfo process, bool isDebugging) + { + if (fileService == null) + throw new ArgumentNullException("fileService"); + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + if (handle == null) + throw new ArgumentNullException("handle"); + if (process == null) + throw new ArgumentNullException("process"); + + FileService = fileService; + Path = path; + Handle = handle; + Process = process; + IsDebugging = isDebugging; + _chunks = new List(); + } + + ~LogMonitorStatus() + { + Dispose(false); + } + + #region Properties + + public TargetServiceFile FileService + { + get; + private set; + } + + public string Path + { + get; + private set; + } + + public TargetFileDescriptor Handle + { + get; + private set; + } + + public ProcessInfo Process + { + get; + private set; + } + + /// + /// Gets an indication, if this log monitoring is attached to debugged app or not. + /// + public bool IsDebugging + { + get; + private set; + } + + #endregion + + /// + /// Resets the reading offset to start logs from the beginning. + /// + public void Reset() + { + _readBytes = 0; + } + + /// + /// Read all new log entries, if available or null. + /// + public string[] Read() + { + try + { + const int ChunkSize = 20 * 1024; + + _chunks.Clear(); + + // read one or more available chunks of data from the file, than glue them into one buffer, + // convert to UTF8 string and split per lines: + while (true) + { + var data = FileService.Read(Handle, _readBytes, ChunkSize); + + if (data != null && data.Length > 0) + { + _readBytes += (ulong) data.Length; + if (data.Length == ChunkSize) + { + // store the chunk and try again: + _chunks.Add(data); + continue; + } + + if (_chunks.Count > 0) + { + return GetString(BitHelper.Combine(_chunks, null, 0)); + } + + return GetString(data); + } + + // if there are no more new chunks, but we did read any previously: + if (_chunks.Count > 0) + { + return GetString(BitHelper.Combine(_chunks, null, 0)); + } + break; + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to read from log file: \"{0}\"", Path); + + if (Finished != null) + Finished(this, EventArgs.Empty); + } + + return null; + } + + private static bool IsWhiteSpace(byte c) + { + return c <= 32; + } + + private static string[] GetString(byte[] data) + { + // since new-line will be automatically added at the end of log entry + // trim-end now, before doing any conversions to save processor & memory: + int length = data.Length; + + while (length > 0 && IsWhiteSpace(data[length - 1])) + { + length--; + } + + return Encoding.UTF8.GetString(data, 0, length).Split(new[] { "\r\n", "\n\r", "\n" }, StringSplitOptions.None); + } + + public bool HasPath(string path) + { + if (string.IsNullOrEmpty(path)) + return false; + + return string.Compare(Path, path, StringComparison.Ordinal) == 0; + } + + #region IDisposable Implementation + + private void Dispose(bool disposing) + { + if (disposing) + { + if (Handle != null) + { + Handle.Close(); + } + + Finished = null; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } + + #endregion + + public const uint DefaultInterval = 750; // how often to check the remote log file for new content; in milliseconds + + private TargetServiceFile _fileService; + private readonly object _sync; + private readonly List _logMonitors; + private uint[] _processIDs; + private uint _interval; + private Timer _keepReadingTimer; + + /// + /// Event notifying that new console log entries are available for processing. + /// + public event EventHandler Captured; + + /// + /// Init constructor. + /// + public TargetServiceConsoleLog(TargetServiceFile fileService) + : base(new Version(1, 0), fileService != null ? fileService.Connection : null) + { + if (fileService == null) + throw new ArgumentNullException("fileService"); + + _fileService = fileService; + _sync = new object(); + _logMonitors = new List(); + _interval = DefaultInterval; + UpdateProcessIDsNoSync(); + } + + protected override void Dispose(bool disposing) + { + try + { + StopAll(); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to stop console-logs for all monitored processes"); + } + + // first close the original service, that should close the connection, if opened: + if (_fileService != null) + { + _fileService.Dispose(); + _fileService = null; + } + + Captured = null; + base.Dispose(disposing); + } + + #region Properties + + /// + /// Gets an array of PIDs of monitored logs. + /// + public uint[] ProcessIDs + { + get { return _processIDs; } + } + + /// + /// Gets an indication, if there is anything monitored at the moment. + /// + public bool IsMonitoringAnything + { + get { return _processIDs != null && _processIDs.Length > 0; } + } + + /// + /// Gets or sets the interval of pinging the logs for new content. + /// + public uint Interval + { + get { return _interval; } + set + { + _interval = value == 0 ? DefaultInterval : value; // it will automatically pickup this value on next round of log refresh + } + } + + #endregion + + /// + /// Starts monitoring of the logs printed on console for specified process. + /// + public bool Start(ProcessInfo process, uint interval, bool isDebugging) + { + if (process == null) + throw new ArgumentNullException("process"); + + TraceLog.WriteLine("> Starting console-logs monitor for: {0}", process.Name); + Interval = interval; + + // PH: this is the same 'trick' used by Momentics, since console dumps everything into a log file + // let's continuously read that file and truncate it, if needed: + + // calculate path to the log file (the dummy way, without using $HOME$ variable): + if (process.ExecutablePath != null) + { + var homeIndex = process.ExecutablePath.IndexOf("/app/", StringComparison.Ordinal); + + if (homeIndex > 0) + { + var logFilePath = process.ExecutablePath.Substring(0, homeIndex) + "/logs/log"; + return Start(logFilePath, process, interval, isDebugging); + } + } + + TraceLog.WarnLine("> Error: Unable to calculate location of the console log file"); + return false; + } + + private bool Start(string logFilePath, ProcessInfo process, uint interval, bool isDebugging) + { + if (string.IsNullOrEmpty(logFilePath)) + throw new ArgumentNullException("logFilePath"); + if (process == null) + throw new ArgumentNullException("process"); + + TraceLog.WriteLine("> Log file: \"{0}\"", logFilePath); + + var existingMonitor = Find(logFilePath); + + if (existingMonitor == null) + { + // open the file: + var fileHandle = _fileService.Open(logFilePath, TargetFile.ModeOpenReadOnly, uint.MaxValue, false); + if (fileHandle != null) + { + lock (_sync) + { + var monitor = new LogMonitorStatus(_fileService, logFilePath, fileHandle, process, isDebugging); + monitor.Finished += OnMonitorStatusFinished; + _logMonitors.Add(monitor); + UpdateProcessIDsNoSync(); + + // start the timer: + if (_keepReadingTimer == null) + _keepReadingTimer = new Timer(OnReaderTick, this, interval, Timeout.Infinite); + } + + return true; + } + + TraceLog.WriteLine("> Error: Unable to open log file: \"{0}\"", logFilePath); + return false; + } + + existingMonitor.Reset(); + TraceLog.WarnLine("> Warning: Log file is already monitored, resetting: \"{0}\"", logFilePath); + return false; + } + + private void OnMonitorStatusFinished(object sender, EventArgs e) + { + var status = (LogMonitorStatus) sender; + status.Finished -= OnMonitorStatusFinished; + + try + { + Stop(status.Process); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Failed to stop console-logs monitor for: {0}", status.Process != null ? status.Process.Name : "unknown process"); + } + } + + /// + /// Checks, if console outputs are specified for specified process. + /// + public bool IsMonitoring(ProcessInfo process) + { + if (process == null) + return false; + + lock (_sync) + { + return FindNoSync(process) != null; + } + } + + /// + /// Stops monitoring of console outputs for specified process. + /// + public bool Stop(ProcessInfo process) + { + if (process == null) + throw new ArgumentNullException("process"); + + bool killTimer = false; + LogMonitorStatus monitor; + + lock (_sync) + { + monitor = FindNoSync(process); + + if (monitor != null) + { + _logMonitors.Remove(monitor); + killTimer = _logMonitors.Count == 0; + UpdateProcessIDsNoSync(); + } + } + + if (killTimer) + { + if (_keepReadingTimer != null) + { + _keepReadingTimer.Dispose(); + _keepReadingTimer = null; + } + } + + if (monitor != null) + { + TraceLog.WriteLine("> Stopping console-logs monitor for: \"{0}\"", monitor.Path); + monitor.Dispose(); + + return true; + } + + return false; + } + + /// + /// Stops monitoring for all console logs. + /// + public void StopAll() + { + TraceLog.WriteLine("> Stopping all console-logs monitors"); + + if (_keepReadingTimer != null) + { + _keepReadingTimer.Dispose(); + _keepReadingTimer = null; + } + + lock (_sync) + { + foreach (var monitor in _logMonitors) + { + monitor.Dispose(); + } + + _logMonitors.Clear(); + UpdateProcessIDsNoSync(); + } + } + + /// + /// Checks, if log file for specified process is monitored. + /// + public bool IsMonitoring(uint processID) + { + var processes = _processIDs; + foreach (uint procID in processes) + { + if (procID == processID) + return true; + } + + return false; + } + + /// + /// Finds existing monitor that is attached to the specified log. + /// In case of non-existence it returns null. + /// + private LogMonitorStatus Find(string path) + { + lock (_sync) + { + foreach (var monitor in _logMonitors) + { + if (monitor.HasPath(path)) + { + return monitor; + } + } + } + + return null; + } + + /// + /// Finds existing monitor that is attached to the specified process. + /// In case of non-existence it returns null. + /// + private LogMonitorStatus FindNoSync(ProcessInfo process) + { + if (process == null) + return null; + + foreach (var monitor in _logMonitors) + { + if (monitor.Process.ID == process.ID || string.Compare(monitor.Process.ExecutablePath, process.ExecutablePath, StringComparison.Ordinal) == 0) + { + return monitor; + } + } + + return null; + } + + private void UpdateProcessIDsNoSync() + { + // copy the PIDs into separate array: + var newArray = new uint[_logMonitors.Count]; + for (int i = 0; i < _logMonitors.Count; i++) + { + newArray[i] = _logMonitors[i].Process.ID; + } + + // PH: and replace the whole array, + // since this array changes rarely, thanks to this trick, none of the external code, + // which only enumerates over this array need any sync-locks! + _processIDs = newArray; + } + + private void OnReaderTick(object state) + { + lock (_sync) + { + // ask each monitor, if there are now log entries and forward them onto the console: + for(int i = 0; i < _logMonitors.Count; i++) + { + var monitor = _logMonitors[i]; + var logEntries = monitor.Read(); + if (logEntries != null && Captured != null) + { + var targetLogs = TargetLogEntry.ParseConsole(monitor.Process, logEntries); + + if (targetLogs != null) + { + Captured(this, new CapturedLogsEventArgs(targetLogs)); + } + } + } + } + + // ask the timer to run again, this will eliminate the problem + // of low network speeds, when accessing the log file for all monitors took more than Interval: + if (_keepReadingTimer != null) + { + _keepReadingTimer.Change(Interval, Timeout.Infinite); + } + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Services/TargetServiceControl.cs b/src_vs2012/NativeCore/QConn/Services/TargetServiceControl.cs new file mode 100644 index 00000000..5d5bfb26 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Services/TargetServiceControl.cs @@ -0,0 +1,68 @@ +using System; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.QConn.Model; + +namespace BlackBerry.NativeCore.QConn.Services +{ + /// + /// Class to communicate with a Control Service running on target. + /// It is supposed to manage running processes. + /// + public sealed class TargetServiceControl : TargetService + { + private const int SIGKILL = 9; + + /// + /// Init constructor. + /// + public TargetServiceControl(Version version, QConnConnection connection) + : base(version, connection) + { + } + + public override string ToString() + { + return "ControlService"; + } + + /// + /// Terminates a process with specified PID. + /// + public void Terminate(uint pid) + { + Kill(pid, SIGKILL); + } + + /// + /// Terminates specified process. + /// + public void Terminate(ProcessInfo process) + { + if (process == null) + throw new ArgumentNullException("process"); + + Kill(process.ID, SIGKILL); + } + + /// + /// Terminates specified process. + /// + public void Terminate(TargetProcess process) + { + if (process == null) + throw new ArgumentNullException("process"); + + Kill(process.PID, SIGKILL); + } + + /// + /// Sends a kill signal to a process with specified PID. + /// + public void Kill(uint pid, uint signal) + { + var response = Connection.Send(string.Concat("kill ", pid, " ", signal)); + QTraceLog.WriteLine("Killed process with PID: {0} - {1}", pid, response); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Services/TargetServiceFile.cs b/src_vs2012/NativeCore/QConn/Services/TargetServiceFile.cs new file mode 100644 index 00000000..4d1ef1e8 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Services/TargetServiceFile.cs @@ -0,0 +1,645 @@ +using System; +using System.Collections.Generic; +using System.Text; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Visitors; + +namespace BlackBerry.NativeCore.QConn.Services +{ + /// + /// Class to communicate with a File-System Service on target. + /// It allows any file and directory manipulations. + /// + public sealed class TargetServiceFile : TargetService + { + private const uint ModeOpenCreate = 0x100; + private const uint ModeOpenTruncate = 0x200; + + internal const int DownloadUploadChunkSize = 48 * 1024; + + /// + /// Init constructor. + /// + public TargetServiceFile(Version version, QConnConnection connection) + : base(version, connection) + { + } + + protected override void Dispose(bool disposing) + { + if (!IsDisposed) + { + // disconnect with target service: + if (Connection.IsConnected) + { + try + { + Post("q"); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to close {0}", this); + } + } + } + + base.Dispose(disposing); + } + + public override string ToString() + { + return "FileService"; + } + + /// + /// Sends a command to the target and returns its parsed representation. + /// + private Token[] Send(string command) + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + // send: + var rawResponse = Connection.Send(command); + if (string.IsNullOrEmpty(rawResponse)) + throw new QConnException("Invalid response received for command: \"" + command + "\""); + + // parse: + var response = Token.Parse(rawResponse); + if (response == null || response.Length == 0) + throw new QConnException("Unable to parse response: \"" + rawResponse + "\" for command: \"" + command + "\""); + + return response; + } + + /// + /// Sends a command to the target and ignores the response. + /// + private void Post(string command) + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + // send: + var rawResponse = Connection.Post(command); + } + + /// + /// Opens specified path with specified mode. + /// + internal TargetFileDescriptor Open(string path, uint mode, uint permissions, bool throwOnFailure) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + Token[] response; + + if (mode == TargetFile.ModeOpenNone) + { + response = Send(string.Concat("oc:\"", path, "\":0")); + } + else + { + uint qmode = (mode & 0xFFFFFFFC) | ((mode - 1) & 3); + + if (permissions != uint.MaxValue) + { + response = Send(string.Concat("o:\"", path, "\":", qmode.ToString("X"), ":", permissions.ToString("X"))); + } + else + { + response = Send(string.Concat("o:\"", path, "\":", qmode.ToString("X"))); + } + } + + // verify response to open request: + if (response[0].StringValue == "e") + { + if (throwOnFailure) + throw new QConnException(string.Concat("Opening-handle failed: ", response[1].StringValue, " (", path, ")")); + QTraceLog.WriteLine(string.Concat("Opening-handle failed: ", response[1].StringValue, " (", path, ")")); + return null; + } + if (response.Length < 5) + { + if (throwOnFailure) + throw new QConnException("Opening-handle response has invalid format"); + + QTraceLog.WriteLine("Opening-handle response has invalid format"); + return null; + } + + var handle = response[1].StringValue; + + // creating folder, returns some dummy data... + if (string.Compare(handle, "-1", StringComparison.Ordinal) == 0) + return new TargetFileDescriptor(this, null, permissions, 4096, mode, path); + + return new TargetFileDescriptor(this, handle, response[2].UInt32Value, response[3].UInt64Value, mode, response[4].StringValue); + } + + internal void Close(TargetFileDescriptor descriptor) + { + if (descriptor == null) + throw new ArgumentNullException("descriptor"); + + if (!descriptor.IsClosed && !IsDisposed && Connection != null && Connection.IsConnected) + { + var response = Send("c:" + descriptor.Handle); + descriptor.Closed(); + + if (response[0].StringValue == "e") + throw new QConnException("Closing-handle failed: " + response[1].StringValue); + } + else + { + descriptor.Closed(); + } + } + + /// + /// Reads binary data directly from a file or folder of the target at specified offset. + /// + internal byte[] Read(TargetFileDescriptor descriptor, ulong offset, ulong length) + { + if (descriptor == null) + throw new ArgumentNullException("descriptor"); + if (descriptor.IsClosed) + throw new ArgumentOutOfRangeException("descriptor"); + if (!descriptor.CanRead) + throw new QConnException("File is not opened for read"); + if (length == 0) + throw new ArgumentOutOfRangeException("length", "Too few data to read requested"); + if (length > int.MaxValue) + throw new ArgumentOutOfRangeException("length", "Unable to load so much data at once"); + + // ask for the raw data: + var command = string.Concat("r:", descriptor.Handle, ":", offset.ToString("X"), ":", length.ToString("X")); + var reader = Connection.Request(command); + if (reader == null) + throw new QConnException("Invalid response to read request received"); + + // read and parse the header part: + var responseHeader = reader.ReadString(uint.MaxValue, '\r'); + reader.Skip(1); // skip '\n' + if (string.IsNullOrEmpty(responseHeader)) + throw new QConnException("Unable to retrieve response header"); + var response = Token.Parse(responseHeader); + if (response[0].StringValue != "o" && response[0].StringValue != "o+") + throw new QConnException("Reading failed: " + response[1].StringValue); + + ulong contentLength = response[1].UInt64Value; + // ulong contentOffset = response[2].UInt64Value; + + if (contentLength > 0) + { + var buffer = reader.ReadBytes((int) contentLength); + if (buffer == null || buffer.Length != (int) contentLength) + throw new QConnException("Invalid number of content bytes read"); + return buffer; + } + + return new byte[0]; + } + + /// + /// Writes specified amount of data into an open file. + /// + internal uint Write(TargetFileDescriptor descriptor, byte[] data) + { + if (descriptor == null) + throw new ArgumentNullException("descriptor"); + if (data == null) + throw new ArgumentNullException("data"); + + return Write(descriptor, data, 0, data.Length); + } + + /// + /// Writes specified amount of data into an open file. + /// + internal uint Write(TargetFileDescriptor descriptor, byte[] data, int offset, int length) + { + if (descriptor == null) + throw new ArgumentNullException("descriptor"); + if (descriptor.IsClosed) + throw new ArgumentOutOfRangeException("descriptor"); + if (!descriptor.CanWrite) + throw new QConnException("File is not opened for write"); + if (data == null) + throw new ArgumentNullException("data"); + if (offset > data.Length) + throw new ArgumentOutOfRangeException("offset"); + if (data.Length < offset + length) + throw new ArgumentOutOfRangeException("length", "Specified data buffer is too short"); + + // send file content: + var command = string.Concat("w:", descriptor.Handle, ":0:", length.ToString("X"), ":1"); // last 1 means appending + var responseContent = Connection.Send(command, data, offset, length, true); + + var response = Token.Parse(responseContent); + if (response[0].StringValue != "o") + throw new QConnException("Reading failed: " + response[1].StringValue); + + uint writeLength = response[1].UInt32Value; + // uint contentOffset = response[2].UInt64Value; + + return writeLength; + } + + /// + /// Gets the info about specified path. + /// If specified, it throws exceptions in case of any errors or permission denies. + /// + internal TargetFile Stat(string path, bool throwOnFailure) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + using (var descriptor = Open(path, TargetFile.ModeOpenNone, uint.MaxValue, throwOnFailure)) + { + // when opening successful: + if (descriptor != null) + { + // ask for full description: + var response = Send("s:" + descriptor.Handle); + if (response[0].StringValue == "e") + { + if (throwOnFailure) + throw new QConnException("Stat failed: " + response[1].StringValue); + + QTraceLog.WriteLine("Stat failed: " + response[1].StringValue); + return null; + } + + // update creation-date, type and size: + if (response.Length > 5) + { + var creationTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(response[9].UInt64Value).ToLocalTime(); + descriptor.Update(response[5].UInt32Value, response[6].UInt32Value, creationTime, response[10].UInt32Value, response[2].UInt64Value); + } + } + return descriptor; + } + } + + /// + /// Gets the info about specified path. + /// It throws exceptions in case of any errors or permission denies. + /// + public TargetFile Stat(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + return Stat(path, true); + } + + /// + /// Lists files and folders at specified location. + /// + public TargetFile[] List(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + var descriptor = Stat(path, true); + if (descriptor == null) + throw new QConnException("Unable to determine path properties"); + return List(descriptor); + } + + /// + /// Lists files and folders at specified location. + /// + public TargetFile[] List(TargetFile location) + { + if (location == null) + throw new ArgumentNullException("location"); + + if (location.IsDirectory) + { + using (var directory = Open(location.Path, TargetFile.ModeOpenReadOnly, TargetFile.TypeDirectory, true)) + { + // PH: HINT: + // since some folders reports no size (like /tmp/slogger2) or too small size (like /pps/system only 8 bytes), try to read as much as possible... + // just fingers crossed, it won't really try to allocated 2GB of memory... + var data = Read(directory, 0, int.MaxValue); + if (data == null) + throw new QConnException("Invalid directory listing read"); + string listing = Encoding.UTF8.GetString(data); + + // parse names, as each is in separate line: + var result = new SortedList(); + var foundItems = listing.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var item in foundItems) + { + if (item != "." && item != "..") + { + string itemPath = location.CreateItemPath(item); + + // and try to load detailed info: + var statInfo = Stat(itemPath, false); + if (statInfo != null) + { + statInfo.Update(item); + } + else + { + //QTraceLog.WriteLine("Unable to load info about path: \"" + itemPath + "\""); // PH: for debugging only; this log only duplicates error printouts from Stat() call + + // add a stub, just to keep the path only (as might have lack permissions to read info): + statInfo = new TargetFile(itemPath, item, false); + } + + result.Add(statInfo, statInfo); + } + } + + // and return an non-mutable array: + var array = new TargetFile[result.Count]; + result.Values.CopyTo(array, 0); + return array; + } + } + + throw new QConnException("Not a folder, unable to perform listing"); + } + + /// + /// Create a folder at specified location. + /// + public TargetFile CreateFolder(string fullPath, uint permissions) + { + if (string.IsNullOrEmpty(fullPath)) + throw new ArgumentNullException("fullPath"); + + // does it exist? + using (var descriptor = Open(fullPath, TargetFile.ModeOpenNone, (permissions & TargetFile.TypeMask) | TargetFile.TypeDirectory, false)) + { + if (descriptor != null) + return descriptor; + } + + // try to create directory: + using (var descriptor = Open(fullPath, ModeOpenCreate, (permissions & TargetFile.TypeMask) | TargetFile.TypeDirectory, false)) + { + if (descriptor != null) + return descriptor; + } + + // if creation failed, maybe some parent folders on the path are missing, try to create them: + var parent = CreateFolder(PathHelper.ExtractDirectory(fullPath), permissions); + if (parent == null) + throw new QConnException("Failed to create folder"); + + // try to create directory again throwing exception if failed: + using (var descriptor = Open(fullPath, ModeOpenCreate, (permissions & TargetFile.TypeMask) | TargetFile.TypeDirectory, true)) + { + return descriptor; + } + } + + /// + /// Creates a folder at specified location. + /// + public TargetFile CreateFolder(string fullPath) + { + if (string.IsNullOrEmpty(fullPath)) + throw new ArgumentNullException("fullPath"); + + return CreateFolder(fullPath, TargetFile.ModePermissionsAll); + } + + /// + /// Creates new sub-folder at specified location. + /// + public TargetFile CreateFolder(TargetFile location, string name) + { + if (location == null) + throw new ArgumentNullException("location"); + if (location.NoAccess) + throw new ArgumentOutOfRangeException("location"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + + return CreateFolder(PathHelper.MakePath(location.Path, name), TargetFile.ModePermissionsAll); + } + + /// + /// Creates an empty file on target. + /// + public TargetFile CreateFile(string path, uint permissions) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + using (var descriptor = CreateNewFile(path, permissions)) + { + return descriptor; + } + } + + /// + /// Opens a file for reading or writing on target. + /// + internal TargetFileDescriptor CreateNewFile(string path, uint permissions) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + return Open(path, ModeOpenCreate | ModeOpenTruncate | TargetFile.ModeOpenReadWrite, permissions & TargetFile.TypeMask, true); + } + + /// + /// Removes the file or folder at specified location. + /// + public void Remove(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + Remove(path, 0u); + } + + /// + /// Removes the file or folder at specified location. + /// + public void Remove(string path, uint flags) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + // ask to delete: + var response = Send("d:\"" + path + "\":" + flags.ToString("X")); + if (response[0].StringValue == "e") + throw new QConnException("Remove failed: " + response[1].StringValue); + } + + /// + /// Removes the whole directory tree. + /// + public void RemoveTree(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + Remove(path, 1u); + } + + /// + /// Moves the file or folder from specified source location to the destination location. + /// + public void Move(string sourcePath, string destinationPath) + { + if (string.IsNullOrEmpty(sourcePath)) + throw new ArgumentNullException("sourcePath"); + if (string.IsNullOrEmpty(destinationPath)) + throw new ArgumentNullException("destinationPath"); + + // ask to move: + var response = Send("m:\"" + sourcePath + "\":\"" + destinationPath + "\""); + if (response[0].StringValue == "e") + throw new QConnException("Move failed: " + response[1].StringValue); + } + + /// + /// Downloads files and folders (including whole subtree) from specified location on target and passes them to visitor for further processing. + /// + public IFileServiceVisitorMonitor DownloadAsync(string targetPath, IFileServiceVisitor visitor) + { + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + if (visitor == null) + throw new ArgumentNullException("visitor"); + + return EnumerateAsync(new TargetEnumerator(targetPath), visitor) as IFileServiceVisitorMonitor; + } + + /// + /// Downloads files and folders (including whole subtree) from specified location on target and saves them locally. + /// + public IFileServiceVisitorMonitor DownloadAsync(string targetPath, string localPath, object tag) + { + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + if (string.IsNullOrEmpty(localPath)) + throw new ArgumentNullException("localPath"); + + return EnumerateAsync(new TargetEnumerator(targetPath), new LocalCopyVisitor(localPath, tag)) as IFileServiceVisitorMonitor; + } + + /// + /// Gets a specified collection of files and folders and uploads them to target at specified location. + /// + public TargetCopyVisitor UploadAsync(IFileServiceEnumerator enumerator, string targetPath, object tag) + { + if (enumerator == null) + throw new ArgumentNullException("enumerator"); + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + + return (TargetCopyVisitor) EnumerateAsync(enumerator, new TargetCopyVisitor(targetPath, tag)); + } + + /// + /// Gets collection of files and folders (including whole subtree) from specified location on current desktop machine and uploads them to target at specified location. + /// + public TargetCopyVisitor UploadAsync(string localPath, string targetPath, object tag) + { + if (string.IsNullOrEmpty(localPath)) + throw new ArgumentNullException("localPath"); + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + + return (TargetCopyVisitor) EnumerateAsync(new LocalEnumerator(localPath), new TargetCopyVisitor(targetPath, tag)); + } + + /// + /// Loads specified file or folders (including whole subtree) into memory. + /// + public BufferVisitor PreviewAsync(string targetPath) + { + if (string.IsNullOrEmpty(targetPath)) + throw new ArgumentNullException("targetPath"); + + return (BufferVisitor) EnumerateAsync(new TargetEnumerator(targetPath), new BufferVisitor()); + } + + /// + /// Enumerates asynchronously the content of the file or folder (including whole subtree) and passes them to specified visitor. + /// It allows then more advanced processing like: + /// * loading specified files into memory + /// * storing them in local file-system + /// * zipping them and storing locally + /// and also: + /// * waiting for completion + /// * progress monitoring + /// + /// Check the implemented visitors for more details. + /// + public IFileServiceVisitor EnumerateAsync(IFileServiceEnumerator enumerator, IFileServiceVisitor visitor) + { + if (enumerator == null) + throw new ArgumentNullException("enumerator"); + if (visitor == null) + throw new ArgumentNullException("visitor"); + + // clone current QConn-connection to allow asynchronous processing (otherwise it could interfere with other sync commands) + // and arm clone with a bigger buffer, to faster load data: + var connection = (QConnConnection) Connection.Clone(DownloadUploadChunkSize); + if (connection == null) + throw new QConnException("Unable to establish asynchronous connection"); + + // connect: + connection.Open(); + + // load info about the file to download: + var service = new TargetServiceFile(Version, connection); + enumerator.Begin(service); + + // HINT: service will be automatically disposed in completion callback below: + var asyncHandler = new Action(enumerator.Enumerate); + asyncHandler.BeginInvoke(visitor, DownloadAsyncCompleted, new Tuple(enumerator, service, asyncHandler)); + + return visitor; + } + + private void DownloadAsyncCompleted(IAsyncResult ar) + { + var data = (Tuple)ar.AsyncState; + var enumerator = data.Item1; + var service = data.Item2; + var action = (Action)data.Item3; + + try + { + action.EndInvoke(ar); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Asynchronous download failed"); + } + + try + { + enumerator.End(); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Enumerator cleaning-up failed"); + } + + try + { + service.Dispose(); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Service cleaning-up failed"); + } + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Services/TargetServiceLauncher.cs b/src_vs2012/NativeCore/QConn/Services/TargetServiceLauncher.cs new file mode 100644 index 00000000..30fcee8c --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Services/TargetServiceLauncher.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Text; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.QConn.Model; + +namespace BlackBerry.NativeCore.QConn.Services +{ + /// + /// Class to communicate with a service running on the device, responsible for launching any remote tools. + /// + public sealed class TargetServiceLauncher : TargetService + { + public const uint LaunchDefault = 0; + public const uint LaunchSuspended = 0x8000; + private const uint LaunchFlagMask = 0xFFFF; + + internal const int ConsoleOutputsChunkSize = 32 * 1024; + + /// + /// Init constructor. + /// + public TargetServiceLauncher(Version version, QConnConnection connection) + : base(version, connection) + { + } + + /// + /// Returns a string that represents the current object. + /// + public override string ToString() + { + return "LauncherService"; + } + + /// + /// Executes specified command on a target device. + /// + public T Start(string command, string[] arguments) where T : TargetProcess + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + return Start(command, arguments, null, null, string.Empty, LaunchDefault); + } + + /// + /// Executes specified command on a target device. + /// + public TargetProcess Start(string command, string[] arguments) + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + return Start(command, arguments, null, null, string.Empty, LaunchDefault); + } + + /// + /// Executes specified command on a target device. + /// + public T Start(string command, string[] arguments, IEnumerable> environmentVariables, string workingDirectory, string pty, uint flags) + where T : TargetProcess + { + if (string.IsNullOrEmpty(command)) + throw new ArgumentNullException("command"); + + // first establish new connection, so that created process is able to perform all actions asynchronously + // and not interfere with the current state of the service: + var newConnection = (QConnConnection) Connection.Clone(ConsoleOutputsChunkSize); + + if (string.IsNullOrEmpty(workingDirectory)) + { + var pathEndAt = command.LastIndexOf('/'); + if (pathEndAt >= 0) + { + workingDirectory = command.Substring(0, pathEndAt + 1); + } + } + + if (!string.IsNullOrEmpty(workingDirectory)) + { + newConnection.Send(string.Concat("chdir \"", workingDirectory, "\"")); + } + + // disable killing processes by Ctrl+C + if (pty == null) + { + newConnection.Send("set nopty"); + } + + // prepare environment variables: + if (environmentVariables != null) + { + foreach (var ev in environmentVariables) + { + if (string.IsNullOrEmpty(ev.Value)) + { + // remove variable: + newConnection.Send(string.Concat("setenv ", ev.Key, "=")); + } + else + { + // update variable's value: + newConnection.Send(string.Concat("setenv ", ev.Key, "=\"", ev.Value, "\"")); + } + } + } + + // initiate the run command to execute: + var runner = new StringBuilder(); + flags &= LaunchFlagMask; + + runner.Append("start"); + if (flags != 0) + { + runner.Append("/flags "); + runner.Append(flags.ToString("X")); + } + runner.Append(" "); + runner.Append(command); // PH: TODO: some escaping? + + if (arguments != null && arguments.Length > 0) + { + foreach (var arg in arguments) + { + runner.Append(" "); + runner.Append(arg); // PH: TODO: some escaping? + } + } + + // execute and grab the process' ID: + var startupResult = newConnection.Send(runner.ToString()); + uint pid; + + if (startupResult != null && startupResult.StartsWith("ok ", StringComparison.OrdinalIgnoreCase) + && uint.TryParse(startupResult.Substring(3), out pid)) + { + // create new instance of the class wrapping process functionalities: + return (T)Activator.CreateInstance(typeof(T), this, newConnection, pid, (flags & LaunchSuspended) == LaunchSuspended); + } + + QTraceLog.WriteLine("Failed to startup the command, result: {0}", startupResult); + return null; + } + + /// + /// Gets the exit code of the specified process. + /// + public uint GetExitCode(TargetProcess process) + { + if (process == null) + throw new ArgumentNullException("process"); + + return GetExitCode(process.PID); + } + + /// + /// Gets the exit code for process with specified ID. + /// + public uint GetExitCode(uint pid) + { + var exitResult = Connection.Send("getexitcode " + pid); + + if (exitResult != null && exitResult.StartsWith("e:", StringComparison.OrdinalIgnoreCase)) + { + return uint.Parse(exitResult.Substring(2)); + } + + throw new QConnException("Invalid response for exit-code request (\"" + exitResult + "\")"); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Services/TargetServiceSysInfo.cs b/src_vs2012/NativeCore/QConn/Services/TargetServiceSysInfo.cs new file mode 100644 index 00000000..3665b540 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Services/TargetServiceSysInfo.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.IO; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.QConn.Model; + +namespace BlackBerry.NativeCore.QConn.Services +{ + /// + /// Class to communicate with a System-Info Service on target. + /// It specifies information about the host. + /// + public sealed class TargetServiceSysInfo : TargetService + { + #region Private Classes + + struct Header + { + public int version; + public int status; + public int nbytes; + public int bbytes; + public int nelems; + public int flags; + public int sinfo_rate; + + public void Read(IDataReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + version = reader.ReadInt32(); + status = reader.ReadInt32(); + nbytes = reader.ReadInt32(); + bbytes = reader.ReadInt32(); + nelems = reader.ReadInt32(); + flags = reader.ReadInt32(); + sinfo_rate = reader.ReadInt32(); + } + } + + /* + sealed class SystemInfoPid + { + public int pid; + public int parent; + public int flags; + public int umask; + public int child; + public int sibling; + public int pgrp; + public int sid; + public long base_address; + public long initial_stack; + public int uid; + public int gid; + public int euid; + public int egid; + public int suid; + public int sgid; + public long sig_ignore; + public long sig_queue; + public long sig_pending; + public long num_chancons; + public long num_fdcons; + public long num_threads; + public long num_timers; + public long start_time; + public long utime; + public long stime; + public long cutime; + public long cstime; + public long codesize; + public long datasize; + public long stacksize; + public long vstacksize; + public char name[128]; + } + + public static class SystemInfoEnv + { + public int env_str_length; + public String env_str; + } + + public static class SystemInfoArgs + { + public int args_str_length; + public String args_str; + } + + */ + + #endregion + + /// + /// Init constructor. + /// + public TargetServiceSysInfo(Version version, QConnConnection connection) + : base(version, connection) + { + } + + public override string ToString() + { + return "SysInfoService"; + } + + /// + /// Gets the list of running processes. + /// + public SystemInfoProcess[] LoadProcesses() + { + var reader = Connection.Request("get pids"); + + // read info about payload: + var header = new Header(); + header.Read(reader); + + // read payload: + var result = new List(); + for (int i = 0; i < header.nelems; i++) + { + uint id = reader.ReadUInt32(); + uint parentID = reader.ReadUInt32(); + reader.Skip(40 * 4); // some other non-interesting fields + + // read the process name, which is a NUL-terminated string with max 128 chars + string name = reader.ReadString(128u, '\0'); + + // skip remaining name buffer: + if (name.Length + 1 < 128) + { + reader.Skip(127 - name.Length); + } + + if (id != 0 && parentID != 0 && !string.IsNullOrEmpty(name)) + { + // some fixes around name: + if (name[0] != Path.DirectorySeparatorChar && name[0] != Path.AltDirectorySeparatorChar) + { + name = "/" + name; + } + + result.Add(new SystemInfoProcess(id, parentID, name)); + } + else + { +#if DEBUG + if (System.Diagnostics.Debugger.IsAttached) + System.Diagnostics.Debugger.Break(); +#endif + } + } + + return result.ToArray(); + } + + /// + /// Loads environment variables for specified process. + /// + public string[] LoadEnvironmentVariables(ProcessInfo process) + { + if (process == null) + throw new ArgumentNullException("process"); + + return LoadEnvironmentVariables(process.ID); + } + + /// + /// Loads environment variables for specified process. + /// + public string[] LoadEnvironmentVariables(uint processID) + { + var reader = Connection.Request("get env " + processID); + + if (reader != null) + { + // read header: + var header = new Header(); + header.Read(reader); + + // read environment string: + uint length = reader.ReadUInt32(); + var variables = reader.ReadString(length, '\0'); + + return string.IsNullOrEmpty(variables) ? null : variables.Split(new[] { "@@@" }, StringSplitOptions.RemoveEmptyEntries); + } + + return null; + } + + /// + /// Loads startup arguments for specified process. + /// + public string LoadArguments(ProcessInfo process) + { + if (process == null) + throw new ArgumentNullException("process"); + + return LoadArguments(process.ID); + } + + /// + /// Loads startup arguments for specified process. + /// + public string LoadArguments(uint processID) + { + var reader = Connection.Request("get args " + processID); + + if (reader != null) + { + // read header: + var header = new Header(); + header.Read(reader); + + // read arguments string: + uint length = reader.ReadUInt32(); + return reader.ReadString(length, '\0'); + } + + return null; + } + + /// + /// Searches for a running process with specified executable (full name or partial). + /// It will return null, if not found. + /// + public SystemInfoProcess FindProcess(string executable) + { + if (string.IsNullOrEmpty(executable)) + throw new ArgumentNullException("executable"); + + return (SystemInfoProcess) ProcessInfo.Find(LoadProcesses(), executable); + } + + /// + /// Searches for a running process with specified ID. + /// It will return null, if not found. + /// + public SystemInfoProcess FindProcess(uint pid) + { + if (pid == 0) + throw new ArgumentOutOfRangeException("pid"); + + var processes = LoadProcesses(); + foreach (var proc in processes) + { + if (proc.ID == pid) + return proc; + } + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/BaseFileServiceEnumerator.cs b/src_vs2012/NativeCore/QConn/Visitors/BaseFileServiceEnumerator.cs new file mode 100644 index 00000000..fe5164e7 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/BaseFileServiceEnumerator.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Base class for enumerators traversing the abstract file system. + /// + public abstract class BaseFileServiceEnumerator : IFileServiceEnumerator + { + private readonly string _path; + private TargetServiceFile _service; + + /// + /// Init constructor. + /// + public BaseFileServiceEnumerator(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + _path = path; + } + + #region Properties + + /// + /// Gets the reference to the file-service on target. + /// + protected TargetServiceFile Service + { + get { return _service; } + } + + /// + /// Gets the initial path, which is the root of enumeration. + /// + protected string Path + { + get { return _path; } + } + + #endregion + + #region IFileServiceEnumerator + + public void Begin(TargetServiceFile service) + { + if (service == null) + throw new ArgumentNullException("service"); + _service = service; + } + + public void End() + { + _service = null; + } + + public void Enumerate(IFileServiceVisitor visitor) + { + if (visitor == null) + throw new ArgumentNullException("visitor"); + + // gets initial info about path we are about to enumerate: + TargetFile descriptor; + + try + { + descriptor = LoadInitialInfo(_path); + } + catch (Exception ex) + { + descriptor = null; + QTraceLog.WriteException(ex, "Failed to initialize startup description"); + visitor.Failure(null, ex, "Failed to initialize startup description"); + } + + try + { + visitor.Begin(_service, descriptor); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Failed to initialize visitor"); + visitor.Failure(descriptor, ex, "Failed to initialize visitor"); + } + + try + { + if (descriptor != null) + { + PerformEnumeration(visitor, descriptor); + } + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Failed enumeration over \"{0}\"", descriptor != null ? descriptor.Path : "- unknown path -"); + visitor.Failure(descriptor, ex, "Failed to enumerate"); + } + + try + { + visitor.End(); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Failed to clean-up visitor"); + visitor.Failure(descriptor, ex, "Failed to clean-up visitor"); + } + } + + /// + /// Method to visit the whole file system deep-down, starting at given point and read all info around including file contents. + /// Then it's the visitors responsibility to use received data and save it anyhow (keep in memory, store to local file system or ZIP). + /// + private void PerformEnumeration(IFileServiceVisitor visitor, TargetFile descriptor) + { + Stack items = new Stack(); + items.Push(descriptor); + + while (items.Count > 0 && !visitor.IsCancelled) + { + var item = items.Pop(); + + try + { + // do we have an access to open that item? + if (item.NoAccess) + { + visitor.UnknownEntering(item); + continue; + } + + if (item.IsDirectory) + { + // list items inside the directory and add to queue to visit them: + visitor.DirectoryEntering(item); + + var childItems = PerformDirectoryListing(item); + if (childItems != null) + { + // add non-files, to visit them last: + foreach (var child in childItems) + { + if (!child.IsFile) + items.Push(child); + } + + // then add files to visit them immediately: + foreach (var child in childItems) + { + if (child.IsFile) + items.Push(child); + } + } + } + else + { + // download a file and also treat all named-pipes, sockets etc as file and download any content if possible... + PerformFileRead(visitor, item); + } + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Failure during data transfer"); + visitor.Failure(item, ex, "Failure during data transfer"); + } + } + } + + #endregion + + protected abstract TargetFile LoadInitialInfo(string path); + protected abstract void PerformFileRead(IFileServiceVisitor visitor, TargetFile descriptor); + protected abstract TargetFile[] PerformDirectoryListing(TargetFile descriptor); + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/BaseVisitorMonitor.cs b/src_vs2012/NativeCore/QConn/Visitors/BaseVisitorMonitor.cs new file mode 100644 index 00000000..9f8b71b9 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/BaseVisitorMonitor.cs @@ -0,0 +1,273 @@ +using System; +using System.Threading; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Base class for all FileService visitors that want to also support status change notifications and waiting. + /// + public abstract class BaseVisitorMonitor : IFileServiceVisitorMonitor, IDisposable + { + private AutoResetEvent _event; + + private int _lastProgress; + private string _lastDestination; + private string _lastRelativeName; + private TransferOperation _lastOperation; + private TransferOperation _firstOperation; + private int _filesTransferred; + + /// + /// Default constructor. + /// + public BaseVisitorMonitor() + { + _event = new AutoResetEvent(false); + } + + ~BaseVisitorMonitor() + { + Dispose(false); + } + + #region Properties + + /// + /// Gets or sets the indication, if visitor wants to stop further processing. + /// + public bool IsCancelled + { + get; + set; + } + + public IEventDispatcher Dispatcher + { + get; + set; + } + + public object Tag + { + get; + set; + } + + #endregion + + /// + /// Resets the state. It clears the wait-event and fallbacks other fields to default values. + /// + protected void Reset() + { + if (_event == null) + throw new ObjectDisposedException("BaseVisitorMonitor"); + + _event.Reset(); + _lastProgress = -1; + _lastDestination = null; + _lastRelativeName = null; + _lastOperation = TransferOperation.Unknown; + _firstOperation = TransferOperation.Unknown; + _filesTransferred = 0; + + // notify that visiting started: + if (Dispatcher != null) + { + Dispatcher.Invoke(Started, this, new VisitorEventArgs(Tag)); + } + else + { + var handler = Started; + if (handler != null) + { + handler(this, new VisitorEventArgs(Tag)); + } + } + } + + #region IFileServiceVisitorMonitor Implementation + + public event EventHandler Started; + public event EventHandler ProgressChanged; + public event EventHandler Failed; + public event EventHandler Completed; + + /// + /// Notifies subscribed listeners, that visitor finished its task and arms the wait-event. + /// + protected void NotifyCompleted() + { + if (_event == null) + throw new ObjectDisposedException("BaseVisitorMonitor"); + + if (Dispatcher != null) + { + Dispatcher.Invoke(Completed, this, new VisitorCompletionEventArgs(Tag, _firstOperation, IsCancelled, _filesTransferred)); + } + else + { + var handler = Completed; + if (handler != null) + handler(this, new VisitorCompletionEventArgs(Tag, _firstOperation, IsCancelled, _filesTransferred)); + } + + _event.Set(); + } + + /// + /// Notifies that transfer operation of new item has started. + /// + protected void NotifyProgressNew(TargetFile source, string destination, string relativeName, TransferOperation operation) + { + if (_firstOperation == TransferOperation.Unknown) + { + _firstOperation = operation; + } + + var handler = ProgressChanged; + if (handler != null) + { + _lastProgress = 0; + _lastDestination = destination; + _lastRelativeName = relativeName; + _lastOperation = operation; + + var e = new VisitorProgressChangedEventArgs(source, destination, relativeName, 0, 0, operation, Tag); + if (Dispatcher != null) + { + Dispatcher.Invoke(ProgressChanged, this, e); + } + else + { + handler(this, e); + } + } + } + + /// + /// Notifies that transfer operation continues. + /// + protected void NotifyProgressChanged(TargetFile source, ulong transferred) + { + if (source == null) + throw new ArgumentNullException("source"); + + var handler = ProgressChanged; + if (handler != null) + { + int progress = transferred >= source.Size ? 100 : (int) ((transferred * 100) / source.Size); + if (progress != _lastProgress) + { + _lastProgress = progress; + + var e = new VisitorProgressChangedEventArgs(source, _lastDestination, _lastRelativeName, transferred, progress, _lastOperation, Tag); + if (Dispatcher != null) + { + Dispatcher.Invoke(ProgressChanged, this, e); + } + else + { + handler(this, e); + } + } + } + } + + /// + /// Notifies that transfer operation has ended. + /// + protected void NotifyProgressDone(TargetFile source, ulong transferred) + { + _filesTransferred++; + + var handler = ProgressChanged; + if (handler != null && _lastProgress != 100) + { + var destination = _lastDestination; + var relativeName = _lastRelativeName; + var operation = _lastOperation; + + _lastProgress = -1; + _lastDestination = null; + _lastRelativeName = null; + _lastOperation = TransferOperation.Unknown; + + var e = new VisitorProgressChangedEventArgs(source, destination, relativeName, transferred, 100, operation, Tag); + if (Dispatcher != null) + { + Dispatcher.Invoke(ProgressChanged, this, e); + } + else + { + handler(this, e); + } + } + } + + /// + /// Notifies that something has failed. + /// + protected void NotifyFailed(TargetFile descriptor, Exception ex, string message) + { + if (Dispatcher != null) + { + Dispatcher.Invoke(Failed, this, new VisitorFailureEventArgs(descriptor, ex, message, Tag)); + } + else + { + var handler = Failed; + if (handler != null) + { + handler(this, new VisitorFailureEventArgs(descriptor, ex, message, Tag)); + } + } + } + + /// + /// Waits for the transfer operation to complete. + /// + public bool Wait() + { + if (_event == null) + throw new ObjectDisposedException("BaseVisitorMonitor"); + + return _event.WaitOne(); + } + + #endregion + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + Started = null; + ProgressChanged = null; + Completed = null; + Failed = null; + + if (disposing) + { + if (_event != null) + { + _event.Dispose(); + _event = null; + } + } + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/BufferVisitor.cs b/src_vs2012/NativeCore/QConn/Visitors/BufferVisitor.cs new file mode 100644 index 00000000..9f943c4f --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/BufferVisitor.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Class saving the received files only inside memory buffers. + /// + public sealed class BufferVisitor : BaseVisitorMonitor, IFileServiceVisitor + { + private List> _processedBuffers; + private TargetFile _currentFile; + private List _chunks; + + /// + /// Default constructor. + /// + public BufferVisitor() + { + Buffers = new Tuple[0]; + } + + #region Properties + + public int Count + { + get { return Buffers.Length; } + } + + public Tuple[] Buffers + { + get; + private set; + } + + /// + /// Gets the source file name of the first item. + /// + public TargetFile Source + { + get + { + if (Buffers.Length > 0) + { + return Buffers[0].Item1; + } + + return null; + } + } + + /// + /// Gets the buffer value of the first item. + /// + public byte[] Data + { + get + { + if (Buffers.Length > 0) + { + return Buffers[0].Item2; + } + + return null; + } + } + + #endregion + + #region IFileServiceVisitor Implementation + + public void Begin(TargetServiceFile service, TargetFile descriptor) + { + Reset(); + _processedBuffers = new List>(); + _chunks = new List(); + _currentFile = null; + } + + public void End() + { + Buffers = _processedBuffers.ToArray(); + _processedBuffers = null; + _chunks = null; + _currentFile = null; + + NotifyCompleted(); + } + + public void FileOpening(TargetFile file) + { + if (_currentFile != null) + throw new InvalidOperationException("Previous file was not correctly closed"); + _currentFile = file; + _chunks.Clear(); + + NotifyProgressNew(file, file.Name, null, TransferOperation.Buffering); + } + + public void FileContent(TargetFile file, byte[] data, ulong totalRead) + { + if (_currentFile == null) + throw new ObjectDisposedException("BufferVisitor"); + + _chunks.Add(data); + NotifyProgressChanged(file, totalRead); + } + + public void FileClosing(TargetFile file, ulong totalRead) + { + if (_currentFile == null) + throw new ObjectDisposedException("BufferVisitor"); + + _processedBuffers.Add(new Tuple(_currentFile, BitHelper.Combine(_chunks, null, 0))); + _chunks.Clear(); + _currentFile = null; + } + + public void DirectoryEntering(TargetFile folder) + { + // don't care, do nothing + } + + public void UnknownEntering(TargetFile descriptor) + { + // don't care, do nothing + } + + public void Failure(TargetFile descriptor, Exception ex, string message) + { + NotifyFailed(descriptor, ex, message); + } + + #endregion + + /// + /// Gets the content of specified file. + /// + public byte[] Find(string name) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + + // first try to find identical executable: + foreach (var bufferInfo in Buffers) + { + if (string.CompareOrdinal(bufferInfo.Item1.Path, name) == 0) + return bufferInfo.Item2; + } + + // is the name matching: + foreach (var bufferInfo in Buffers) + { + if (string.CompareOrdinal(bufferInfo.Item1.Name, name) == 0) + return bufferInfo.Item2; + } + + // or maybe only ends with it? + foreach (var bufferInfo in Buffers) + { + if (bufferInfo.Item1.Path != null && bufferInfo.Item1.Path.EndsWith(name, StringComparison.Ordinal)) + return bufferInfo.Item2; + } + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/IFileServiceEnumerator.cs b/src_vs2012/NativeCore/QConn/Visitors/IFileServiceEnumerator.cs new file mode 100644 index 00000000..75d2a10e --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/IFileServiceEnumerator.cs @@ -0,0 +1,32 @@ +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Interface defining the protocol of enumerating file-system resources. + /// + /// Potential usages could be: + /// - enumerating target device file-system + /// - enumerating local files and folders + /// - enumerating content of the local zip-package + /// + public interface IFileServiceEnumerator + { + /// + /// Called once at very beginning to setup the enumerator. + /// It should never block. + /// + void Begin(TargetServiceFile service); + + /// + /// Called once at the end to clean-up used resources. + /// + void End(); + + /// + /// Called in dedicated thread, so it might take as much time as needed. + /// It should enumerate all known items calling proper method of the specified visitor. + /// + void Enumerate(IFileServiceVisitor visitor); + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/IFileServiceVisitor.cs b/src_vs2012/NativeCore/QConn/Visitors/IFileServiceVisitor.cs new file mode 100644 index 00000000..39633bde --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/IFileServiceVisitor.cs @@ -0,0 +1,69 @@ +using System; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Interface used, when traversing over file system, when downloading files from the target. + /// + public interface IFileServiceVisitor + { + /// + /// Gets or sets the indication, if visitor wants to stop further processing. + /// + bool IsCancelled + { + get; + set; + } + + /// + /// Any object associated with this visitor. + /// + object Tag + { + get; + set; + } + + /// + /// Called once, when visiting has started. + /// + void Begin(TargetServiceFile service, TargetFile descriptor); + + /// + /// Called once, when visiting has finished. + /// + void End(); + + /// + /// Called once for each new file, which is supposed to be downloaded. + /// + void FileOpening(TargetFile file); + /// + /// Called each time part of the file is being downloaded. + /// + void FileContent(TargetFile file, byte[] data, ulong totalRead); + /// + /// Called once for each file, when download has been completed or cancelled. + /// + void FileClosing(TargetFile file, ulong totalRead); + + /// + /// Called each time, when entering new folder. + /// It will be followed by number of calls to file downloads. + /// + void DirectoryEntering(TargetFile folder); + + /// + /// Called each time unexpected item was visited (for example, when no rights to enter or read). + /// + void UnknownEntering(TargetFile descriptor); + + /// + /// Called each time a failure happened. + /// + void Failure(TargetFile descriptor, Exception ex, string message); + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/IFileServiceVisitorMonitor.cs b/src_vs2012/NativeCore/QConn/Visitors/IFileServiceVisitorMonitor.cs new file mode 100644 index 00000000..6214f3a0 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/IFileServiceVisitorMonitor.cs @@ -0,0 +1,55 @@ +using System; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.Tools; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Interface informing about additional status changes of the visitors. + /// + public interface IFileServiceVisitorMonitor + { + /// + /// Gets or sets the indication, if visitor wants to stop further processing. + /// + bool IsCancelled + { + get; + set; + } + + /// + /// Gets or sets the dispatcher object to handle callbacks invocations. + /// + IEventDispatcher Dispatcher + { + get; + set; + } + + /// + /// Event triggered, when visiting has started. + /// + event EventHandler Started; + + /// + /// Event fired any time data transfer progress has changed. + /// + event EventHandler ProgressChanged; + + /// + /// Event fired each time transfer has failed. + /// + event EventHandler Failed; + + /// + /// Event triggered, when visiting finished. + /// + event EventHandler Completed; + + /// + /// Waits until visiting is not fully completed. + /// + bool Wait(); + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/LocalCopyVisitor.cs b/src_vs2012/NativeCore/QConn/Visitors/LocalCopyVisitor.cs new file mode 100644 index 00000000..5388e205 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/LocalCopyVisitor.cs @@ -0,0 +1,181 @@ +using System; +using System.IO; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Class saving the received files into local file system. + /// + public class LocalCopyVisitor : BaseVisitorMonitor, IFileServiceVisitor + { + private readonly string _outputPath; + private string _basePath; + private bool _singleFileDownload; + private Stream _stream; + + /// + /// Init constructor. + /// + public LocalCopyVisitor(string outputPath) + { + if (string.IsNullOrEmpty(outputPath)) + throw new ArgumentNullException("outputPath"); + + _outputPath = outputPath; + } + + /// + /// Init constructor. + /// + public LocalCopyVisitor(string outputPath, object tag) + : this(outputPath) + { + Tag = tag; + } + + #region IFileServiceVisitor Implementation + + public void Begin(TargetServiceFile service, TargetFile descriptor) + { + Reset(); + _stream = null; + + if (descriptor == null) + return; + + if (!descriptor.IsDirectory) + { + // only downloading a single file: + _singleFileDownload = true; + _basePath = null; + } + else + { + // copying folder, so get parent folder, to remember where is the root, to make processed paths of each received file or folder shorter + _singleFileDownload = false; + _basePath = PathHelper.ExtractDirectory(descriptor.Path); + } + } + + public void End() + { + Close(); + NotifyCompleted(); + } + + public void FileOpening(TargetFile file) + { + if (_stream != null) + throw new InvalidOperationException("Previous file was not correctly closed"); + + // assumption is that directory entering, supposed to create whole directory structure, + // was already called before on that visitor: + + string relativeName; + string name; + + if (_singleFileDownload) + { + name = _outputPath; + relativeName = PathHelper.ExtractName(_outputPath); + } + else + { + name = GetLocalPath(file, out relativeName); + } + + _stream = File.Create(name, TargetServiceFile.DownloadUploadChunkSize, FileOptions.SequentialScan); + NotifyProgressNew(file, name, relativeName, TransferOperation.Downloading); + } + + public void FileContent(TargetFile file, byte[] data, ulong totalRead) + { + if (_stream == null) + throw new ObjectDisposedException("LocalCopyVisitor"); + + _stream.Write(data, 0, data.Length); + NotifyProgressChanged(file, totalRead); + } + + public void FileClosing(TargetFile file, ulong totalRead) + { + if (_stream == null) + throw new ObjectDisposedException("LocalCopyVisitor"); + + _stream.Close(); + _stream = null; + + NotifyProgressDone(file, totalRead); + } + + public void DirectoryEntering(TargetFile folder) + { + string ignored; + var name = GetLocalPath(folder, out ignored); + Directory.CreateDirectory(name); + } + + public void UnknownEntering(TargetFile descriptor) + { + // just create simple empty file: + string relativeName; + var name = GetLocalPath(descriptor, out relativeName); + + var stream = File.Create(name); + stream.Close(); + + NotifyProgressNew(descriptor, name, relativeName, TransferOperation.Downloading); + NotifyProgressDone(descriptor, 0); + } + + public void Failure(TargetFile descriptor, Exception ex, string message) + { + NotifyFailed(descriptor, ex, message); + } + + private string GetLocalPath(TargetFile descriptor, out string name) + { + if (descriptor == null) + throw new ArgumentNullException("descriptor"); + + name = descriptor.Path.StartsWith(_basePath) ? descriptor.Path.Substring(_basePath.Length + (IsPathSeparator(descriptor.Path, _basePath.Length) ? 1 : 0)) : descriptor.Path; + name = name.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + + return Path.Combine(_outputPath, name); + } + + private bool IsPathSeparator(string path, int index) + { + if (string.IsNullOrEmpty(path)) + return false; + if (index < 0 || index >= path.Length) + return false; + + return path[index] == Path.DirectorySeparatorChar || path[index] == Path.AltDirectorySeparatorChar; + } + + #endregion + + private void Close() + { + if (_stream != null) + { + _stream.Close(); + _stream = null; + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Close(); + } + + base.Dispose(disposing); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/LocalEnumerator.cs b/src_vs2012/NativeCore/QConn/Visitors/LocalEnumerator.cs new file mode 100644 index 00000000..91e11516 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/LocalEnumerator.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Enumerator class that is able to access file-system on current desktop machine. + /// Location can point to single file or folder (it will then go through whole subtree). + /// + public sealed class LocalEnumerator : BaseFileServiceEnumerator + { + /// + /// Init constructor. + /// + public LocalEnumerator(string path) + : base(path) + { + } + + protected override TargetFile LoadInitialInfo(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + try + { + var attributes = File.GetAttributes(path); + + // create fully-featured info about the local file or folder: + FileSystemInfo info; + if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) + { + info = new DirectoryInfo(path); + } + else + { + info = new FileInfo(path); + } + + return new TargetFile(info); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Unable to access: \"{0}\"", path); + + // or a stub, in case directory doesn't exist nor we have rights to open it: + return new TargetFile(path, System.IO.Path.GetFileName(path), false); + } + } + + protected override TargetFile[] PerformDirectoryListing(TargetFile descriptor) + { + // is it really an existing folder? + if (descriptor == null || !Directory.Exists(descriptor.Path)) + return null; + + // if so, then read all file and folder names: + var result = new List(); + + foreach (var file in Directory.EnumerateFiles(descriptor.Path)) + { + result.Add(new TargetFile(new FileInfo(file))); + } + + foreach (var directory in Directory.EnumerateDirectories(descriptor.Path)) + { + result.Add(new TargetFile(new DirectoryInfo(directory))); + } + + // and return, so they are + return result.ToArray(); + } + + protected override void PerformFileRead(IFileServiceVisitor visitor, TargetFile descriptor) + { + if (descriptor == null || !File.Exists(descriptor.Path)) + return; + + ulong totalRead = 0ul; + using (var file = new FileStream(descriptor.Path, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + try + { + visitor.FileOpening(descriptor); + + var data = new byte[TargetServiceFile.DownloadUploadChunkSize]; + + while (!visitor.IsCancelled) + { + var length = file.Read(data, 0, data.Length); + if (length > 0) + { + totalRead += (ulong) length; + + // is last chunk? + if (length != TargetServiceFile.DownloadUploadChunkSize) + { + // because, if it is, we need to allocate smaller array matching the size + var lastData = new byte[length]; + Array.Copy(data, 0, lastData, 0, length); + visitor.FileContent(descriptor, lastData, totalRead); + break; + } + + visitor.FileContent(descriptor, data, totalRead); + } + else + { + break; + } + } + } + finally + { + visitor.FileClosing(descriptor, totalRead); + } + } + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/LoggingVisitor.cs b/src_vs2012/NativeCore/QConn/Visitors/LoggingVisitor.cs new file mode 100644 index 00000000..94f163e3 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/LoggingVisitor.cs @@ -0,0 +1,84 @@ +using System; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Support class to log statistics about visited files and folders. + /// Mostly for testing scenarios. + /// + public sealed class LoggingVisitor : BaseVisitorMonitor, IFileServiceVisitor + { + #region Properties + + public uint FilesCount + { + get; + private set; + } + + public ulong TotalSize + { + get; + private set; + } + + #endregion + + public void Begin(TargetServiceFile service, TargetFile descriptor) + { + Reset(); + + QTraceLog.WriteLine("Initializing download for: {0}", descriptor.Path); + FilesCount = 0; + TotalSize = 0; + } + + public void End() + { + QTraceLog.WriteLine("- DONE -"); + + // notify about completion: + NotifyCompleted(); + } + + public void FileOpening(TargetFile file) + { + QTraceLog.WriteLine("Started downloading: {0}", file.Name); + FilesCount = FilesCount + 1; + + NotifyProgressNew(file, file.Name, null, TransferOperation.Buffering); + } + + public void FileContent(TargetFile file, byte[] data, ulong totalRead) + { + QTraceLog.WriteLine("Downloaded: {0}", data.Length); + NotifyProgressChanged(file, totalRead); + } + + public void FileClosing(TargetFile file, ulong totalRead) + { + QTraceLog.WriteLine("Completed downloading: {0}", file.Name); + TotalSize = TotalSize + totalRead; + + NotifyProgressDone(file, totalRead); + } + + public void DirectoryEntering(TargetFile folder) + { + QTraceLog.WriteLine("Entering directory: {0}", folder.Name); + } + + public void UnknownEntering(TargetFile other) + { + // no idea, if this is a directory or file or named-pipe or socket... we simply don't have rights to visit it... so ignore in statistics + } + + public void Failure(TargetFile descriptor, Exception ex, string message) + { + NotifyFailed(descriptor, ex, message); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/TargetCopyVisitor.cs b/src_vs2012/NativeCore/QConn/Visitors/TargetCopyVisitor.cs new file mode 100644 index 00000000..f18cb625 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/TargetCopyVisitor.cs @@ -0,0 +1,207 @@ +using System; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Class saving the received files directly on target file-system. + /// + public sealed class TargetCopyVisitor : BaseVisitorMonitor, IFileServiceVisitor + { + private readonly string _outputPath; + private string _basePath; + private bool _singleFileDownload; + private TargetServiceFile _service; + private TargetFileDescriptor _currentFile; + + /// + /// Init constructor. + /// + public TargetCopyVisitor(string outputPath) + { + if (string.IsNullOrEmpty(outputPath)) + throw new ArgumentNullException("outputPath"); + + _outputPath = outputPath; + } + + /// + /// Init constructor. + /// + public TargetCopyVisitor(string outputPath, object tag) + : this(outputPath) + { + Tag = tag; + } + + #region IFileServiceVisitor Implementation + + public void Begin(TargetServiceFile service, TargetFile descriptor) + { + if (service == null) + throw new ArgumentNullException("service"); + _service = service; + + Reset(); + + if (descriptor == null) + return; + + if (!descriptor.IsDirectory) + { + // only downloading a single file: + _singleFileDownload = true; + _basePath = null; + } + else + { + // copying folder, so get parent folder, to remember where is the root, to make processed paths of each received file or folder shorter + _singleFileDownload = false; + _basePath = PathHelper.ExtractDirectory(descriptor.Path); + + // make sure path ends with '\\': + if (!string.IsNullOrEmpty(_basePath) && _basePath[_basePath.Length - 1] != Path.DirectorySeparatorChar && _basePath[_basePath.Length - 1] != Path.AltDirectorySeparatorChar) + { + _basePath += Path.DirectorySeparatorChar; + } + } + } + + public void End() + { + Close(); + NotifyCompleted(); + } + + public void FileOpening(TargetFile file) + { + if (_service == null) + throw new ObjectDisposedException("TargetCopyVisitor"); + + string name; + string relativeName; + + if (_singleFileDownload) + { + if (IsPathSeparator(_outputPath, _outputPath.Length - 1)) + { + relativeName = PathHelper.ExtractName(file.Path); + name = PathHelper.MakePath(_outputPath, relativeName); + } + else + { + name = _outputPath; + relativeName = PathHelper.ExtractName(_outputPath); + } + } + else + { + name = GetTargetPath(file, out relativeName); + } + + _currentFile = _service.CreateNewFile(name, TargetFile.ModePermissionDefault); + NotifyProgressNew(file, name, relativeName, TransferOperation.Uploading); + } + + public void FileContent(TargetFile file, byte[] data, ulong totalRead) + { + if (_service == null) + throw new ObjectDisposedException("TargetCopyVisitor"); + if (_currentFile == null) + throw new InvalidOperationException("File is already close"); + + uint length = _service.Write(_currentFile, data); + if (length != data.Length) + throw new QConnException("Unable to write data to \"" + _currentFile.Path + "\""); + + NotifyProgressChanged(file, totalRead); + } + + public void FileClosing(TargetFile file, ulong totalRead) + { + if (_service == null) + throw new ObjectDisposedException("TargetCopyVisitor"); + if (_currentFile == null) + throw new InvalidOperationException("File is already closed"); + + _currentFile.Close(); + _currentFile = null; + + NotifyProgressDone(file, totalRead); + } + + public void DirectoryEntering(TargetFile folder) + { + if (_service == null) + throw new ObjectDisposedException("TargetCopyVisitor"); + + string ignored; + var name = GetTargetPath(folder, out ignored); + + try + { + _service.CreateFolder(name, TargetFile.ModePermissionDefault); + } + catch (Exception ex) + { + QTraceLog.WriteException(ex, "Unable to create folder: \"{0}\"", name); + } + } + + public void UnknownEntering(TargetFile descriptor) + { + // do nothing - ignore them - as expected are files and folders from known source! + } + + public void Failure(TargetFile descriptor, Exception ex, string message) + { + NotifyFailed(descriptor, ex, message); + } + + private static bool IsPathSeparator(string path, int index) + { + if (string.IsNullOrEmpty(path)) + return false; + if (index < 0 || index > path.Length) + return false; + + return path[index] == Path.DirectorySeparatorChar || path[index] == Path.AltDirectorySeparatorChar; + } + + private string GetTargetPath(TargetFile descriptor, out string name) + { + if (descriptor == null) + throw new ArgumentNullException("descriptor"); + + name = descriptor.Path.StartsWith(_basePath) ? descriptor.Path.Substring(_basePath.Length) : descriptor.Path; + name = name.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + + return PathHelper.MakePath(_outputPath, name); + } + + #endregion + + private void Close() + { + if (_currentFile != null) + { + _currentFile.Close(); + _currentFile = null; + } + _service = null; + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Close(); + } + base.Dispose(disposing); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/TargetEnumerator.cs b/src_vs2012/NativeCore/QConn/Visitors/TargetEnumerator.cs new file mode 100644 index 00000000..6429bf05 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/TargetEnumerator.cs @@ -0,0 +1,80 @@ +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Enumerator class that is able to access file-system on a target. + /// Location can point to single file or folder (it will then go through whole subtree). + /// + public sealed class TargetEnumerator : BaseFileServiceEnumerator + { + /// + /// Init constructor. + /// Enumeration will take place from specified file or folder. + /// + public TargetEnumerator(string path) + : base(path) + { + } + + protected override TargetFile LoadInitialInfo(string path) + { + // load info about the initial path: + var descriptor = Service.Stat(path, false); + if (descriptor == null) + { + descriptor = new TargetFile(path, null, false); + } + + return descriptor; + } + + protected override void PerformFileRead(IFileServiceVisitor visitor, TargetFile descriptor) + { + ulong totalRead = 0ul; + + using (var file = Service.Open(descriptor.Path, TargetFile.ModeOpenReadOnly, 0, false)) + { + if (file != null) + { + try + { + visitor.FileOpening(file); + + while (!visitor.IsCancelled) + { + // read following chunks of the file + // (it's crucial that we use the same chunk size as during service cloning, so it will minimize the number of buffer allocations) + var data = Service.Read(file, totalRead, TargetServiceFile.DownloadUploadChunkSize); + if (data != null && data.Length > 0) + { + totalRead += (ulong) data.Length; + visitor.FileContent(descriptor, data, totalRead); + + // is last chunk? + if (data.Length != TargetServiceFile.DownloadUploadChunkSize) + { + break; + } + } + else + { + break; + } + } + } + finally + { + visitor.FileClosing(file, totalRead); + } + } + } + } + + protected override TargetFile[] PerformDirectoryListing(TargetFile descriptor) + { + return Service.List(descriptor); + } + } +} diff --git a/src_vs2012/NativeCore/QConn/Visitors/ZipPackageVisitor.cs b/src_vs2012/NativeCore/QConn/Visitors/ZipPackageVisitor.cs new file mode 100644 index 00000000..4a1657f9 --- /dev/null +++ b/src_vs2012/NativeCore/QConn/Visitors/ZipPackageVisitor.cs @@ -0,0 +1,195 @@ +using System; +using System.IO; +using System.IO.Packaging; +using System.Text; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.QConn.Model; +using BlackBerry.NativeCore.QConn.Services; + +namespace BlackBerry.NativeCore.QConn.Visitors +{ + /// + /// Class packaging the received files into a dedicated ZIP file. + /// + public sealed class ZipPackageVisitor : BaseVisitorMonitor, IFileServiceVisitor + { + private readonly string _fileName; + private readonly CompressionOption _compression; + private string _basePath; + private Package _package; + private PackagePart _currentPart; + private Stream _currentStream; + + /// + /// Init constructor. + /// + public ZipPackageVisitor(string fileName, CompressionOption compression) + { + if (string.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + + _fileName = fileName; + _compression = compression; + } + + /// + /// Init constructor. + /// + public ZipPackageVisitor(string fileName, CompressionOption compression, object tag) + : this(fileName, compression) + { + Tag = tag; + } + + #region IFileServiceVisitor Implementation + + public void Begin(TargetServiceFile service, TargetFile descriptor) + { + Reset(); + _package = Package.Open(_fileName, FileMode.Create); + _basePath = GetInitialBasePath(descriptor); + } + + private static string GetInitialBasePath(TargetFile descriptor) + { + if (descriptor == null) + return null; + + if (!descriptor.IsDirectory) + { + // get the base path to the home folder of the single file processed: + return PathHelper.ExtractDirectory(descriptor.Path); + } + + // get whole folder, to remember where is the root, to make processed paths of each received file or folder shorter + return descriptor.Path; + } + + public void End() + { + Close(); + NotifyCompleted(); + } + + public void FileOpening(TargetFile file) + { + string shortName; + _currentPart = CreatePart(file.Path, out shortName); + + if (_currentPart == null) + throw new InvalidOperationException("Unable to create package part to store file content"); + + _currentStream = _currentPart.GetStream(); + NotifyProgressNew(file, DecodeNameForProgress(shortName), null, TransferOperation.Downloading); + } + + private static string DecodeNameForProgress(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + if (path[0] == '/' || path[0] == '\\') + { + path = path.Substring(1); + } + + // unify separators with other visitors: + return path.Replace('/', '\\'); + } + + public void FileContent(TargetFile file, byte[] data, ulong totalRead) + { + if (_currentPart == null) + throw new ObjectDisposedException("ZipPackageVisitor"); + + _currentStream.Write(data, 0, data.Length); + NotifyProgressChanged(file, totalRead); + } + + public void FileClosing(TargetFile file, ulong totalRead) + { + if (_currentStream != null) + { + _currentStream.Close(); + _currentStream = null; + } + _currentPart = null; + NotifyProgressDone(file, totalRead); + } + + public void DirectoryEntering(TargetFile folder) + { + // don't care, do nothing + } + + public void UnknownEntering(TargetFile other) + { + string shortName; + + // create 0-length entry: + CreatePart(other.Path, out shortName); + } + + public void Failure(TargetFile descriptor, Exception ex, string message) + { + NotifyFailed(descriptor, ex, message); + } + + private PackagePart CreatePart(string fullName, out string shortName) + { + if (_package == null) + throw new ObjectDisposedException("PackagingFileServiceVisitor"); + + var uri = PackUriHelper.CreatePartUri(GetRelativeUri(fullName, out shortName)); + + if (_package.PartExists(uri)) + { + _package.DeletePart(uri); + } + + return _package.CreatePart(uri, string.Empty, _compression); + } + + private Uri GetRelativeUri(string fullName, out string shortName) + { + if (string.IsNullOrEmpty(fullName)) + throw new ArgumentNullException("fullName"); + + if (fullName.StartsWith(_basePath)) + { + shortName = fullName.Substring(_basePath.Length); + return new Uri(shortName, UriKind.Relative); + } + + shortName = fullName; + return new Uri(fullName, UriKind.Relative); + } + + #endregion + + private void Close() + { + if (_currentStream != null) + { + _currentStream.Close(); + _currentStream = null; + } + _currentPart = null; + if (_package != null) + { + _package.Close(); + _package = null; + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Close(); + } + + base.Dispose(disposing); + } + } +} diff --git a/src_vs2012/NativeCore/Resources/Instructions.txt b/src_vs2012/NativeCore/Resources/Instructions.txt new file mode 100644 index 00000000..2026a2be --- /dev/null +++ b/src_vs2012/NativeCore/Resources/Instructions.txt @@ -0,0 +1,48 @@ +asynchronous:->:??=thread-exited,id;{#51\;;??";@@";#$EOL$;};??thread-created,id;{#40\;;??";@@";#\;;??pid ;@@ ;#$EOL$;};0;??*running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};#$EOL$;};0;??*stopped;{??breakpoint-hit;{#27\;;??bkptno=";@@";#\;;??file=";@@";#\;;??line=";@@";}{??end-stepping-range;{#45;??file=";{#\;;@@";0;#\;;??line=";@@";};}{??function-finished;{#46;??file=;{#\;;??";@@";#\;;??line=";@@";};}{??exited-normally;{#42;}{??exit-code;{#43\;;??";@@";}{??signal-received;{??signal-meaning="Killed";{#47;}{??signal-meaning="Segmentation fault";{#54\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};}{??signal-meaning="Aborted";{#55\;;0;??signal-name=";@@";#\;;??signal-meaning=";@@";}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};}{??exited-signalled;{#55\;;0;??signal-name=";@@";#\;;??signal-meaning=";@@";}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};};};};};#\;;??thread-id=;{??";@@";};#$EOL$;};0;??=breakpoint-modified,bkpt=\{number=";{0;($EOR$;$1=?:($EOR$;$1=?:??(gdb);{0;#80\;";(??~";?:??^connected;{0;#80\;";(??~";?:??^done;{0;#80\;";(??~";?:??^done;#File uploaded!; +-target-attach:->:??^done;{#state="stopped"\;processID=";0;??pid=";@@";#"\;thread-ID=";??thread-created,id=";@@";0;#"\;$EOL$80\;";(??~";?:??^done;#File and symbols loaded.; +-gdb-set:->:??^done;{#done;}; +set:->:??^done;{#done;}; +-exec-arguments:->:??^done;#Arguments loaded.; +-exec-run:->:??^running;{0;#40\;;??thread-created,id=";@@";0;??pid=";#\;;@@";0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??^running;{#41\;;??thread-id="all;{#0;}{??thread-id=";@@";};0;#$EOL$;(??~";#80\;";?:??=breakpoint-created;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{??^error;{#ERROR: ;??msg=";@@";#$EOL$;(??&";#80\;";?:??^done;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{#Function not found!;}; +-break-watch:->:??^done;{#20\;;??number=";{@@";};#\;;??enabled=";{@@";};#\;;??addr=";{@@";};#\;;??func=";{@@";};#\;;??file=";{@@";};#\;;??line=";{@@";};#\;;??times=";{@@";};}{#Function not found!;}; +$-break-delete:->:??^done;{#25;@@$EOL$}; +$-break-disable:->:??^done;{#24;@@$EOL$}; +$-break-enable:->:??^done;{#23;@@$EOL$}; +$-break-after:->:??^done;{#26;@@$EOL$}; +$-break-condition:->:??^done;{#28;@@$EOL$}; +-break-list:->:??^done;{(??number=";#21\;;@@";#\;;??enabled=";@@";#\;;??addr=";@@";#\;;??func=";@@";#\;;??file=";@@";#\;;??line=";@@";#\;;??times=";@@";):$EOL$;}; +kill:->:??^done;{#done;}; +generate-core-file:->:#NOT CREATED! +jump:->:#NOT CREATED! +handle:->:#NOT CREATED! +watch:->:#NOT CREATED! +interrupt:->:#NOT CREATED! +show:->:#NOT CREATED! +-stack-info-depth:->:??^done,depth=";@@";$EOL$ +-stack-list-frames:->:??^done;{(??level=;{??";@@";};~"\};#\;;??addr=;{??";@@";};#\;;??func=;{??";@@";};#\;;??file=;{??";@@";};#\;;??line=;{??";@@";};);}; +-stack-select-frame:->:??^done;{#done;}; +-stack-list-variables:->:??^done;{#70\;;(??name=;{??";@@";};~"\};#\;;??arg=;{??";@@";};#\;;??type=;{??";@@";};#\;;??value=;{??";@@";};);}{#ERROR;}; +-var-create:->:??^done;{??numchild=";@@";}{#ERROR;}; +-var-delete:->:??^done;{#DONE;}{#ERROR;}; +-var-list-children:->:??^done;{#71\;;(??name=;{??";@@";};~"\};#\;;??numchild=;{??";@@";};#\;;??value=;{??";@@";};#\;;??type=;{??";@@";};);}{#ERROR;}; +-data-evaluate-expression:->:??^done;{??value=";#60\;;@@";$EOL$;}{??^error;{??-data-evaluate-expression: Usage: -data-evaluate-expression expression;{#61\;Error in expression.;}{??A syntax error in expression, near `'.;{#61\;A syntax error at the end of the expression.;}{??=;#61\;;@@$EOL$;};};};}; +ptype:->:??type = ;{@@\\n";}{# ;}; +whatis:->:??type = ;{@@\\n";}{# ;}; +-exec-interrupt:->:??^done;{??signal-received;{??signal-meaning="Killed";{#47;}{#44\;;??addr=";@@";#\;;??func=";@@";0;??file=;{#\;;??";@@";#\;;??line=";@@";};};};};#\;;??thread-id=;{??";@@";}; +-target-detach:->:#NOT CREATED! +-var-info-num-children:->:??numchild;{??";@@";}{#ERROR;}; +info:->:??Address;{??0x;?:??^done;{(??\{id=";@@";#\;;??state=;{??";@@";};#\;;~\};?:??^done;{#done;}; diff --git a/src_vs2012/NativeCore/Services/IAttachDiscoveryService.cs b/src_vs2012/NativeCore/Services/IAttachDiscoveryService.cs new file mode 100644 index 00000000..d8ae8532 --- /dev/null +++ b/src_vs2012/NativeCore/Services/IAttachDiscoveryService.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; +using BlackBerry.NativeCore.Debugger.Model; + +namespace BlackBerry.NativeCore.Services +{ + /// + /// Service dedicated to attaching to a process running on target. + /// It allows discovering matching local executable (binary) from currently active projects, + /// so that the debugger can issue breakpoints and step through the code. + /// + [Guid("71465b7f-1730-4d55-8e5d-65ddb14a0ce1")] + public interface IAttachDiscoveryService + { + /// + /// Find path to local executable matching running process. + /// + string FindExecutable(ProcessInfo process); + } +} diff --git a/src_vs2012/NativeCore/Services/IDeviceDiscoveryService.cs b/src_vs2012/NativeCore/Services/IDeviceDiscoveryService.cs new file mode 100644 index 00000000..008e4bbe --- /dev/null +++ b/src_vs2012/NativeCore/Services/IDeviceDiscoveryService.cs @@ -0,0 +1,17 @@ +using System.Runtime.InteropServices; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Services +{ + /// + /// Interface exposed by components providing find-a-running-device feature. + /// + [Guid("0a034a4d-dfe3-405d-86c9-b47602813df8")] + public interface IDeviceDiscoveryService + { + /// + /// Do anything what needed to allow developer to find a device and return it or null, if cancelled or not found. + /// + DeviceDefinition FindDevice(); + } +} diff --git a/src_vs2012/NativeCore/Tools/ApiLevelListLoadRunner.cs b/src_vs2012/NativeCore/Tools/ApiLevelListLoadRunner.cs new file mode 100644 index 00000000..d0e4396e --- /dev/null +++ b/src_vs2012/NativeCore/Tools/ApiLevelListLoadRunner.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to list available NDKs or simulator versions. + /// + public sealed class ApiLevelListLoadRunner : BBToolRunner + { + private ApiLevelListTypes _type; + + /// + /// Init constructor. + /// + public ApiLevelListLoadRunner(string workingDirectory, ApiLevelListTypes type) + : base(workingDirectory) + { + Type = type; + } + + #region Properties + + /// + /// Gets or sets the type of list to load. + /// + public ApiLevelListTypes Type + { + get { return _type; } + set + { + _type = value; + UpdateArguments(); + } + } + + /// + /// Gets the installation descriptor location. + /// + public Uri DescriptorLocation + { + get; + private set; + } + + /// + /// Gets the list received from server. + /// + public ApiInfo[] APIs + { + get; + private set; + } + + /// + /// Gets the grouped by Level list. + /// + public ApiInfoArray[] ApiLevels + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + string args = "/C eclipsec.exe"; + + switch (Type) + { + case ApiLevelListTypes.Default: + args += " --list"; + break; + case ApiLevelListTypes.Full: + args += " --list-all"; + break; + case ApiLevelListTypes.Simulators: + args += " --list-all --simulator"; + break; + case ApiLevelListTypes.Runtimes: + args += " --list-all --runtime"; + break; + default: + throw new InvalidOperationException("Specified list type is unsupported (" + Type + ")"); + } + + Arguments = args; + } + + protected override void ConsumeResults(string output, string error) + { + DescriptorLocation = null; + APIs = new ApiInfo[0]; + + if (!string.IsNullOrEmpty(output)) + { + var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var result = new List(); + + foreach (var line in lines) + { + // runtime error: + if (line.StartsWith("error:", StringComparison.InvariantCultureIgnoreCase)) + { + LastError = line.Substring(6).Trim(); + continue; + } + + // gets the metadata location: + if (line.StartsWith("location:", StringComparison.InvariantCultureIgnoreCase)) + { + DescriptorLocation = new Uri(line.Substring(9).Trim()); + continue; + } + + // ignore this line: + if (line.StartsWith("available sdk", StringComparison.InvariantCultureIgnoreCase)) + { + continue; + } + + // SDK entries: + int separatorIndex = line.LastIndexOf(" - ", StringComparison.Ordinal); + if (separatorIndex > 0) + { + string name = line.Substring(separatorIndex + 3); + string version = line.Substring(0, separatorIndex); + + if (name.EndsWith("(SIMULATOR)", StringComparison.InvariantCultureIgnoreCase)) + { + name = name.Substring(0, name.Length - 11).Replace("10 Native SDK", "Simulator").Replace("Native SDK", "Simulator"); + } + if (name.EndsWith("(EXTERNAL_NDK)", StringComparison.InvariantCultureIgnoreCase)) + { + name = name.Substring(0, name.Length - 14); + } + if (name.EndsWith("(RUNTIME)", StringComparison.InvariantCultureIgnoreCase)) + { + name = name.Substring(0, name.Length - 9).Replace("10 Native SDK", "Runtime Libraries").Replace("Native SDK", "Runtime Libraries"); + } + + // PH: TODO: there is no way to load list of tablet NDKs from server, so mark all of them as 'phone'... + result.Add(new ApiInfo(name.Trim(), new Version(version), DeviceFamilyType.Phone)); + } + } + + APIs = result.ToArray(); + Array.Sort(APIs); + } + + // group the received list by level: + ApiLevels = GroupList(APIs, Type != ApiLevelListTypes.Simulators && Type != ApiLevelListTypes.Runtimes); + } + + /// + /// Sorts the list of given API levels and injects some special ones (to download PlayBook NDK and 'Add custom local NDK') + /// + public static ApiInfoArray[] GroupList(ApiInfo[] list, bool injectExtraActions) + { + if ((list == null || list.Length == 0) && !injectExtraActions) + return new ApiInfoArray[0]; + + var groups = new List>(); + + if (injectExtraActions) + { + // inject info about BBNDK for VS: + if (!Directory.Exists(ConfigDefaults.NdkDirectory)) + { + AddUnique(groups, ApiInfo.CreateBBNDKforVSInfo()); + } + + // inject info about tablet NDK: + AddUnique(groups, ApiInfo.CreateTabletInfo()); + + // inject info about 'custom NDK': + AddUnique(groups, ApiInfo.CreateAddCustomInfo()); + } + + // group BlackBerry 10 items together: + if (list != null && list.Length > 0) + { + foreach (var item in list) + { + Add(groups, item); + } + } + + // convert to pure arrays and assign the name for each group: + var result = new ApiInfoArray[groups.Count]; + int i = 0; + foreach (var item in groups) + { + result[i++] = new ApiInfoArray(SimplifyName(item[item.Count - 1]), item[0].Level, item.ToArray()); + } + + return result; + } + + /// + /// Get the name of specified item without full version. + /// + private static string SimplifyName(ApiInfo item) + { + if (item == null) + throw new ArgumentNullException("item"); + + if (item.Name.Contains(item.Version.ToString())) + return item.Name.Replace(item.Version.ToString(), item.Level.ToString()); + + return item.Name; + } + + private static void Add(ICollection> groups, ApiInfo item) + { + if (groups == null) + throw new ArgumentNullException("groups"); + + var group = Find(groups, item.Level); + if (group != null) + { + group.Add(item); + } + else + { + AddUnique(groups, item); + } + } + + private static void AddUnique(ICollection> groups, ApiInfo item) + { + if (groups == null) + throw new ArgumentNullException("groups"); + + var group = new List(); + group.Add(item); + groups.Add(group); + } + + private static List Find(IEnumerable> groups, Version level) + { + foreach (var item in groups) + { + Debug.Assert(item.Count > 0, "Invalid number of items!"); + if (item[0].Level == level) + return item; + } + + return null; + } + } +} diff --git a/src_vs2012/NativeCore/Tools/ApiLevelUpdateLogEventArgs.cs b/src_vs2012/NativeCore/Tools/ApiLevelUpdateLogEventArgs.cs new file mode 100644 index 00000000..0f4c8478 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/ApiLevelUpdateLogEventArgs.cs @@ -0,0 +1,46 @@ +using System; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Arguments passed along with 'Log' event. + /// + public class ApiLevelUpdateLogEventArgs : EventArgs + { + public ApiLevelUpdateLogEventArgs(string message, int progress, bool canAbort) + { + Message = message; + Progress = progress; + CanAbort = canAbort; + } + + public ApiLevelUpdateLogEventArgs(string message) + { + Message = message; + Progress = -1; + CanAbort = true; + } + + #region Properties + + public string Message + { + get; + private set; + } + + public int Progress + { + get; + private set; + } + + public bool CanAbort + { + get; + private set; + } + + #endregion + } +} \ No newline at end of file diff --git a/src_vs2012/NativeCore/Tools/ApiLevelUpdateRunner.cs b/src_vs2012/NativeCore/Tools/ApiLevelUpdateRunner.cs new file mode 100644 index 00000000..50b2f68a --- /dev/null +++ b/src_vs2012/NativeCore/Tools/ApiLevelUpdateRunner.cs @@ -0,0 +1,562 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Management; +using System.Text; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to update specified target within the NDK (new API Level, new simulator or runtime). + /// + public sealed class ApiLevelUpdateRunner : BBToolRunner + { + #region Internal Classes + + /// + /// Description of the file fetched from the server. + /// + [DebuggerDisplay("{Name} ({Read} / {Size})")] + sealed class LogFetchFile + { + public LogFetchFile(string name) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + + Name = name; + } + + #region Properties + + public string Name + { + get; + private set; + } + + public long Read + { + get; + set; + } + + public long Size + { + get; + set; + } + + #endregion + } + + public enum LogState + { + Waiting, + Preparing, + Downloading, + Installing, + Configuring, + Completed + } + + public sealed class LogParser + { + public event EventHandler Log; + + private LogState _state; + private readonly ApiLevelUpdateRunner _parent; + private readonly List _files; + + public LogParser(ApiLevelUpdateRunner parent) + { + if (parent == null) + throw new ArgumentNullException("parent"); + + _state = LogState.Waiting; + _parent = parent; + _files = new List(); + } + + public void Reset() + { + State = LogState.Waiting; + _files.Clear(); + _parent.CanAbort = true; + } + + /// + /// Converts the log message from the runner into a notification with similar data. + /// + public void Consume(string line) + { + if (string.IsNullOrEmpty(line)) + return; + + if (line.StartsWith("downloading ", StringComparison.OrdinalIgnoreCase)) + { + State = LogState.Downloading; + + // ok, new file to download: + var name = line.Substring(12).Trim(); + _files.Add(new LogFetchFile(name)); + + Notify(string.Concat("Preparing ", name, "..."), 10, true); + return; + } + + if (line.StartsWith("fetching ", StringComparison.OrdinalIgnoreCase)) + { + long progress; + long size; + string originalFileName = ExtractFileName(line, out progress, out size); + var fileName = originalFileName; + + var file = Get(fileName, _files); + if (file == null) + { + fileName = Path.GetFileNameWithoutExtension(fileName); + file = Get(fileName, _files); + } + + if (file != null && size > 0) + { + file.Read = progress; + file.Size = size; + } + + // show nice log message, this is the one developer sees most often: + var overallProgress = 10 + (int)((CalculateDownloadProgress() * 70d)); // expected from 10-80% + if (file != null) + { + const double megaByte = 1024d * 1024d; + double dProgress = file.Read / megaByte; + double dSize = (file.Size / megaByte); + if (dSize < 1) // just a guard, to make it look like, there is always something to download + dSize = 1; + + Notify(string.Concat("Downloading ", originalFileName, " (", dProgress.ToString("N2"), "MB of ", dSize.ToString("N2"), "MB)..."), overallProgress, true); + } + else + { + Notify(string.Concat("Downloading ", originalFileName, "..."), overallProgress, true); + } + return; + } + + if (line.StartsWith("installing ", StringComparison.OrdinalIgnoreCase)) + { + var file = Find(line, _files); + if (file != null) + { + // mark as completed download + file.Read = file.Size; + State = LogState.Installing; + + Notify(line, 80, false); + return; + } + + Notify(line, 5, true); + return; + } + + if (line.StartsWith("configuring ", StringComparison.OrdinalIgnoreCase)) + { + State = LogState.Configuring; + Notify(line, 90, false); + return; + } + + if (line.StartsWith("preparing to commit ", StringComparison.OrdinalIgnoreCase)) + { + Notify(line, 95, false); + return; + } + + if (line.StartsWith("committing ", StringComparison.OrdinalIgnoreCase)) + { + State = LogState.Completed; + Notify(line, 100, false); + } + } + + private double CalculateDownloadProgress() + { + // go through all files and measure global progress: + long size = 0; + long read = 0; + + foreach (var file in _files) + { + read += file.Read; + size += file.Size; + } + + return size == 0 ? 0d : read / (double) size; + } + + private string ExtractFileName(string text, out long progress, out long size) + { + progress = 0; + size = 0; + + if (string.IsNullOrEmpty(text)) + return null; + + int startAt = text.IndexOf(' '); // from first space + int endAt = text.IndexOf('('); // till the bracket with progress + + if (startAt < 0 || endAt < 0) + return null; + + var name = text.Substring(startAt + 1, endAt - startAt - 1).Trim(); + + int progressEndAt = text.IndexOf(" of ", endAt, StringComparison.OrdinalIgnoreCase); + int sizeEndAt = text.IndexOf(" at ", endAt, StringComparison.OrdinalIgnoreCase); + + if (progressEndAt < 0 || sizeEndAt < 0) + return name; + + try + { + progress = GetLong(text.Substring(endAt + 1, progressEndAt - endAt - 1).Trim()); + } + catch (Exception ex) + { + TraceLog.WriteException(ex); + return name; + } + + try + { + size = GetLong(text.Substring(progressEndAt + 4, sizeEndAt - progressEndAt - 4).Trim()); + } + catch (Exception ex) + { + TraceLog.WriteException(ex); + return name; + } + + return name; + } + + private long GetLong(string text) + { + decimal multiplier = 1; + + if (string.IsNullOrEmpty(text)) + return 0; + + if (text.EndsWith("kB", StringComparison.OrdinalIgnoreCase)) + { + multiplier = 1024; + text = text.Substring(0, text.Length - 2); + } + else if (text.EndsWith("MB", StringComparison.OrdinalIgnoreCase)) + { + multiplier = 1024 * 1024; + text = text.Substring(0, text.Length - 2); + } + else + { + if (text.EndsWith("GB", StringComparison.OrdinalIgnoreCase)) + { + multiplier = 1024 * 1024 * 1024; + text = text.Substring(0, text.Length - 2); + } + else + { + text = text.Substring(0, text.Length - 1); + } + } + + // clean-up from some strange local chars: + for (int i = 0; i < text.Length; i++) + { + if (!char.IsDigit(text[i]) && text[i] != '.' && text[i] != ',') + { + text = text.Remove(i, 1); + i--; + } + } + + // and convert the number finally: + decimal value; + if (decimal.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out value)) + return (long) (value * multiplier); + + if (decimal.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out value)) + return (long) (value * multiplier); + + return 0; + } + + private static LogFetchFile Find(string text, ICollection files) + { + if (string.IsNullOrEmpty(text) || files == null || files.Count == 0) + return null; + + foreach (var file in files) + { + if (text.IndexOf(file.Name, StringComparison.CurrentCulture) >= 0) + return file; + } + + return null; + } + + private static LogFetchFile Get(string text, ICollection files) + { + if (string.IsNullOrEmpty(text) || files == null || files.Count == 0) + return null; + + foreach (var file in files) + { + if (string.Compare(text, file.Name, StringComparison.CurrentCulture) == 0) + return file; + } + + return null; + } + + private void Notify(string message, int progress, bool canAbort) + { + _parent.CanAbort = canAbort; + + var handler = Log; + if (handler != null) + handler(_parent, new ApiLevelUpdateLogEventArgs(message, progress, canAbort)); + } + + #region Properties + + public LogState State + { + get { return _state; } + private set + { + if (_state != value) + { + _state = value; + TraceLog.WriteLine("New state: {0}", State); + } + } + } + + #endregion + } + + #endregion + + /// + /// Event fired each time progress of an update has been changed. + /// + public event EventHandler Log + { + add { _parser.Log += value; } + remove { _parser.Log -= value; } + } + + private readonly List _runningInstallers; + private readonly LogParser _parser; + + private ApiLevelAction _action; + private ApiLevelTarget _target; + private Version _version; + + /// + /// Init constructor. + /// + public ApiLevelUpdateRunner(string workingDirectory, ApiLevelAction action, ApiLevelTarget target, Version version) + : base(workingDirectory) + { + if (version == null) + throw new ArgumentNullException("version"); + + _action = action; + _target = target; + _version = version; + _runningInstallers = new List(); + _parser = new LogParser(this); + CanAbort = true; + + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the action to be performed. + /// + public ApiLevelAction Action + { + get { return _action; } + set + { + _action = value; + UpdateArguments(); + } + } + + /// + /// Gets or sets the target the action is performed over. + /// + public ApiLevelTarget Target + { + get { return _target; } + set + { + _target = value; + UpdateArguments(); + } + } + + /// + /// Gets or sets the version of the target operation is performed over. + /// + public Version Version + { + get { return _version; } + set + { + if (value != null) + { + _version = value; + UpdateArguments(); + } + } + } + + /// + /// Gets an indication, if this task entered a moment, when can not be aborted. + /// + public bool CanAbort + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + var args = new StringBuilder("/C eclipsec.exe"); + + switch (Action) + { + case ApiLevelAction.Install: + args.Append(" --install"); + break; + case ApiLevelAction.Uninstall: + args.Append(" --uninstall"); + break; + default: + throw new InvalidOperationException("Specified action is unsupported (" + Action + ")"); + } + args.Append(' ').Append(Version); + + switch (Target) + { + case ApiLevelTarget.NDK: + // do nothing + break; + case ApiLevelTarget.Simulator: + args.Append(" --simulator"); + break; + case ApiLevelTarget.Runtime: + args.Append(" --runtime"); + break; + default: + throw new InvalidOperationException("Specified target is unsupported (" + Target + ")"); + } + + Arguments = args.ToString(); + } + + protected override void PrepareStartup() + { + base.PrepareStartup(); + _runningInstallers.Clear(); + _parser.Reset(); + } + + protected override void PrepareStarted(int pid) + { + var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Process WHERE ParentProcessId=" + pid); + foreach (var item in searcher.Get()) + { + try + { + _runningInstallers.Add(Convert.ToInt32(item["ProcessId"].ToString())); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to acquire installation process-id"); + } + } + } + + protected override void ProcessOutputLine(string text) + { + _parser.Consume(text); + } + + protected override void ConsumeResults(string output, string error) + { + _runningInstallers.Clear(); + } + + /// + /// Waits for update to complete. + /// + public void Wait() + { + foreach (int pid in _runningInstallers) + { + using (var process = Process.GetProcessById(pid)) + { + process.WaitForExit(); + } + } + } + + /// + /// Aborts running update. + /// + public override bool Abort() + { + if (!CanAbort) + return false; + + foreach (int pid in _runningInstallers) + { + try + { + using (var process = Process.GetProcessById(pid)) + { + process.Kill(); + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to abort update ({0}, {1}, {2})", Action, Target, Version); + } + } + + _runningInstallers.Clear(); + return true; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + Abort(); // kill all spawned processes if available... + } + } +} diff --git a/src_vs2012/NativeCore/Tools/ApplicationRemoveRunner.cs b/src_vs2012/NativeCore/Tools/ApplicationRemoveRunner.cs new file mode 100644 index 00000000..a4143a66 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/ApplicationRemoveRunner.cs @@ -0,0 +1,132 @@ +using System; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to remove installed application from the device. + /// + public sealed class ApplicationRemoveRunner : BBToolRunner + { + private string _packageID; + private string _ip; + private string _password; + + /// + /// Init constructor. + /// + /// Identifier of the application .bar file + /// Device IP + /// Device password + public ApplicationRemoveRunner(string packageID, string ip, string password) + { + if (string.IsNullOrEmpty(packageID)) + throw new ArgumentNullException("packageID"); + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + + _packageID = packageID; + _ip = ip; + _password = password; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the package identifier of the application .bar file. + /// + public string PackageID + { + get { return _packageID; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _packageID = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the IP of the device. + /// + public string IP + { + get { return _ip; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _ip = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the device access password. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets and indication, if application was removed from the device. + /// + public bool RemovedSuccessfully + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + Arguments = string.Format(@"/C blackberry-deploy.bat -uninstallApp -device ""{0}"" -password ""{1}"" -package-id ""{2}""", IP, Password, _packageID); + } + + protected override void ConsumeResults(string output, string error) + { + RemovedSuccessfully = false; + + if (string.IsNullOrEmpty(error) && !string.IsNullOrEmpty(output)) + { + var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + + // check, if there is any runtime error message: + foreach (var line in lines) + { + if (line.StartsWith("error:", StringComparison.InvariantCultureIgnoreCase)) + { + LastError = line.Substring(6).Trim(); + break; + } + if (string.Compare("result::success", line, StringComparison.InvariantCultureIgnoreCase) == 0) + { + RemovedSuccessfully = true; + break; + } + if (line.StartsWith("result::failure", StringComparison.InvariantCultureIgnoreCase)) + { + RemovedSuccessfully = false; + LastError = line.Substring(15).Trim(); + break; + } + } + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/BBToolRunner.cs b/src_vs2012/NativeCore/Tools/BBToolRunner.cs new file mode 100644 index 00000000..0b6ae3f7 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/BBToolRunner.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Specific base-class for + /// + public class BBToolRunner : ToolRunner + { + /// + /// Default constructor. It sets 'ToolsDirectory' as the default working directory. + /// + protected BBToolRunner() + : base("cmd.exe", ConfigDefaults.ToolsDirectory) + { + } + + /// + /// Init constructor. + /// + /// Tools directory + protected BBToolRunner(string workingDirectory) + : base("cmd.exe", workingDirectory) + { + } + + protected override void PrepareStartup() + { + base.PrepareStartup(); + + // make sure proper Java installation for BB NDK plugin is used: + if (!string.IsNullOrEmpty(Environment["PATH"]) && !string.IsNullOrEmpty(ConfigDefaults.JavaHome) + && !Environment["PATH"].StartsWith(Path.Combine(ConfigDefaults.JavaHome, "bin"), StringComparison.OrdinalIgnoreCase)) + { + Environment["PATH"] = string.Concat(Path.Combine(ConfigDefaults.JavaHome, "bin"), ";", Environment["PATH"]); + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/DebugTokenCreateRunner.cs b/src_vs2012/NativeCore/Tools/DebugTokenCreateRunner.cs new file mode 100644 index 00000000..d4684317 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/DebugTokenCreateRunner.cs @@ -0,0 +1,164 @@ +using System; +using System.Text; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to create debug-token .bar file on disk. + /// If a file exists at specified file location, it will be overwritten. + /// + public sealed class DebugTokenCreateRunner : BBToolRunner + { + private string _location; + private string _password; + private ulong[] _devices; + private string _storeFileName; + + /// + /// Init constructor. + /// + /// File name and directory of the debug-token bar file + /// Password to the local certificate, specified when registering with the BlackBerry Signing Authority + /// List of device PINs + /// Name of the certificate, where to developer data is stored; if null, 'author.p12' is used + public DebugTokenCreateRunner(string debugTokenLocation, string password, ulong[] devices, string storeFileName) + { + if (string.IsNullOrEmpty(debugTokenLocation)) + throw new ArgumentNullException("debugTokenLocation"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (devices == null || devices.Length == 0) + throw new ArgumentNullException("devices"); + + _location = debugTokenLocation; + _password = password; + _devices = devices; + _storeFileName = storeFileName; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the full name with location of the debugtoken.bar file. + /// It the file exists, if will be overwritten. + /// + public string DebugTokenLocation + { + get { return _location; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _location = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the list of devices (PINs) the debug token is valid for. + /// + public ulong[] Devices + { + get { return _devices; } + set + { + if (value != null && value.Length > 0) + { + _devices = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the access password to the local keystore. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the name of the certificate file, where developer (publisher) data is stored. + /// + public string StoreFileName + { + get { return _storeFileName; } + set + { + _storeFileName = value; + UpdateArguments(); + } + } + + /// + /// Gets and indication, if the debug-token was created successfully. + /// + public bool CreatedSuccessfully + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + var args = new StringBuilder("/C blackberry-debugtokenrequest.bat "); + + // password: + args.Append("-storepass \"").Append(Password).Append("\" "); + + // keystore: + if (!string.IsNullOrEmpty(StoreFileName)) + args.Append("-keystore \"").Append(System.Environment.ExpandEnvironmentVariables(StoreFileName)).Append("\" "); + + + // list of devices: + foreach (var device in Devices) + { + args.Append("-devicepin \"").Append(device.ToString("X")).Append("\" "); + } + + // path to the output .bar file: + args.Append('"').Append(System.Environment.ExpandEnvironmentVariables(DebugTokenLocation)).Append('"'); + + Arguments = args.ToString(); + } + + protected override void ConsumeResults(string output, string error) + { + CreatedSuccessfully = false; + + if (string.IsNullOrEmpty(error) && !string.IsNullOrEmpty(output)) + { + var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + + // check, if there is any runtime error message: + foreach (var line in lines) + { + if (line.StartsWith("error:", StringComparison.InvariantCultureIgnoreCase)) + { + LastError = line.Substring(6).Trim(); + break; + } + if (string.Compare("Info: Debug token created.", line, StringComparison.InvariantCultureIgnoreCase) == 0) + { + CreatedSuccessfully = true; + break; + } + } + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/DebugTokenInfoRunner.cs b/src_vs2012/NativeCore/Tools/DebugTokenInfoRunner.cs new file mode 100644 index 00000000..4aa3a7f3 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/DebugTokenInfoRunner.cs @@ -0,0 +1,59 @@ +using System; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to get debug-token information. + /// + public sealed class DebugTokenInfoRunner : BBToolRunner + { + private string _location; + + /// + /// Init constructor. + /// + /// File name and directory of the debug-token bar file + public DebugTokenInfoRunner(string debugTokenLocation) + { + if (string.IsNullOrEmpty(debugTokenLocation)) + throw new ArgumentNullException("debugTokenLocation"); + + DebugTokenLocation = debugTokenLocation; + } + + #region Properties + + /// + /// Gets the info about debug-token. + /// + public DebugTokenInfo DebugToken + { + get; + private set; + } + + /// + /// Gets or sets the full name with location of the debugtoken.bar file. + /// + public string DebugTokenLocation + { + get { return _location; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _location = value; + Arguments = string.Format(@"/C blackberry-airpackager.bat -listManifest ""{0}""", System.Environment.ExpandEnvironmentVariables(value)); + } + } + } + + #endregion + + protected override void ConsumeResults(string output, string error) + { + DebugToken = string.IsNullOrEmpty(error) ? DebugTokenInfo.Parse(output) : null; + } + } +} diff --git a/src_vs2012/NativeCore/Tools/DebugTokenUploadRunner.cs b/src_vs2012/NativeCore/Tools/DebugTokenUploadRunner.cs new file mode 100644 index 00000000..ea809d76 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/DebugTokenUploadRunner.cs @@ -0,0 +1,127 @@ +using System; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to upload debug-token onto the device. + /// + public sealed class DebugTokenUploadRunner : BBToolRunner + { + private string _location; + private string _ip; + private string _password; + + /// + /// Init constructor. + /// + /// File name and directory of the debug-token bar file + /// Device IP + /// Device password + public DebugTokenUploadRunner(string debugTokenLocation, string ip, string password) + { + if (string.IsNullOrEmpty(debugTokenLocation)) + throw new ArgumentNullException("debugTokenLocation"); + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + + _location = debugTokenLocation; + _ip = ip; + _password = password; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the full name with location of the debugtoken.bar file. + /// + public string DebugTokenLocation + { + get { return _location; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _location = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the IP of the device. + /// + public string IP + { + get { return _ip; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _ip = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the device access password. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets and indication, if debug-token was uploaded on the device. + /// + public bool UploadedSuccessfully + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + Arguments = string.Format(@"/C blackberry-deploy.bat -installDebugToken ""{0}"" -device ""{1}"" -password ""{2}""", + System.Environment.ExpandEnvironmentVariables(DebugTokenLocation), IP, Password); + } + + protected override void ConsumeResults(string output, string error) + { + UploadedSuccessfully = false; + + if (string.IsNullOrEmpty(error) && !string.IsNullOrEmpty(output)) + { + var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + + // check, if there is any runtime error message: + foreach (var line in lines) + { + if (line.StartsWith("error:", StringComparison.InvariantCultureIgnoreCase)) + { + LastError = line.Substring(6).Trim();; + break; + } + if (string.Compare("result::success", line, StringComparison.InvariantCultureIgnoreCase) == 0) + { + UploadedSuccessfully = true; + break; + } + } + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/DeviceConnectRunner.cs b/src_vs2012/NativeCore/Tools/DeviceConnectRunner.cs new file mode 100644 index 00000000..1936d249 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/DeviceConnectRunner.cs @@ -0,0 +1,159 @@ +using System; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to establish secured connection to specified device. + /// + public sealed class DeviceConnectRunner : BBToolRunner + { + private string _ip; + private string _password; + private string _publicKeyPath; + + public event EventHandler StatusChanged; + + /// + /// Init constructor. + /// + /// Device IP + /// Device password + /// Path to SSH public key to be used, to establish connection to the device + public DeviceConnectRunner(string ip, string password, string publicKeyPath) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (string.IsNullOrEmpty(publicKeyPath)) + throw new ArgumentNullException("publicKeyPath"); + + _ip = ip; + _password = password; + _publicKeyPath = publicKeyPath; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the IP of the device. + /// + public string IP + { + get { return _ip; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _ip = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the device access password. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the path to the SSH public key file. + /// + public string PublicKeyPath + { + get { return _publicKeyPath; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _publicKeyPath = value; + UpdateArguments(); + } + } + } + + public bool ShowConsole + { + get { return ShowWindow; } + set { ShowWindow = value; } + } + + public bool IsConnected + { + get; + private set; + } + + public bool IsConnectionFailed + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + Arguments = string.Concat("/C blackberry-connect.bat \"", IP, "\" -password \"", Password, "\" -sshPublicKey \"", PublicKeyPath, "\""); + } + + protected override void PrepareStartup() + { + base.PrepareStartup(); + IsConnected = ShowWindow; + IsConnectionFailed = false; + } + + protected override void ProcessOutputLine(string text) + { + bool wasConnected = IsConnected; + base.ProcessOutputLine(text); + + IsConnected |= text != null && text.StartsWith("Info: Successfully connected."); + if (!wasConnected && IsConnected) + { + NotifyStatusChange(); + } + } + + protected override void ProcessErrorLine(string text) + { + base.ProcessErrorLine(text); + IsConnectionFailed = true; + LastError = ExtractErrorMessages(text); + NotifyStatusChange(); + } + + protected override void Cleanup() + { + bool wasConnectedOrFailed = IsConnected || IsConnectionFailed; + + IsConnected = false; + IsConnectionFailed = false; + + if (wasConnectedOrFailed) + { + NotifyStatusChange(); + } + } + + private void NotifyStatusChange() + { + var eventHandler = StatusChanged; + if (eventHandler != null) + eventHandler(this, EventArgs.Empty); + } + } +} diff --git a/src_vs2012/NativeCore/Tools/DeviceInfoRunner.cs b/src_vs2012/NativeCore/Tools/DeviceInfoRunner.cs new file mode 100644 index 00000000..82daf225 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/DeviceInfoRunner.cs @@ -0,0 +1,100 @@ +using System; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to get information about specified device. + /// + public sealed class DeviceInfoRunner : BBToolRunner + { + private string _ip; + private string _password; + + /// + /// Init constructor. + /// + /// Device IP + /// Device password + public DeviceInfoRunner(string ip, string password) + { + if (string.IsNullOrEmpty(ip)) + throw new ArgumentNullException("ip"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + + _ip = ip; + _password = password; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the IP of the device. + /// + public string IP + { + get { return _ip; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _ip = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the device access password. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets the info about the device. + /// + public DeviceInfo DeviceInfo + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + Arguments = string.Concat("/C blackberry-deploy.bat -listDeviceInfo \"", IP, "\" -password \"", Password, "\""); + } + + protected override void ConsumeResults(string output, string error) + { + if (string.IsNullOrEmpty(error)) + { + string runtimeError; + DeviceInfo = DeviceInfo.Parse(output, out runtimeError); + + // if during parsing found any runtime error, overwrite current state: + if (!string.IsNullOrEmpty(runtimeError)) + { + LastError = runtimeError; + } + } + else + { + DeviceInfo = null; + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/EventDispatcher.cs b/src_vs2012/NativeCore/Tools/EventDispatcher.cs new file mode 100644 index 00000000..2c3578de --- /dev/null +++ b/src_vs2012/NativeCore/Tools/EventDispatcher.cs @@ -0,0 +1,411 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Windows; +using System.Windows.Forms; +using System.Windows.Threading; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Helper class for creating cross-thread event dispatchers. + /// + public static class EventDispatcher + { + #region Windows Forms + + class WindowsFormsEventDispatcher : IEventDispatcher + { + private readonly Control _control; + + public WindowsFormsEventDispatcher(Control control) + { + if (control == null) + throw new ArgumentNullException("control"); + _control = control; + } + + #region IEventDispatcher Implementation + + public bool IsSynchronous + { + get { return true; } + } + + public void Invoke(EventHandler eventHandler, object sender, T e) where T : EventArgs + { + if (eventHandler != null) + { + if (_control.InvokeRequired) + { + _control.Invoke(eventHandler, sender, e); + } + else + { + eventHandler(sender, e); + } + } + } + + public void Invoke(Action action) + { + if (action != null) + { + if (_control.InvokeRequired) + { + _control.Invoke(action); + } + else + { + action(); + } + } + } + + public void Invoke(Action action, T e) + { + if (action != null) + { + if (_control.InvokeRequired) + { + _control.Invoke(action, e); + } + else + { + action(e); + } + } + } + + #endregion + } + + #endregion + + #region Classic + + /// + /// Class for calling all events synchronously in the same thread. + /// + class ClassicEventDispatcher : IEventDispatcher + { + #region IEventDispatcher Implementation + + public bool IsSynchronous + { + get { return true; } + } + + public void Invoke(EventHandler eventHandler, object sender, T e) where T : EventArgs + { + if (eventHandler != null) + { + eventHandler(sender, e); + } + } + + public void Invoke(Action action) + { + if (action != null) + { + action(); + } + } + + public void Invoke(Action action, T e) + { + if (action != null) + { + action(e); + } + } + + #endregion + } + + class ClassicAsyncEventDispatcher : IEventDispatcher + { + #region Private Classes + + abstract class AsyncTask + { + public abstract void Execute(); + } + + class EventHandlerTask : AsyncTask where T : EventArgs + { + private readonly EventHandler _eventHandler; + private readonly object _sender; + private readonly T _e; + + public EventHandlerTask(EventHandler eventHandler, object sender, T e) + { + if (eventHandler == null) + throw new ArgumentNullException("eventHandler"); + + _eventHandler = eventHandler; + _sender = sender; + _e = e; + } + + public override void Execute() + { + _eventHandler(_sender, _e); + } + } + + class ActionTask : AsyncTask + { + private readonly Action _action; + + public ActionTask(Action action) + { + if (action == null) + throw new ArgumentNullException("action"); + + _action = action; + } + + public override void Execute() + { + _action(); + } + } + + class ActionTask : AsyncTask + { + private readonly Action _action; + private readonly T _e; + + public ActionTask(Action action, T e) + { + if (action == null) + throw new ArgumentNullException("action"); + + _action = action; + _e = e; + } + + public override void Execute() + { + _action(_e); + } + } + + #endregion + + private readonly AutoResetEvent _dataAvailableEvent; + private readonly Queue _tasks; + private readonly Thread _worker; + + public ClassicAsyncEventDispatcher(string name) + { + _dataAvailableEvent = new AutoResetEvent(false); + _tasks = new Queue(); + + _worker = new Thread(DispatchEvents); + _worker.Name = name; + _worker.IsBackground = true; // won't block closing of the process + _worker.Start(); + } + + private void DispatchEvents() + { + AsyncTask task = null; + + while (true) + { + // get pending task: + lock (_tasks) + { + if (_tasks.Count > 0) + { + task = _tasks.Dequeue(); + } + } + + if (task == null) + { + // wait for next task: + _dataAvailableEvent.WaitOne(Timeout.Infinite); + } + else + { + task.Execute(); + task = null; + } + } + } + + public bool IsSynchronous + { + get { return false; } + } + + public void Invoke(EventHandler eventHandler, object sender, T e) where T : EventArgs + { + if (eventHandler != null) + { + Add(new EventHandlerTask(eventHandler, sender, e)); + } + } + + public void Invoke(Action action) + { + if (action != null) + { + Add(new ActionTask(action)); + } + } + + public void Invoke(Action action, T e) + { + if (action != null) + { + Add(new ActionTask(action, e)); + } + } + + private void Add(AsyncTask task) + { + if (task == null) + throw new ArgumentNullException("task"); + + lock (_tasks) + { + _tasks.Enqueue(task); + } + + // and wake-up the executing thread: + _dataAvailableEvent.Set(); + } + } + + #endregion + + #region Dependency Object (WPF/Silverlight) + + class DependencyObjectEventDispatcher : IEventDispatcher + { + private readonly Dispatcher _dispatcher; + + public DependencyObjectEventDispatcher() + { + // PH: could use System.Windows.Deployment.Current.Dispatcher instead + // but that would require reference to System.Windows.dll... + _dispatcher = Dispatcher.CurrentDispatcher; + if (_dispatcher == null) + throw new InvalidOperationException("Could not create dispatcher object associated with current thread"); + } + + public DependencyObjectEventDispatcher(DependencyObject control) + { + if (control == null) + throw new ArgumentNullException("control"); + _dispatcher = control.Dispatcher; + } + + #region IEventDispatcher Implementation + + public bool IsSynchronous + { + get { return false; } + } + + public void Invoke(EventHandler eventHandler, object sender, T e) where T : EventArgs + { + if (eventHandler != null) + { + if (_dispatcher.CheckAccess()) + { + eventHandler(sender, e); + } + else + { + _dispatcher.BeginInvoke(eventHandler, sender, e); + } + } + } + + public void Invoke(Action action) + { + if (action != null) + { + if (_dispatcher.CheckAccess()) + { + action(); + } + else + { + _dispatcher.BeginInvoke(action); + } + } + } + + public void Invoke(Action action, T e) + { + if (action != null) + { + if (_dispatcher.CheckAccess()) + { + action(e); + } + else + { + _dispatcher.BeginInvoke(action, e); + } + } + } + + #endregion + } + + #endregion + + /// + /// Creates an event dispatcher for invoking events in the same thread. + /// + public static IEventDispatcher New() + { + return new ClassicEventDispatcher(); + } + + /// + /// Creates an event dispatcher for invoking events withing .NET default threadpool. + /// + public static IEventDispatcher NewAsync(string name) + { + return new ClassicAsyncEventDispatcher(name); + } + + /// + /// Creates an event dispatcher for WPF/Silverlight UI thread. + /// + public static IEventDispatcher NewForWPF() + { + return new DependencyObjectEventDispatcher(); + } + + /// + /// Creates an event dispatcher for Windows Forms UI thread. + /// + public static IEventDispatcher From(Control control) + { + if (control == null) + throw new ArgumentNullException("control"); + + return new WindowsFormsEventDispatcher(control); + } + + /// + /// Creates an event dispatcher for WPF/Silverlight UI thread. + /// + public static IEventDispatcher From(DependencyObject control) + { + if (control == null) + throw new ArgumentNullException("control"); + + return new DependencyObjectEventDispatcher(control); + } + } +} diff --git a/src_vs2012/NativeCore/Tools/GdbHostRunner.cs b/src_vs2012/NativeCore/Tools/GdbHostRunner.cs new file mode 100644 index 00000000..c07ee58c --- /dev/null +++ b/src_vs2012/NativeCore/Tools/GdbHostRunner.cs @@ -0,0 +1,123 @@ +using System; +using System.Diagnostics; +using System.Threading; +using BlackBerry.NativeCore.Debugger; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that starts up the GDB via GDBHostprocess and helps in passing commands in both directions. + /// + public sealed class GdbHostRunner : GdbRunner + { + private EventWaitHandle _eventCtrlC; + private EventWaitHandle _eventTerminate; + + private static int HostID = 1; + + /// + /// Init constructor. + /// + /// Path to the BlackBerry.GDBHost.exe tool. + /// Description of the GDB to communicate with. + public GdbHostRunner(string gdbHostFileName, GdbInfo gdb) + : base(gdbHostFileName, gdb) + { + int currentPID = Process.GetCurrentProcess().Id; + int currentHostID = Interlocked.Increment(ref HostID); + string eventCtrlCName = string.Concat("HostCtrlC-", currentHostID, "-", currentPID); + string eventTerminateName = string.Concat("HostTerminate-", currentHostID, "-", currentPID); + + _eventCtrlC = new EventWaitHandle(false, EventResetMode.AutoReset, eventCtrlCName); + _eventTerminate = new EventWaitHandle(false, EventResetMode.AutoReset, eventTerminateName); + + // GDB-Host process required a specific order of arguments: + // 1. the name of the event, which set will trigger the Ctrl+C signal to the GDB + // 2. the name of the event, which set will exit the host process and GDB + // 3. the path to GDB executable itself, that will run + // 4. optional settings for GDBHost (-s => disable custom console logs, -c => skip checking for GDB-executable existence) + // 5. all the other arguments that should be passed to GDB (although it's possible to pass arguments to GDB via the executable path, + // but in practice they can't be escaped this way; that's why passing them as last arguments of the host are the recommended approach) + Arguments = string.Concat(eventCtrlCName, " ", eventTerminateName, " -sc ", "\"", gdb.Executable, "\" ", gdb.Arguments); + } + + /// + /// Sends Ctrl+C to the GDB process. + /// + public override void Break() + { + if (_eventCtrlC == null) + throw new ObjectDisposedException("GdbHostRunner"); + + _eventCtrlC.Set(); + } + + /// + /// Requests host process to terminate gracefully. + /// + public void Terminate() + { + if (_eventTerminate == null) + throw new ObjectDisposedException("GdbHostRunner"); + + _eventTerminate.Set(); + } + + /// + /// Aborts the process and all its child processes. + /// + public override bool Abort() + { + if (Processor != null) + { + try + { + var request = RequestsFactory.Exit(); + if (Processor.Send(request)) + { + // synchronously wait for the completion: + request.Wait(); + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to send input data"); + } + } + + if (_eventTerminate != null) + { + Terminate(); + return true; + } + + return false; + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_eventCtrlC != null) + { + _eventCtrlC.Dispose(); + _eventCtrlC = null; + } + + if (_eventTerminate != null) + { + Terminate(); + _eventTerminate.Dispose(); + _eventTerminate = null; + } + } + base.Dispose(disposing); + } + + #region Message Processing + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Tools/GdbRunner.cs b/src_vs2012/NativeCore/Tools/GdbRunner.cs new file mode 100644 index 00000000..9a831b51 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/GdbRunner.cs @@ -0,0 +1,218 @@ +using System; +using BlackBerry.NativeCore.Debugger; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that starts up the GDB and helps in passing commands in both directions. + /// + public class GdbRunner : ToolRunner, IGdbSender + { + private GdbProcessor _processor; + + /// + /// Init constructor. + /// + /// Description of the GDB to communicate with. + public GdbRunner(GdbInfo gdb) + : base(gdb != null ? gdb.Executable : null, null) + { + if (gdb == null) + throw new ArgumentNullException("gdb"); + + GDB = gdb; + _processor = new GdbProcessor(this); + Arguments = gdb.Arguments; + } + + /// + /// Init constructor. + /// + /// Path to the executable, invoked, when starting this tool. + /// Description of the GDB to communicate with. + protected GdbRunner(string fileName, GdbInfo gdb) + : base(fileName, null) + { + if (string.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + if (gdb == null) + throw new ArgumentNullException("gdb"); + + GDB = gdb; + _processor = new GdbProcessor(this); + Arguments = gdb.Arguments; + } + + #region Properties + + /// + /// Gets the startup info about the GDB itself. + /// + public GdbInfo GDB + { + get; + private set; + } + + /// + /// Gets the target device the GDB is supposed to connect. + /// + public DeviceDefinition Device + { + get { return GDB.Device; } + } + + /// + /// Gets the runtime state and events from the GDB. + /// + public GdbProcessor Processor + { + get { return _processor; } + } + + /// + /// Gets or sets showing of the GDB console. + /// Please note, that when console is shown, output is not consumed as it is not delivered to Processor. + /// + public bool ShowConsole + { + get { return ShowWindow; } + set { ShowWindow = value; } + } + + #endregion + + #region IGdbSender Implementation + + void IGdbSender.Break() + { + Break(); + } + + bool IGdbSender.Send(string command) + { +#if DEBUG + System.Diagnostics.Trace.WriteLine("INPUT : " + command, TraceLog.CategoryGDB); +#endif + + return SendInput(command); + } + + #endregion + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_processor != null) + { + _processor.Dispose(); + _processor = null; + } + } + base.Dispose(disposing); + } + + #region Command Processing + + /// + /// Sends Ctrl+C to the GDB process. + /// + public virtual void Break() + { + throw new NotSupportedException("Breaking is not supported by GDB in this type of call"); + } + + protected override void ProcessOutputLine(string text) + { +#if DEBUG + System.Diagnostics.Trace.WriteLine("OUTPUT: " + text, TraceLog.CategoryGDB); +#endif + + if (_processor != null) + { + _processor.Receive(text); + } + } + + #endregion + + #region Forwarded Communication + + /// + /// Reads next response from the buffer. + /// If there is nothing received until last call, null value is returned. + /// + public Response Read() + { + if (_processor == null) + throw new ObjectDisposedException("GdbRunner"); + + return _processor.Read(); + } + + /// + /// This method sends a desired request to the GDB. + /// + public bool Send(Request request) + { + if (request == null) + throw new ArgumentNullException("request"); + if (_processor == null) + throw new ObjectDisposedException("GdbRunner"); + + return _processor.Send(request); + } + + /// + /// This method sends a request to the GDB, waits for a response and parses it following specified parsing instruction. + /// Returns parsed response or empty string in case of error. + /// + public string Send(Request request, Instruction instruction) + { + if (request == null) + throw new ArgumentNullException("request"); + if (instruction == null) + throw new ArgumentNullException("instruction"); + if (_processor == null) + throw new ObjectDisposedException("GdbRunner"); + + + _processor.Send(request); + if (!request.Wait()) + { + return string.Empty; + } + + return instruction.Parse(request.Response); + } + + /// + /// Waits until a valid message was not received. + /// + /// Returns 'true', if the signal was received and data is valid, 'false' in case of timeout. + public bool Wait(out Response response) + { + if (_processor == null) + throw new ObjectDisposedException("GdbRunner"); + + return _processor.Wait(out response); + } + + /// + /// Waits until a valid message was not received. + /// + /// Returns 'true', if the signal was received and data is valid, 'false' in case of timeout. + public bool Wait(int millisecondsTimeout, out Response response) + { + if (_processor == null) + throw new ObjectDisposedException("GdbRunner"); + + return _processor.Wait(millisecondsTimeout, out response); + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Tools/IEventDispatcher.cs b/src_vs2012/NativeCore/Tools/IEventDispatcher.cs new file mode 100644 index 00000000..037e2a40 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/IEventDispatcher.cs @@ -0,0 +1,19 @@ +using System; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Interface simplifying events invocations. + /// + public interface IEventDispatcher + { + bool IsSynchronous + { + get; + } + + void Invoke(EventHandler eventHandler, object sender, T e) where T : EventArgs; + void Invoke(Action action); + void Invoke(Action action, T e); + } +} \ No newline at end of file diff --git a/src_vs2012/NativeCore/Tools/KeyToolGenRunner.cs b/src_vs2012/NativeCore/Tools/KeyToolGenRunner.cs new file mode 100644 index 00000000..048ec27f --- /dev/null +++ b/src_vs2012/NativeCore/Tools/KeyToolGenRunner.cs @@ -0,0 +1,123 @@ +using System; +using System.IO; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to create a pair of signing keys for developer of specified name. + /// + public sealed class KeyToolGenRunner : BBToolRunner + { + private string _name; + private string _password; + private string _storeFileName; + + /// + /// Init constructor. + /// + /// Name of the developer + /// Password protection, required later to use the keys + /// Name of the certificate, where to store specified data; if null, 'author.p12' is used + public KeyToolGenRunner(string name, string password, string storeFileName) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + + _name = name; + _password = password; + _storeFileName = storeFileName; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the name of the developer used to generate keys. + /// + public string Name + { + get { return _name; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _name = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or set access password, when using generated keys. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the name of the certificate file, where to store the data. + /// + public string StoreFileName + { + get { return _storeFileName; } + set + { + _storeFileName = value; + UpdateArguments(); + } + } + + /// + /// Gets the name of the certificate file created (if needed) with info about the developer (publisher). + /// + public string CertificateFileName + { + get + { + string fileName = null; + + if (!string.IsNullOrEmpty(_storeFileName)) + { + fileName = Path.GetFileName(_storeFileName); + } + + return string.IsNullOrEmpty(fileName) ? DeveloperDefinition.DefaultCertificateName : fileName; + } + } + + #endregion + + private void UpdateArguments() + { + if (string.IsNullOrEmpty(StoreFileName)) + { + Arguments = string.Format(@"/C blackberry-keytool -genkeypair -author ""{0}"" -storepass ""{1}""", Name, Password); + } + else + { + Arguments = string.Format(@"/C blackberry-keytool -genkeypair -author ""{0}"" -storepass ""{1}"" -keystore ""{2}""", + Name, Password, System.Environment.ExpandEnvironmentVariables(StoreFileName)); + } + } + + protected override void ConsumeResults(string output, string error) + { + if (string.IsNullOrEmpty(error) && !string.IsNullOrEmpty(output)) + { + LastError = ExtractErrorMessages(output); + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/KeyToolInfoRunner.cs b/src_vs2012/NativeCore/Tools/KeyToolInfoRunner.cs new file mode 100644 index 00000000..b4ec6835 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/KeyToolInfoRunner.cs @@ -0,0 +1,117 @@ +using System; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to load info about developer's signing keys. + /// + public sealed class KeyToolInfoRunner : BBToolRunner + { + private string _password; + private string _storeFileName; + + /// + /// Init constructor. + /// + /// Name of the certificate file + /// Required password to decrypt info inside the certificate file + public KeyToolInfoRunner(string storeFileName, string password) + { + if (string.IsNullOrEmpty(storeFileName)) + throw new ArgumentNullException("storeFileName"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + + _storeFileName = storeFileName; + _password = password; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or set access password, used when generating certificate. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the name of the certificate file, where to load info from. + /// + public string StoreFileName + { + get { return _storeFileName; } + set + { + _storeFileName = value; + UpdateArguments(); + } + } + + /// + /// Gets the certificate info returned by the keytool. + /// + public CertificateInfo Info + { + get; + private set; + } + + #endregion + + private void UpdateArguments() + { + Arguments = string.Format(@"/C blackberry-keytool -list -keystore ""{0}"" -storepass ""{1}"" -verbose", System.Environment.ExpandEnvironmentVariables(StoreFileName), Password); + } + + protected override void ConsumeResults(string output, string error) + { + /* +Found 1 private key +Found 1 certificate: + Alias: + author + Serial Number: + aa:bb:cc:dd + Subject Name: + CommonName=XyXyXyXyXyXy + Issuer Name: + CommonName=XyXyXyXyXyXy + Valid From: + Thu Oct 18 22:25:41 CEST 2012 + Valid To: + Wed Oct 13 22:25:41 CEST 2032 + Public Key: + ECC-SECP521R1 + Signature Algorithm: + SHA512withECDSA + SHA1 Fingerprint: + aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:00:11:22:33:44:55:66:77 + MD5 Fingerprint: + 00:11:22:33:44:55:66:77:88:99:00:11:22:33:44:55 + */ + + Info = null; + if (string.IsNullOrEmpty(error) && !string.IsNullOrEmpty(output)) + { + Info = CertificateInfo.Parse(output); + } + + TraceLog.WriteLine("For certificate: {0}", StoreFileName); + TraceLog.WriteLine(" * issuer: {0}", Info != null ? Info.Issuer : "- none -"); + TraceLog.WriteLine(" * algorithm: {0}", Info != null ? Info.Algorithm : "- none -"); + } + } +} diff --git a/src_vs2012/NativeCore/Tools/KeyToolRegisterRunner.cs b/src_vs2012/NativeCore/Tools/KeyToolRegisterRunner.cs new file mode 100644 index 00000000..42088f99 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/KeyToolRegisterRunner.cs @@ -0,0 +1,127 @@ +using System; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to register Signing Authority based on CSJ files. + /// + public sealed class KeyToolRegisterRunner : BBToolRunner + { + private string _pin; + private string _password; + private string _rdkFileName; + private string _pbdtFileName; + + /// + /// Init constructor. + /// + public KeyToolRegisterRunner(string pin, string password, string rdkFileName, string pbdtFileName) + { + if (string.IsNullOrEmpty(pin)) + throw new ArgumentNullException("pin"); + if (string.IsNullOrEmpty(password)) + throw new ArgumentNullException("password"); + if (string.IsNullOrEmpty(rdkFileName)) + throw new ArgumentNullException("rdkFileName"); + if (string.IsNullOrEmpty(pbdtFileName)) + throw new ArgumentNullException("pbdtFileName"); + + _pin = pin; + _password = password; + _rdkFileName = rdkFileName; + _pbdtFileName = pbdtFileName; + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the PIN setup at the time CSJ files were generated. It is required to decode info form them. + /// + public string PIN + { + get { return _pin; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _pin = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the access password for the generated certificate. + /// + public string Password + { + get { return _password; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _password = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets full path to the RDK file (received from BlackBerry). + /// + public string RdkFileName + { + get { return _rdkFileName; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _rdkFileName = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets full path to the PBDT file (received from BlackBerry). + /// + public string PbdtFileName + { + get { return _pbdtFileName; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _pbdtFileName = value; + UpdateArguments(); + } + } + } + + /// + /// Gets the name of the certificate file created (if needed) with info about the developer (publisher). + /// + public string CertificateFileName + { + get { return DeveloperDefinition.DefaultCertificateName; } + } + + #endregion + + private void UpdateArguments() + { + Arguments = string.Format(@"/C blackberry-signer.bat -register -csjpin ""{0}"" -storepass ""{1}"" ""{2}"" ""{3}""", + _pin, _password, _rdkFileName, _pbdtFileName); + } + + protected override void ConsumeResults(string output, string error) + { + if (string.IsNullOrEmpty(error) && !string.IsNullOrEmpty(output)) + { + LastError = ExtractErrorMessages(output); + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/KeyToolRemoveRunner.cs b/src_vs2012/NativeCore/Tools/KeyToolRemoveRunner.cs new file mode 100644 index 00000000..d76b4910 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/KeyToolRemoveRunner.cs @@ -0,0 +1,24 @@ +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner, that calls specific tool to remove instaled pair of signing keys. + /// + public sealed class KeyToolRemoveRunner : BBToolRunner + { + /// + /// Init constructor. + /// + public KeyToolRemoveRunner() + { + Arguments = @"/C blackberry-signer.bat -cskdelete"; + } + + protected override void ConsumeResults(string output, string error) + { + if (string.IsNullOrEmpty(error) && !string.IsNullOrEmpty(output)) + { + LastError = ExtractErrorMessages(output); + } + } + } +} diff --git a/src_vs2012/NativeCore/Tools/SshCreateKeyRunner.cs b/src_vs2012/NativeCore/Tools/SshCreateKeyRunner.cs new file mode 100644 index 00000000..f91edcd8 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/SshCreateKeyRunner.cs @@ -0,0 +1,126 @@ +using System; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Runner that calls ssh-keygen.exe to generate private/public pair of keys. + /// + public sealed class SshCreateKeyRunner : ToolRunner + { + private string _sshPublicKeyLocation; + private string _sshPrivateKeyLocation; + private uint _keySize; + + /// + /// + /// + /// Full path to the ssh-keygen.exe + /// Location of the public SSH key (can be null) + /// Location of the private SSH key + /// Size of the generated key in bits + public SshCreateKeyRunner(string sshKeyGenToolLocation, string sshPublicKeyLocation, string sshPrivateKeyLocation, uint keySize) + : base(!string.IsNullOrEmpty(sshKeyGenToolLocation) ? Path.GetFileName(sshKeyGenToolLocation) : null, + !string.IsNullOrWhiteSpace(sshKeyGenToolLocation) ? Path.GetDirectoryName(sshKeyGenToolLocation) : null) + { + if (string.IsNullOrEmpty(sshKeyGenToolLocation)) + throw new ArgumentNullException("sshKeyGenToolLocation"); + if (!File.Exists(sshKeyGenToolLocation)) + throw new ArgumentException("Specified SSH key generator doesn't exist", "sshKeyGenToolLocation"); + if (string.IsNullOrEmpty(sshPrivateKeyLocation)) + throw new ArgumentNullException("sshPrivateKeyLocation"); + + _sshPublicKeyLocation = sshPublicKeyLocation; + _sshPrivateKeyLocation = sshPrivateKeyLocation; + _keySize = keySize; + + UpdateArguments(); + } + + #region Properties + + /// + /// Gets or sets the location of the public SSH key. + /// + public string SshPublicKeyLocation + { + get { return _sshPublicKeyLocation; } + set { _sshPublicKeyLocation = value; } + } + + /// + /// Gets or sets the location of the private SSH key. + /// + public string SshPrivateKeyLocation + { + get { return _sshPrivateKeyLocation; } + set + { + if (!string.IsNullOrEmpty(value)) + { + _sshPrivateKeyLocation = value; + UpdateArguments(); + } + } + } + + /// + /// Gets or sets the generated key size (in bits). + /// + public uint KeySize + { + get { return _keySize; } + set + { + if (value > 0) + { + _keySize = value; + UpdateArguments(); + } + } + } + + #endregion + + private void UpdateArguments() + { + Arguments = string.Concat("-t rsa -N \"\" -b ", _keySize, " -f \"", _sshPrivateKeyLocation, "\""); + } + + /// + /// Method executed before starting the tool, to setup the state of the current runner. + /// + protected override void PrepareStartup() + { + // create directory, where the private and public keys are about to be stored + Directory.CreateDirectory(Path.GetDirectoryName(_sshPrivateKeyLocation)); + if (!string.IsNullOrEmpty(_sshPublicKeyLocation)) + { + Directory.CreateDirectory(Path.GetDirectoryName(_sshPublicKeyLocation)); + } + + // do default things + base.PrepareStartup(); + } + + protected override void Cleanup() + { + // since by default, the public key is named .pub, move the file to designated location: + var generatedPublicKey = _sshPrivateKeyLocation + ".pub"; + if (string.IsNullOrEmpty(_sshPublicKeyLocation) && File.Exists(generatedPublicKey) && string.CompareOrdinal(_sshPublicKeyLocation, generatedPublicKey) != 0) + { + try + { + File.Move(generatedPublicKey, _sshPublicKeyLocation); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to move generated public SSH key from: \"{0}\" to \"{1}\"", generatedPublicKey, _sshPublicKeyLocation); + } + } + + base.Cleanup(); + } + } +} diff --git a/src_vs2012/NativeCore/Tools/ToolRunner.cs b/src_vs2012/NativeCore/Tools/ToolRunner.cs new file mode 100644 index 00000000..81e3015e --- /dev/null +++ b/src_vs2012/NativeCore/Tools/ToolRunner.cs @@ -0,0 +1,512 @@ +using System; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Management; +using System.Text; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Class that runs specified executable, captures its output and error messages, then provides to parsers (implemented in child classes! by overriding ConsumeResults() method). + /// + /// Note: The outputs are assumed to be small. They are all accumulated inside internal buffers and at process exit just flushed. + /// If this behavior doesn't suit specific tool needs, override the ProcessOutputLine() and ProcessErrorLine() methods to process them as they arrive. + /// + public class ToolRunner : IDisposable + { + private Process _process; + private StringBuilder _output; + private StringBuilder _error; + private bool _isProcessing; + + public static event EventHandler Startup; + public event EventHandler Finished; + + /// + /// Default constructor. + /// + public ToolRunner() + { + _process = new Process(); + + _process.StartInfo.UseShellExecute = false; + _process.StartInfo.CreateNoWindow = true; + _process.StartInfo.RedirectStandardOutput = true; + _process.StartInfo.RedirectStandardError = true; + _process.StartInfo.RedirectStandardInput = true; + + _process.OutputDataReceived += OutputDataReceived; + _process.ErrorDataReceived += ErrorDataReceived; + } + + ~ToolRunner() + { + Dispose(false); + } + + /// + /// Init constructor. Setups the executable and its working directory. + /// + /// Name of the binary to execute + /// Executable working directory + public ToolRunner(string fileName, string workingDirectory) + : this() + { + FileName = fileName; + WorkingDirectory = workingDirectory; + } + + #region Properties + + public IEventDispatcher Dispatcher + { + get; + set; + } + + public string FileName + { + get { return _process.StartInfo.FileName; } + set { _process.StartInfo.FileName = value; } + } + + public string WorkingDirectory + { + get { return _process.StartInfo.WorkingDirectory; } + set { _process.StartInfo.WorkingDirectory = value; } + } + + public StringDictionary Environment + { + get { return _process.StartInfo.EnvironmentVariables; } + } + + public string Arguments + { + get { return _process.StartInfo.Arguments; } + set { _process.StartInfo.Arguments = value; } + } + + public bool IsProcessing + { + get { return _isProcessing; } // using custom variable instead of _process.HasExited, as 'data processing' after tool termination should also indicate that state + } + + public int ExitCode + { + get; + private set; + } + + public string LastOutput + { + get; + protected set; + } + + public string LastError + { + get; + protected set; + } + + public object Tag + { + get; + set; + } + + #endregion + + #region Internal Properties + + protected int PID + { + get; + set; + } + + /// + /// Gets or sets the indication, if started process should display a main application window. + /// Please note, that showing a console window for CUI tools will disable any output redirection. + /// + protected bool ShowWindow + { + get { return _process != null && !_process.StartInfo.CreateNoWindow; } + set + { + if (_process == null) + throw new ObjectDisposedException("ToolRunner"); + + _process.StartInfo.CreateNoWindow = !value; + + // and don't redirect anything, to have the data displayed inside that window: + _process.StartInfo.RedirectStandardOutput = !value; + _process.StartInfo.RedirectStandardError = !value; + } + } + + #endregion + + protected virtual void ProcessOutputLine(string text) + { + if (_output != null && text != null) + _output.AppendLine(text); + } + + protected virtual void ProcessErrorLine(string text) + { + if (_error != null && text != null) + _error.AppendLine(text); + } + + private void OutputDataReceived(object sender, DataReceivedEventArgs e) + { + if (e.Data != null) + { + ProcessOutputLine(e.Data); + } + } + + private void ErrorDataReceived(object sender, DataReceivedEventArgs e) + { + if (e.Data != null) + { + ProcessErrorLine(e.Data); + } + } + + private void InternalPrepareStarted() + { + if (_process.StartInfo.RedirectStandardError) + _process.BeginErrorReadLine(); + if (_process.StartInfo.RedirectStandardOutput) + _process.BeginOutputReadLine(); + if (_process.StartInfo.RedirectStandardInput) + _process.StandardInput.AutoFlush = true; + + PID = _process.Id; + PrepareStarted(PID); + } + + /// + /// Starts the tool and waits until it completes. It will block the current thread until that time. + /// The executable file name and all arguments are required to be setup earlier. + /// + /// Returns 'true', if tool returned exit code '0', otherwise 'false'. + public bool Execute() + { + if (_isProcessing) + throw new InvalidOperationException("The process is already running"); + if (_process == null) + throw new ObjectDisposedException("ToolRunner"); + if (string.IsNullOrEmpty(FileName)) + throw new InvalidOperationException("No executable to start"); + + PrepareExecution(); + + try + { + _process.EnableRaisingEvents = false; + _process.Start(); + InternalPrepareStarted(); + + _process.WaitForExit(); + ExitCode = _process.ExitCode; + + return ExitCode == 0; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to start {0}", GetType().Name); + ProcessErrorLine(ex.Message); + return false; + } + finally + { + // release process resources: + _process.Close(); + + CompleteExecution(); + } + } + + /// + /// Starts the tool asynchronously. It will not block the current thread. + /// Subscribe to Finished event before, to know, when tool's process completed execution. + /// + public void ExecuteAsync() + { + if (_isProcessing) + throw new InvalidOperationException("The process is already running"); + if (_process == null) + throw new ObjectDisposedException("ToolRunner"); + + PrepareExecution(); + + try + { + _process.Exited -= AsyncProcessExited; + _process.Exited += AsyncProcessExited; + _process.EnableRaisingEvents = true; + + _process.Start(); + InternalPrepareStarted(); + } + catch (Exception ex) + { + Debug.WriteLine(_process.StartInfo.Arguments); + TraceLog.WriteException(ex, "Unable to start {0}", GetType().Name); + + _process.Close(); + _isProcessing = false; + + ProcessErrorLine(ex.Message); + NotifyFinished(-1, null, null); + } + } + + private void AsyncProcessExited(object sender, EventArgs e) + { + if (_process != null) + { + ExitCode = _process.ExitCode; + _process.Exited -= AsyncProcessExited; + + // release process resources: + _process.Close(); + + CompleteExecution(); + } + } + + private void NotifyFinished(int exitCode, string output, string error) + { + var finishedHandler = Finished; + var dispatcher = Dispatcher; + + if (finishedHandler != null) + { + // perform a cross-thread notification (in case we want to update UI directly from the handler) + if (dispatcher != null) + { + dispatcher.Invoke(finishedHandler, this, new ToolRunnerEventArgs(exitCode, output, error, Tag)); + } + else + { + finishedHandler(this, new ToolRunnerEventArgs(exitCode, output, error, Tag)); + } + } + } + + private void PrepareExecution() + { + ExitCode = int.MinValue; + _isProcessing = true; + LastOutput = null; + LastError = null; + _output = new StringBuilder(); + _error = new StringBuilder(); + + // allow setup customization by sub-classes: + PrepareStartup(); + } + + private void CompleteExecution() + { + var outputText = _output != null && _output.Length > 0 ? _output.ToString() : null; + var errorText = _error != null && _error.Length > 0 ? _error.ToString() : null; + + _output = null; + _error = null; + LastOutput = outputText; + LastError = errorText; + +#if DEBUG + TraceLog.WriteLine("{0} {1}", _process.StartInfo.FileName, _process.StartInfo.Arguments); + TraceLog.WriteLine(" * PATH: {0}", _process.StartInfo.EnvironmentVariables["PATH"]); + TraceLog.WriteLine(" * QNX_TARGET: {0}", _process.StartInfo.EnvironmentVariables["QNX_TARGET"]); + TraceLog.WriteLine(" * QNX_HOST: {0}", _process.StartInfo.EnvironmentVariables["QNX_HOST"]); + + // print received data: + if (!string.IsNullOrEmpty(outputText)) + TraceLog.WriteLine(outputText.Trim()); + if (!string.IsNullOrEmpty(errorText)) + TraceLog.WarnLine(errorText.Trim()); +#endif + + // consume received data: + ConsumeResults(outputText, errorText); + + // notify other listeners, in case they want to get something extra: + NotifyFinished(ExitCode, outputText, errorText); + + _isProcessing = false; + Cleanup(); + } + + /// + /// Method executed before starting the tool, to setup the state of the current runner. + /// + protected virtual void PrepareStartup() + { + // this is the place to override and DISABLE running GLOBAL setup: + var handler = Startup; + if (handler != null) + handler(this, new ToolRunnerStartupEventArgs(this)); + } + + /// + /// Method executed just after staring the tool, to setup extra behavior of the runner. + /// + protected virtual void PrepareStarted(int pid) + { + // do nothing, subclasses should handle it, if needed + } + + protected virtual void ConsumeResults(string output, string error) + { + // do nothing, subclasses should handle parsing output + } + + protected virtual void Cleanup() + { + // do nothing, subclasses should handle it, when needed + } + + /// + /// Sends given text to the process. + /// + /// Returns 'true', when sending succeeded, otherwise 'false'. + public virtual bool SendInput(string text) + { + if (_process != null && IsProcessing) + { + _process.StandardInput.WriteLine(text); + return true; + } + + return false; + } + + /// + /// Sends given char to the process. + /// + /// Returns 'true', when sending succeeded, otherwise 'false'. + public virtual bool SendInput(char c) + { + if (_process != null) + { + _process.StandardInput.Write(c); + return true; + } + + return false; + } + + /// + /// Sends given chars to the process. + /// + /// Returns 'true', when sending succeeded, otherwise 'false'. + public virtual bool SendInput(char[] buffer, int startIndex, int count) + { + if (_process != null) + { + _process.StandardInput.Write(buffer, startIndex, count); + return true; + } + + return false; + } + + /// + /// Extracts the error messages out of the given text. + /// + protected static string ExtractErrorMessages(string error) + { + if (string.IsNullOrEmpty(error)) + return null; + + var result = new StringBuilder(); + var lines = error.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var line in lines) + { + if (line.StartsWith("error:", StringComparison.InvariantCultureIgnoreCase)) + { + if (result.Length > 0) + result.AppendLine(); + result.Append(line.Substring(6).Trim()); + } + } + + return result.ToString(); + } + + /// + /// Aborts the process and all its child processes. + /// + public virtual bool Abort() + { + if (!IsProcessing) + return false; + if (_process == null) + throw new ObjectDisposedException("ToolRunner"); + + // kill current process and all child ones: + if (IsProcessing) + { + try + { + _process.Kill(); // PH: INFO: somehow, it gets automatically killed for command-line tools... + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to kill current tool"); + } + } + + var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Process WHERE ParentProcessId=" + PID); + foreach (var item in searcher.Get()) + { + try + { + var childProcess = Process.GetProcessById(Convert.ToInt32(item["ProcessId"].ToString())); + childProcess.Kill(); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to kill current tool child-process"); + } + } + + return true; + } + + #region IDisposable Implementation + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_process != null) + { + _process.Exited -= AsyncProcessExited; + _process.OutputDataReceived -= OutputDataReceived; + _process.ErrorDataReceived -= ErrorDataReceived; + + Abort(); + _process.Dispose(); + _process = null; + } + + Finished = null; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Tools/ToolRunnerEventArgs.cs b/src_vs2012/NativeCore/Tools/ToolRunnerEventArgs.cs new file mode 100644 index 00000000..b1f06575 --- /dev/null +++ b/src_vs2012/NativeCore/Tools/ToolRunnerEventArgs.cs @@ -0,0 +1,51 @@ +using System; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Arguments passes along with ToolRunner events. + /// + public sealed class ToolRunnerEventArgs : EventArgs + { + #region Properties + + public ToolRunnerEventArgs(int exitCode, string output, string error, object tag) + { + ExitCode = exitCode; + Output = output; + Error = error; + Tag = tag; + } + + public int ExitCode + { + get; + private set; + } + + public string Output + { + get; + private set; + } + + public string Error + { + get; + private set; + } + + public bool IsSuccessfull + { + get { return string.IsNullOrEmpty(Error); } + } + + public object Tag + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/NativeCore/Tools/ToolRunnerStartupEventArgs.cs b/src_vs2012/NativeCore/Tools/ToolRunnerStartupEventArgs.cs new file mode 100644 index 00000000..f9b33e2c --- /dev/null +++ b/src_vs2012/NativeCore/Tools/ToolRunnerStartupEventArgs.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Specialized; + +namespace BlackBerry.NativeCore.Tools +{ + /// + /// Arguments passed along with Startup event of the ToolRunner class. + /// + public sealed class ToolRunnerStartupEventArgs : EventArgs + { + private readonly ToolRunner _runner; + + /// + /// Init constructor. + /// + public ToolRunnerStartupEventArgs(ToolRunner runner) + { + if (runner == null) + throw new ArgumentNullException("runner"); + + _runner = runner; + } + + #region Properties + + /// + /// Gets or set the working directory of the runner. + /// + public string WorkingDirectory + { + get { return _runner.WorkingDirectory; } + set { _runner.WorkingDirectory = value; } + } + + /// + /// Gets the reference to environment variables. + /// + public StringDictionary Environment + { + get { return _runner.Environment; } + } + + #endregion + + /// + /// Indexer to access and update environment variables. + /// + public string this[string key] + { + get { return _runner.Environment[key]; } + set { _runner.Environment[key] = value; } + } + } +} diff --git a/src_vs2012/Package/BlackBerry.Package.csproj b/src_vs2012/Package/BlackBerry.Package.csproj new file mode 100644 index 00000000..a27a5b5f --- /dev/null +++ b/src_vs2012/Package/BlackBerry.Package.csproj @@ -0,0 +1,931 @@ + + + + + Debug + AnyCPU + 2.0 + {3D6EFFAF-FF39-497D-B6F8-0B6169E90C6D} + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + BlackBerry.Package + BlackBerry.Package + false + + + v4.5 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + 11.0 + + + + + 4.0 + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PLATFORM_VS2012 + prompt + 4 + true + false + AnyCPU + false + + + pdbonly + true + bin\Release\ + TRACE;PLATFORM_VS2012;CODE_ANALYSIS + prompt + 4 + true + true + false + AnyCPU + + + + + + + + False + ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\Microsoft.VisualStudio.Package.LanguageService.11.0.dll + + + + + + + + false + + + + + True + + + ..\..\..\..\..\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.VisualStudio.XmlEditor\v4.0_11.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.XmlEditor.dll + + + + + + + + + + + + + + + + + + + {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2} + 8 + 0 + 0 + primary + False + False + + + {26AD1324-4B7C-44BC-84F8-B86AED45729F} + 10 + 0 + 0 + primary + False + False + + + {1A31287A-4D7D-413E-8E32-3B374931BD89} + 8 + 0 + 0 + primary + False + False + + + {2CE2370E-D744-4936-A090-3FFFE667B0E1} + 9 + 0 + 0 + primary + False + False + + + {1CBA492E-7263-47BB-87FE-639000619B15} + 8 + 0 + 0 + primary + False + False + + + + + GlobalSuppressions.cs + + + Properties\AssemblyInfo.cs + + + Resources\Strings.Designer.cs + True + True + Strings.resx + + + + + + + + + + Form + + + BinaryDiscoveryForm.cs + + + Form + + + CachedAuthorForm.cs + + + Form + + + FolderForm.cs + + + Form + + + ImportProjectForm.cs + + + BarDescriptorEditorControl.xaml + + + + + + + + + + + + + + + + + + + + + Component + + + Code + + + Code + + + Code + + + UserControl + + + ApiLevelOptionControl.cs + + + Component + + + Form + + + AboutForm.cs + + + Form + + + AddLocalNdkForm.cs + + + Form + + + CertificateDetailsForm.cs + + + Form + + + CskRequestForm.cs + + + Form + + + DebugTokenDeploymentForm.cs + + + Form + + + DeviceForm.cs + + + Form + + + InstallConfirmationForm.cs + + + Form + + + InstallForm.cs + + + UserControl + + + ListItemControl.cs + + + Form + + + MissingNdkInstalledForm.cs + + + Form + + + PasswordForm.cs + + + Form + + + PinListForm.cs + + + Form + + + RegistrationForm.cs + + + Form + + + UpdateManagerStatusForm.cs + + + UserControl + + + BackupOptionControl.cs + + + Component + + + UserControl + + + GeneralOptionControl.cs + + + Component + + + UserControl + + + LogsOptionControl.cs + + + Component + + + UserControl + + + SigningOptionControl.cs + + + Component + + + UserControl + + + TargetsOptionControl.cs + + + Component + + + + + + + + + TargetNavigatorControl.xaml + + + + + + + Code + + + + Code + + + + + + + + + + + + + + + + + + + + Code + + + + Always + true + + + Always + true + + + Always + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + Designer + + + true + + + true + + + true + + + true + + + true + + + true + + + Designer + + + + + true + + + true + + + true + + + true + + + true + + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + CachedAuthorForm.cs + + + ImportProjectForm.cs + + + BackupOptionControl.cs + + + Designer + + + + Always + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + Resources\Images_24bit.bmp + + + Resources\Images_32bit.bmp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BinaryDiscoveryForm.cs + + + CertificateDetailsForm.cs + + + CskRequestForm.cs + + + InstallConfirmationForm.cs + + + InstallForm.cs + + + ListItemControl.cs + + + MissingNdkInstalledForm.cs + + + FolderForm.cs + + + UpdateManagerStatusForm.cs + + + + + Resources\File.ico + + + Resources\info.png + + + Resources\Package.ico + + + + + Resources\Strings.resx + ResXFileCodeGenerator + Strings.Designer.cs + + + Resources\Package.resx + true + Package + Designer + + + ApiLevelOptionControl.cs + + + AboutForm.cs + + + AddLocalNdkForm.cs + + + DebugTokenDeploymentForm.cs + + + DeviceForm.cs + + + PasswordForm.cs + + + PinListForm.cs + + + RegistrationForm.cs + + + GeneralOptionControl.cs + + + LogsOptionControl.cs + + + SigningOptionControl.cs + + + TargetsOptionControl.cs + + + + + Key.snk + + + Designer + Always + + + + + Menus.ctmenu + Designer + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + {59a7b188-e307-4495-a3af-4ed76b086a87} + BlackBerry.DebugEngine + + + {9A560339-44DB-413F-868C-403962C2CF01} + BlackBerry.GDBHost + BuiltProjectOutputGroup%3bBuiltProjectOutputGroupDependencies%3bGetCopyToOutputDirectoryItems%3bSatelliteDllsProjectOutputGroup%3b + DebugSymbolsProjectOutputGroup%3b + false + + + {faddd789-6cb5-4f9d-8481-1c0c72e5f19f} + BlackBerry.NativeCore + + + + + true + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + \ No newline at end of file diff --git a/src_vs2012/Package/BlackBerryPackage.cs b/src_vs2012/Package/BlackBerryPackage.cs new file mode 100644 index 00000000..0639c2ac --- /dev/null +++ b/src_vs2012/Package/BlackBerryPackage.cs @@ -0,0 +1,670 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.InteropServices; +using System.ComponentModel.Design; +using BlackBerry.DebugEngine; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Debugger.Model; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Services; +using BlackBerry.Package.Components; +using BlackBerry.Package.Diagnostics; +using BlackBerry.Package.Dialogs; +using BlackBerry.Package.Editors; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.Model.Integration; +using BlackBerry.Package.Options; +using BlackBerry.Package.Registration; +using BlackBerry.Package.ToolWindows; +using BlackBerry.Package.ViewModels; +using BlackBerry.Package.Wizards; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Shell; +using System.IO; +using EnvDTE; +using System.Windows.Forms; +using BlackBerry.Package.Languages.Qml; +using EnvDTE80; + +namespace BlackBerry.Package +{ + /// + /// This is the class that implements the package exposed by this assembly. + /// + /// The minimum requirement for a class to be considered a valid package for Visual Studio + /// is to implement the IVsPackage interface and register itself with the shell. + /// This package uses the helper classes defined inside the Managed Package Framework (MPF) + /// to do it: it derives from the Package class that provides the implementation of the + /// IVsPackage interface and uses the registration attributes defined in the framework to + /// register itself and its components with the shell. + /// + [PackageRegistration(UseManagedResourcesOnly = true)] + // Register the editor factory + [XmlEditorDesignerViewRegistration("BarDescriptor", BarDescriptorEditorFactory.DefaultExtension, LogicalViewID.Designer, 0x60, DesignerLogicalViewEditor = typeof(BarDescriptorEditorFactory), + Namespace = "http://www.qnx.com/schemas/application/1.0", MatchExtensionAndNamespace = true)] + // And which type of files we want to handle and notify about file changes, while in Microsoft Visual C++ Projects + [ProvideEditorExtension(typeof(BarDescriptorEditorFactory), BarDescriptorEditorFactory.DefaultExtension, 0x10, NameResourceID = 106, EditorFactoryNotify = true, ProjectGuid = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")] + // We register that our editor supports LOGVIEWID_Designer logical view + [ProvideEditorLogicalView(typeof(BarDescriptorEditorFactory), LogicalViewID.Designer)] + + // Registration of custom debugger + [DebugEngineRegistration(AD7PortSupplier.PublicName, AD7Engine.DebugEngineGuid, + Attach = true, AddressBreakpoints = false, CallstackBreakpoints = true, AlwaysLoadLocal = true, AutoSelectPriority = 4, + DebugEngineClassGUID = AD7Engine.ClassGuid, DebugEngineClassName = AD7Engine.ClassName, + ProgramProviderClassGUID = AD7ProgramProvider.ClassGuid, ProgramProviderClassName = AD7ProgramProvider.ClassName, + PortSupplierClassGUID = AD7PortSupplier.ClassGuid, PortSupplierClassName = AD7PortSupplier.ClassName, +#if DEBUG + AssemblyName = ConfigDefaults.DebugEngineDebugablePath +#else + AssemblyName = "BlackBerry.DebugEngine.dll" +#endif +)] + + // This attribute is used to register the informations needed to show the this package + // in the Help/About dialog of Visual Studio. + [InstalledProductRegistration("#110", "#112", ConfigDefaults.VersionString, IconResourceID = 400)] + // This attribute is needed to let the shell know that this package exposes some menus. + [ProvideMenuResource("Menus.ctmenu", 1)] + + [ProvideAutoLoad(UIContextGuids80.SolutionExists)] + [Guid(GuidList.guidVSNDK_PackageString)] + + // This attribute adds top level node at [Add Project Item] dialog for Visual C++ projects only and showing + // new item wizards from '/Templates/ProjectItems' folder. This is an easy way to inject new templates + // without any need of copying them into Visual Studio folder itself. + // No extra permissions for the plugin are required in that case. + [ProvideProjectItem("{8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942}", "BlackBerry", @"Templates\ProjectItems\BlackBerry", 10)] +#if PLATFORM_VS2013 + // PH: somehow for VS2013 it uses a different value for VC++ projects... don't ask, how I discovered it + [ProvideProjectItem("{8bc9ceb8-8b4a-11d0-8d11-00a0c91bc943}", "BlackBerry", @"Templates\ProjectItems\BlackBerry", 10)] +#endif + [ProvideProjectItem("{a2fe74e1-b743-11d0-ae1a-00a0c90fffc3}", "BlackBerry", @"Templates\ProjectItems\BlackBerry", 11)] + [ProvideProjects(GuidList.guidVSNDK_PackageString, "BlackBerry Projects", @"Templates\Projects\BlackBerry", 31)] + // This attribute registers a custom wizard engine, that is used to populate new projects and items into a project. + // Reference to this engine is made directly from *.vsz file (from locations provided by both attributes above). + [ProvideWizardEngine(typeof(PuppetMasterWizardEngine))] + + // This attribute defines set of settings pages provided by this package. + // They are automatically instantiated and displayed inside [Visual Studio -> Tools -> Options...] dialog. + [ProvideOptionPage(typeof(GeneralOptionPage), OptionsCategoryName, "General", 1001, 1002, true)] + [ProvideOptionPage(typeof(LogsOptionPage), OptionsCategoryName, "Logs", 1001, 1003, true)] + [ProvideOptionPage(typeof(ApiLevelOptionPage), OptionsCategoryName, "API Levels", 1001, 1004, true)] + [ProvideOptionPage(typeof(TargetsOptionPage), OptionsCategoryName, "Targets", 1001, 1005, true)] + [ProvideOptionPage(typeof(SigningOptionPage), OptionsCategoryName, "Signing", 1001, 1006, true)] + [ProvideOptionPage(typeof(BackupOptionPage), OptionsCategoryName, "Backup", 1001, 1007, true)] + + // This attribute registers public services exposed by this package. + // The package itself will be automatically loaded if needed. + [ProvideService(typeof(IDeviceDiscoveryService), ServiceName = "BlackBerry Device Discovery")] + [ProvideService(typeof(IAttachDiscoveryService), ServiceName = "BlackBerry Process-Attach Executable Discovery")] + + // This set of attributes registers QML language service to allow colorizing and IntelliSense support. + [ProvideService(typeof(QmlLanguageService), ServiceName = "QML")] + [ProvideLanguageExtension(typeof(QmlLanguageService), ".qml")] + [ProvideLanguageExtension(typeof(QmlLanguageService), ".jsqml")] + [ProvideLanguageService(typeof(QmlLanguageService), QmlLanguageService.LanguageName, 0)] + + // This attribute registers a tool window exposed by this package. + [ProvideToolWindow(typeof(TargetNavigatorPane), Style = VsDockStyle.Tabbed, MultiInstances = false)] + public sealed class BlackBerryPackage : Microsoft.VisualStudio.Shell.Package, IDisposable, IDeviceDiscoveryService, IAttachDiscoveryService + { + public const string OptionsCategoryName = "BlackBerry"; + + private BlackBerryPaneTraceListener _mainTraceWindow; + private BlackBerryPaneTraceListener _gdbTraceWindow; + private BlackBerryPaneTraceListener _qconnTraceWindow; + private BlackBerryPaneTraceListener _standardOutputWindow; + private DTE2 _dte; + private BuildPlatformsManager _buildPlatformsManager; + + #region Package Members + + /// + /// Default constructor of the package. + /// Inside this method you can place any initialization code that does not require + /// any Visual Studio service because at this point the package object is created but + /// not sited yet inside Visual Studio environment. The place to do all the other + /// initialization is the Initialize method. + /// + public BlackBerryPackage() + { + Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", ToString())); + } + + ~BlackBerryPackage() + { + Dispose(false); + } + + /// + /// Initialization of the package; this method is called right after the package is sited, so this is the place + /// where you can put all the initialization code that rely on services provided by VisualStudio. + /// + protected override void Initialize() + { + Trace.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", ToString())); + base.Initialize(); + + _dte = (DTE2) GetService(typeof(SDTE)); + + // create dedicated persistent logs + var logOptions = (LogsOptionPage)GetDialogPage(typeof(LogsOptionPage)); + LogManager.Initialize(logOptions.Path, logOptions.LimitLogs ? logOptions.LimitCount : -1, TraceLog.Category, TraceLog.CategoryGDB); + Targets.TraceOptions(logOptions.DebuggedOnly, logOptions.LogsInterval, logOptions.SLog2Level, logOptions.SLog2Formatter, logOptions.GetSLog2BufferSets(), logOptions.InjectLogs, TraceLog.CategoryDevice); + + // create dedicated trace-logs output window pane (available in combo-box at regular Visual Studio Output Window): + var outputWindowService = GetService(typeof(SVsOutputWindow)) as IVsOutputWindow; + _mainTraceWindow = new BlackBerryPaneTraceListener("BlackBerry", TraceLog.Category, true, outputWindowService, GuidList.GUID_TraceMainOutputWindowPane); +#if DEBUG + _gdbTraceWindow = new BlackBerryPaneTraceListener("BlackBerry - GDB", TraceLog.CategoryGDB, true, outputWindowService, GuidList.GUID_TraceGdbOutputWindowPane); +#endif + _qconnTraceWindow = new BlackBerryPaneTraceListener("BlackBerry - QConn", QTraceLog.Category, true, outputWindowService, GuidList.GUID_TraceQConnOutputWindowPane); + _standardOutputWindow = new BlackBerryPaneTraceListener("Debug", TraceLog.CategoryDevice, false, outputWindowService, VSConstants.GUID_OutWindowDebugPane); + _mainTraceWindow.Activate(); + + // and set it to monitor all logs (they have to be marked with 'BlackBerry' category! aka TraceLog.Category): + TraceLog.Add(_mainTraceWindow); + TraceLog.Add(_gdbTraceWindow); + TraceLog.Add(_qconnTraceWindow); + TraceLog.Add(_standardOutputWindow); + TraceLog.WriteLine("BlackBerry plugin started"); +#if DEBUG + TraceLog.WriteLine(" * location: \"{0}\"", System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); +#endif + + // add this package to the globally-proffed services: + IServiceContainer serviceContainer = this; + serviceContainer.AddService(typeof(IDeviceDiscoveryService), this, true); + serviceContainer.AddService(typeof(IAttachDiscoveryService), this, true); + serviceContainer.AddService(typeof(QmlLanguageService), new QmlLanguageService(), true); + + TraceLog.WriteLine(" * registered services"); + + TraceLog.WriteLine(" * loaded NDK descriptions"); + + // inform Targets, that list of target-devices has been changed and maybe it should force some disconnections: + PackageViewModel.Instance.TargetsChanged += (s, e) => Targets.DisconnectIfOutside(e.TargetDevices); + + // Create Editor Factory. Note that the base Package class will call Dispose on it. + RegisterEditorFactory(new BarDescriptorEditorFactory()); + TraceLog.WriteLine(" * registered editors"); + + _buildPlatformsManager = new BuildPlatformsManager(_dte); + _buildPlatformsManager.Navigate += OpenUrl; + _buildPlatformsManager.OpenSettingsPage += ShowOptionPage; + _buildPlatformsManager.Initialize(); + TraceLog.WriteLine(" * registered build-platforms manager"); + + // Add our command handlers for menu (commands must exist in the .vsct file) + OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; + if (mcs != null) + { + // Create command for the 'Options...' menu + CommandID optionsCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryOptions); + MenuCommand optionsMenu = new MenuCommand((s, e) => ShowOptionPage(typeof(GeneralOptionPage)), optionsCommandID); + mcs.AddCommand(optionsMenu); + + // Create dynamic command for the 'devices-list' menu + CommandID devicesCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryTargetsDevicesPlaceholder); + DynamicMenuCommand devicesMenu = new DynamicMenuCommand(() => PackageViewModel.Instance.TargetDevices, + (cmd, collection, index) => + { + var item = index >= 0 && index < collection.Count ? ((DeviceDefinition[])collection)[index] : null; + PackageViewModel.Instance.ActiveDevice = item; + }, + (cmd, collection, index) => + { + var item = index >= 0 && index < collection.Count ? ((DeviceDefinition[])collection)[index] : null; + cmd.Checked = item != null && (item == PackageViewModel.Instance.ActiveDevice || item == PackageViewModel.Instance.ActiveSimulator); + cmd.Visible = item != null; + cmd.Text = item != null ? item.ToString() : "-"; + }, + devicesCommandID); + mcs.AddCommand(devicesMenu); + + // Create dynamic command for the 'api-level-list' menu + CommandID apiLevelCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryTargetsApiLevelsPlaceholder); + DynamicMenuCommand apiLevelMenu = new DynamicMenuCommand(() => PackageViewModel.Instance.InstalledNDKs, + (cmd, collection, index) => + { + var item = index >= 0 && index < collection.Count ? ((NdkInfo[]) collection)[index] : null; + PackageViewModel.Instance.ActiveNDK = item; + }, + (cmd, collection, index) => + { + var item = index >= 0 && index < collection.Count ? ((NdkInfo[]) collection)[index] : null; + cmd.Checked = item != null && item == PackageViewModel.Instance.ActiveNDK; + cmd.Visible = item != null; + cmd.Text = item != null ? item.ToString() : "-"; + }, + apiLevelCommandID); + mcs.AddCommand(apiLevelMenu); + + // Create dynamic command for the 'runtime-libraries' menu + CommandID runtimeCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryTargetsRuntimeLibrariesPlaceholder); + DynamicMenuCommand runtimeMenu = new DynamicMenuCommand(() => PackageViewModel.Instance.InstalledRuntimes, + (cmd, collection, index) => + { + var item = index >= 0 && index < collection.Count ? ((RuntimeInfo[]) collection)[index] : null; + PackageViewModel.Instance.ActiveRuntime = item; + }, + (cmd, collection, index) => + { + var item = index >= 0 && index < collection.Count ? ((RuntimeInfo[])collection)[index] : null; + cmd.Checked = item != null && item == PackageViewModel.Instance.ActiveRuntime; + cmd.Visible = item != null; + cmd.Text = item != null ? item.Name : "-"; + }, + runtimeCommandID); + mcs.AddCommand(runtimeMenu); + + // Create command for 'Help' menus + var helpCmdIDs = new[] { + PackageCommands.cmdidBlackBerryHelpWelcomePage, PackageCommands.cmdidBlackBerryHelpSupportForum, + PackageCommands.cmdidBlackBerryHelpDocNative, PackageCommands.cmdidBlackBerryHelpDocCascades, PackageCommands.cmdidBlackBerryHelpDocPlayBook, + PackageCommands.cmdidBlackBerryHelpSamplesNative, PackageCommands.cmdidBlackBerryHelpSamplesCascades, PackageCommands.cmdidBlackBerryHelpSamplesPlayBook, PackageCommands.cmdidBlackBerryHelpSamplesOpenSource, + PackageCommands.cmdidBlackBerryHelpAbout + }; + foreach (var cmdID in helpCmdIDs) + { + CommandID helpCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, cmdID); + MenuCommand helpMenu = new MenuCommand(OpenHelpWebPage, helpCommandID); + mcs.AddCommand(helpMenu); + } + + // Create command for 'Configure...' [targets] menu + CommandID configureCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryTargetsConfigure); + MenuCommand configureMenu = new MenuCommand((s, e) => ShowOptionPage(typeof(TargetsOptionPage)), configureCommandID); + mcs.AddCommand(configureMenu); + + // Create the command for 'Add BlackBerry Platforms' menu item + CommandID platformsCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryCommonAddPlatformTargets); + OleMenuCommand platformsItem = new OleMenuCommand(AddBlackBerryTargetPlatforms, platformsCommandID); + mcs.AddCommand(platformsItem); + + // Create the command for 'Import BlackBerry Native Project' menu item + CommandID projectCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryCommonProjectImport); + OleMenuCommand projectItem = new OleMenuCommand(ImportBlackBerryProject, projectCommandID); + mcs.AddCommand(projectItem); + + // Create the command for 'Target Navigator' menu item + CommandID targetNavigatorCommandID = new CommandID(GuidList.guidVSNDK_PackageCmdSet, PackageCommands.cmdidBlackBerryToolWindowsTargetNavigator); + OleMenuCommand targetNavigatorMenu = new OleMenuCommand(ShowTargetNavigator, targetNavigatorCommandID); + mcs.AddCommand(targetNavigatorMenu); + + TraceLog.WriteLine(" * initialized menus"); + } + + TraceLog.WriteLine("-------------------- DONE ({0})", ConfigDefaults.VersionString); + + // make sure there is an NDK selected and developer knows about it: + EnsureActiveNDK(); + if (_buildPlatformsManager.IsBlackBerrySolution() && ActiveNDK == null && InstalledNDKs.Length > 0) + { + var form = new MissingNdkInstalledForm(); + form.ShowDialog(); + EnsureActiveNDK(); + } + + _buildPlatformsManager.VerifyCommonErrors(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_mainTraceWindow != null) + { + _mainTraceWindow.Dispose(); + _mainTraceWindow = null; + } + if (_gdbTraceWindow != null) + { + _gdbTraceWindow.Dispose(); + _gdbTraceWindow = null; + } + if (_qconnTraceWindow != null) + { + _qconnTraceWindow.Dispose(); + _qconnTraceWindow = null; + } + + if (_buildPlatformsManager != null) + { + _buildPlatformsManager.Close(); + _buildPlatformsManager = null; + } + + Targets.TraceStop(); + } + + base.Dispose(disposing); + } + + protected override int QueryClose(out bool canClose) + { + var updateManager = PackageViewModel.Instance.UpdateManager; + + if (updateManager.IsRunning) + { + canClose = false; + + if (MessageBoxHelper.Show("Do you want to abort it and exit?", + "There are still some jobs running by BlackBerry Native Plugin (i.e. new NDK, simulator or runtime downloads).", + MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) + { + canClose = true; + updateManager.CancelAll(); + } + } + else + { + canClose = true; + } + + return VSConstants.S_OK; + } + + public Window2 OpenWebPageTab(string url) + { + return (Window2)_dte.ItemOperations.Navigate(url, vsNavigateOptions.vsNavigateOptionsNewWindow); + } + + private void OpenUrl(string url) + { + var options = (GeneralOptionPage)GetDialogPage(typeof(GeneralOptionPage)); + + if (options.IsOpeningExternal) + { + DialogHelper.StartURL(url); + } + else + { + OpenWebPageTab(url); + } + } + + private void OpenHelpWebPage(object sender, EventArgs e) + { + var menuCommand = sender as MenuCommand; + int cmdID = menuCommand != null ? menuCommand.CommandID.ID : 0; + + switch (cmdID) + { + case PackageCommands.cmdidBlackBerryHelpSupportForum: + OpenUrl("http://supportforums.blackberry.com/t5/Developer-Support-Forums/ct-p/blackberrydev"); + break; + case PackageCommands.cmdidBlackBerryHelpDocNative: + OpenUrl("http://developer.blackberry.com/native/"); + break; + //case PackageCommands.cmdidBlackBerryHelpDocCascades: + // OpenUrl("http://developer.blackberry.com/native/documentation/cascades/dev/index.html"); + // break; + //case PackageCommands.cmdidBlackBerryHelpDocPlayBook: + // OpenUrl("http://developer.blackberry.com/playbook/native/documentation/"); + // break; + case PackageCommands.cmdidBlackBerryHelpSamplesNative: + OpenUrl("http://developer.blackberry.com/native/sampleapps/"); + break; + //case PackageCommands.cmdidBlackBerryHelpSamplesCascades: + // OpenUrl("http://developer.blackberry.com/native/sampleapps/"); + // break; + //case PackageCommands.cmdidBlackBerryHelpSamplesPlayBook: + // OpenUrl("http://developer.blackberry.com/playbook/native/sampleapps/"); + // break; + case PackageCommands.cmdidBlackBerryHelpSamplesOpenSource: + OpenUrl("https://github.com/blackberry/VSPlugin"); + break; + case PackageCommands.cmdidBlackBerryHelpAbout: + { + var form = new AboutForm(); + form.ShowDialog(); + } + break; + default: + TraceLog.WarnLine("Unknown Help item requested"); + break; + } + } + + #endregion + + /// + /// Gets the currently selected NDK to build against. + /// + private NdkInfo ActiveNDK + { + get { return PackageViewModel.Instance.ActiveNDK; } + } + + /// + /// Gets the list of installed NDKs on the machine. + /// + private NdkInfo[] InstalledNDKs + { + get { return PackageViewModel.Instance.InstalledNDKs; } + } + + /// + /// Makes sure the NDK and runtime libraries are selected + /// and their paths are stored inside registry for build toolset. + /// + private void EnsureActiveNDK() + { + PackageViewModel.Instance.EnsureActiveNDK(); + PackageViewModel.Instance.EnsureActiveRuntime(); + } + + private void AddBlackBerryTargetPlatforms(object sender, EventArgs e) + { + var projects = DteHelper.GetProjects(_dte); + + if (projects == null || projects.Length == 0) + { + MessageBoxHelper.Show("Unable to add BlackBerry platform.", "Open a solution with Visual C++ projects", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + if (MessageBoxHelper.Show("Do you want to add BlackBerry target platform for all C/C++ projects?", null, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) + return; + + foreach (var project in projects) + { + _buildPlatformsManager.AddPlatforms(project); + } + + MessageBoxHelper.Show("You might now:\r\n * restart Visual Studio, as it has the 'deploy' option disabled\r\n * update the Author Information within the bar-descriptor.xml", "BlackBerry target have been added to solution configurations.", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + private void ImportBlackBerryProject(object sender, EventArgs e) + { + var form = new ImportProjectForm(); + + // configure dialog to display info about current solution: + form.AddTargetProjects(_dte.Solution); + + // ask for .cproject location: + if (form.UpdateSourceProject()) + { + // commit the list of found files: + if (form.ShowDialog() == DialogResult.OK) + { + // create new project/use existing and add files: + var project = form.FillProject(_dte); + if (project == null) + { + MessageBoxHelper.Show("Unable to create or access requested project, please try again with saved solution", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + MessageBoxHelper.Show(form.CopyFiles ? "All files has been copied" : null, "Project has been imported into: " + project.Name, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + } + + private void ShowTargetNavigator(object sender, EventArgs e) + { + ShowToolWindow(); + } + + /// + /// Shows the singleton tool window or creates new one. + /// + private T ShowToolWindow() where T : ToolWindowPane + { + var toolWindow = (T) FindToolWindow(typeof(T), 0, true); + + if (toolWindow == null || toolWindow.Frame == null) + throw new InvalidOperationException("Unable to create tool window of specified type"); + + // force the frame to be shown as MDI content window: + var frame = (IVsWindowFrame) toolWindow.Frame; + frame.SetProperty((int) __VSFPROPID.VSFPROPID_FrameMode, VSFRAMEMODE.VSFM_MdiChild); + ErrorHandler.ThrowOnFailure(frame.Show()); + + return toolWindow; + } + + #region IDisposable Implementation + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 + public void Dispose() + { + GC.SuppressFinalize(this); + Dispose(true); + } + + #endregion + + #region IDeviceDiscoveryService Implementation + + DeviceDefinition IDeviceDiscoveryService.FindDevice() + { + var dialog = new DeviceForm("Searching for BlackBerry device"); + if (dialog.ShowDialog() == DialogResult.OK) + { + return dialog.ToDevice(); + } + + return null; + } + + #endregion + + #region IAttachDiscoveryService Implementation + + private string FindMatchingProject(ProcessInfo process) + { + if (process != null) + { + foreach (Project project in _dte.Solution.Projects) + { + if (BuildPlatformsManager.IsBlackBerryProject(project)) + { + string outputPath; + if (IsMatchingProject(project, process, out outputPath)) + { + TraceLog.WarnLine("Suggesting executable path: \"{0}\"", outputPath); + return outputPath; + } + } + } + } + + return null; + } + + private static bool IsMatchingProject(Project project, ProcessInfo process, out string outputPath) + { + outputPath = ProjectHelper.GuessTargetFullName(project); + if (string.IsNullOrEmpty(outputPath) || !File.Exists(outputPath)) + { + outputPath = ProjectHelper.GetTargetFullName(project); + } + + if (!string.IsNullOrEmpty(outputPath)) + { + var name = Path.GetFileName(outputPath); + if (process != null && string.Compare(name, process.Name, StringComparison.OrdinalIgnoreCase) == 0) + { + return true; + } + } + + return false; + } + + string IAttachDiscoveryService.FindExecutable(ProcessInfo process) + { + // try to automatically select the project: + foreach (Project project in _dte.Solution.Projects) + { + if (BuildPlatformsManager.IsBlackBerryProject(project)) + { + string outputPath; + if (IsMatchingProject(project, process, out outputPath)) + { + if (File.Exists(outputPath)) + { + TraceLog.WarnLine("Suggesting executable path: \"{0}\"", outputPath); + return outputPath; + } + } + } + } + + // PH: HINT: this code will be for sure executed, when attaching to a process without any solution opened: + + // ask developer via any UI to point the executable (binary): + var form = new BinaryDiscoveryForm("Select Matching Target Process Binary"); + + foreach (Project project in _dte.Solution.Projects) + { + if (BuildPlatformsManager.IsBlackBerryProject(project)) + { + string outputPath; + if (IsMatchingProject(project, process, out outputPath)) + { + form.AddTarget(project, outputPath, true); + } + else + { + form.AddTarget(project, outputPath, false); + } + } + } + + form.AddCustomTarget("Custom executable"); + + if (form.ShowDialog() == DialogResult.OK) + { + return form.SelectedPath; + } + + return null; + } + + #endregion + } +} diff --git a/src_vs2012/Package/Components/BuildPlatformsManager.cs b/src_vs2012/Package/Components/BuildPlatformsManager.cs new file mode 100644 index 00000000..76ddbe53 --- /dev/null +++ b/src_vs2012/Package/Components/BuildPlatformsManager.cs @@ -0,0 +1,1307 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using BlackBerry.DebugEngine; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Helpers; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Services; +using BlackBerry.Package.Dialogs; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.Options; +using BlackBerry.Package.ViewModels; +using BlackBerry.Package.Wizards; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.CommandBars; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.VCProjectEngine; + +namespace BlackBerry.Package.Components +{ + /// + /// Manager class helpful in hijacking the Visual Studio's UI to initiate the build and deployment of BlackBerry project. + /// It exposes some detection mechanisms for external usages. + /// + internal sealed class BuildPlatformsManager + { + #region Internal Classes + + /// + /// Class carrying arguments required to attach to console logs for specified process. + /// + sealed class LogAttachRequest + { + /// + /// Init constructor. + /// + public LogAttachRequest(Project project, uint pid) + { + if (project == null) + throw new ArgumentNullException("project"); + + PID = pid; + Project = project; + } + + #region Properties + + /// + /// Gets the process ID to start capturing logs. + /// + public uint PID + { + get; + private set; + } + + public Project Project + { + get; + private set; + } + + #endregion + + /// + /// Issues request to attach to running process and capture output logs. + /// + public void Attach(DeviceDefinition device) + { + if (device == null) + throw new ArgumentNullException("device"); + + Targets.Connect(device, OnConnected); + } + + private void OnConnected(object sender, TargetConnectionEventArgs e) + { + if (e.Status == TargetStatus.Connected) + { + Targets.Unsubscribe(e.Device, OnConnected); + + var process = e.Client.SysInfoService.FindProcess(PID); + if (process != null) + { + Targets.Trace(e.Device, process, false); + } + else + { + TraceLog.WarnLine("Process to capture logs doesn't exist anymore."); + } + } + } + + /// + /// Creates new request to attach to output logs. + /// + public static LogAttachRequest Create(Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + // deployment was done, look for a file with run info: + // (HINT: this file is created by BBDeploy task, as a result of successful .bar file deployment and launch) + var runInfoFileName = ProjectHelper.GetFlagFileNameForRunInfo(project); + + if (!File.Exists(runInfoFileName)) + { + TraceLog.WarnLine("Unable to find 'runinfo' file to correctly capture logs."); + return null; + } + + var runInfo = File.ReadAllLines(runInfoFileName); + uint pid = 0; + + foreach (var info in runInfo) + { + if (info.StartsWith("pid=", StringComparison.OrdinalIgnoreCase)) + { + uint.TryParse(info.Substring(4), out pid); + } + } + + if (pid != 0) + { + return new LogAttachRequest(project, pid); + } + + TraceLog.WarnLine("Invalid PID inside 'runinfo' file to correctly capture logs."); + return null; + } + } + + #endregion + + private readonly DTE2 _dte; + + private List _buildThese; + private readonly List _filesToDelete; + private bool _hitPlay; + private int _amountOfProjects; + private bool _isDeploying; + private Project _startProject; + private bool _startDebugger; + private LogAttachRequest _currentAttachRequest; + + private BuildEvents _buildEvents; + private SolutionEvents _solutionEvents; + private CommandEvents _deploymentEvents; + private CommandEvents _eventsDebug; + private CommandEvents _eventsNoDebug; + private CommandEvents _eventsDebugContext; + + private bool _solutionOpened; + private int _openedBlackBerryProjects; + + private IServiceProvider _serviceProvider; + private ErrorManager _errorManager; + + private const string ConfigNameBlackBerry = "BlackBerry"; + private const string ToolbarNameStandard = "Standard"; + private const string SolutionConfigurationsName = "Solution Configurations"; + private const string SolutionPlatformsName = "Solution Platforms"; + private const string BarDescriptorFileName = "bar-descriptor.xml"; + private const string BarDescriptorTemplate = @"Shared\bar-descriptor.xml"; + + public event Action Navigate; + public event Action OpenSettingsPage; + + /// + /// Init constructor. + /// + public BuildPlatformsManager(DTE2 dte) + { + if (dte == null) + throw new ArgumentNullException("dte"); + + _dte = dte; + _filesToDelete = new List(); + } + + public void Initialize() + { + if (_buildEvents != null) + return; + + _serviceProvider = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider) _dte); + + // register for command events, when accessing build platforms: + _deploymentEvents = CommandHelper.Register(_dte, VSConstants.GUID_VSStandardCommandSet97, VSConstants.VSStd2KCmdID.SolutionPlatform, null, OnNewPlatform_AfterExecute); + //CommandHelper.Register(_dte, GuidList.guidVSDebugGroup, StandardCommands.cmdidDebugBreakatFunction, cmdNewFunctionBreakpoint_beforeExec, cmdNewFunctionBreakpoint_afterExec); + + ShowSolutionPlatformSelector(); + + // INFO: the references to returned objects must be stored and live as long, as the handlers are needed, + // since they are COM objects and will be automatically reclaimed on next GC.Collect(), causing handlers to be unsubscribed... + _eventsDebug = CommandHelper.Register(_dte, VSConstants.GUID_VSStandardCommandSet97, VSConstants.VSStd97CmdID.Start, StartDebugCommandEvents_BeforeExecute, null); + _eventsNoDebug = CommandHelper.Register(_dte, VSConstants.GUID_VSStandardCommandSet97, VSConstants.VSStd97CmdID.StartNoDebug, StartNoDebugCommandEvents_BeforeExecute, null); + _eventsDebugContext = CommandHelper.Register(_dte, VSConstants.VSStd2K, VSConstants.VSStd2KCmdID.PROJSTARTDEBUG, StartDebugCommandEvents_BeforeExecute, null); + + _buildEvents = _dte.Events.BuildEvents; + _buildEvents.OnBuildBegin += OnBuildBegin; + _buildEvents.OnBuildDone += OnDeploymentDoneAttachLogs; + + // to monitor, when to disable IntelliSense errors, + // TODO: however there is still one case not covered - when project is added as Win32 and manually platform is added and configuration converted co BlackBerry... + _solutionEvents = _dte.Events.SolutionEvents; + _solutionEvents.Opened += OnSolutionOpened; + _solutionEvents.AfterClosing += OnSolutionClosed; + _solutionEvents.ProjectAdded += OnProjectAdded; + _solutionEvents.ProjectRemoved += OnProjectRemoved; + + _errorManager = new ErrorManager(_serviceProvider, new Guid("{54340ee9-e59e-4ff1-8e5d-0370f700eaed}"), "BlackBerry Errors"); + + PackageViewModel.Instance.TargetsChanged += (s, e) => VerifyCommonErrors(); + } + + private void OnDeploymentDoneAttachLogs(vsBuildScope scope, vsBuildAction action) + { + if (action == vsBuildAction.vsBuildActionDeploy) + { + var project = GetActiveSolutionProject(_dte); + if (!_startDebugger && project != null) + { + // deployment was done, look for a file with run info: + _currentAttachRequest = LogAttachRequest.Create(project); + if (_currentAttachRequest != null) + { + ActivateOutputWindowPane("Debug"); + _currentAttachRequest.Attach(ActiveTarget); + } + } + } + } + + #region Properties + + /// + /// Gets the currently selected device all actions should be performed against. + /// + private DeviceDefinition ActiveDevice + { + get { return PackageViewModel.Instance.ActiveDevice; } + } + + /// + /// Gets the currently selected simulator all actions should be performed against. + /// + private DeviceDefinition ActiveSimulator + { + get { return PackageViewModel.Instance.ActiveSimulator; } + } + + /// + /// Gets the currently selected NDK to build against. + /// + private NdkInfo ActiveNDK + { + get { return PackageViewModel.Instance.ActiveNDK; } + } + + /// + /// Gets the currently selected runtime libraries of the device to debug against. + /// + private RuntimeInfo ActiveRuntime + { + get { return PackageViewModel.Instance.ActiveRuntime; } + } + + /// + /// Gets the active target, where the application will be deployed and run on. + /// + private DeviceDefinition ActiveTarget + { + get + { + if (_startProject != null && IsBlackBerryProject(_startProject)) + { + var projectArch = ProjectHelper.GetTargetArchitecture(_startProject); + var simulatorArch = DeviceDefinition.GetArchitecture(DeviceDefinitionType.Simulator); + if (string.Compare(projectArch, simulatorArch, StringComparison.OrdinalIgnoreCase) == 0) + return ActiveSimulator; + } + + // by default, try to run on a device: + return ActiveDevice; + } + } + + /// + /// Gets the list of all available target devices. + /// + private DeviceDefinition[] TargetDevices + { + get { return PackageViewModel.Instance.TargetDevices; } + } + + /// + /// Gets the list of installed NDKs on the machine. + /// + private NdkInfo[] InstalledNDKs + { + get { return PackageViewModel.Instance.InstalledNDKs; } + } + + #endregion + + /// + /// Terminate the manager. + /// + public void Close() + { + } + + private static Project GetActiveSolutionProject(DTE2 dte) + { + if (dte == null) + throw new ArgumentNullException("dte"); + + if (dte.ActiveSolutionProjects != null) + { + foreach (Project project in (Array) dte.ActiveSolutionProjects) + { + return project; + } + } + + return null; + } + + private static Project GetBuildStartupProject(DTE2 dte) + { + if (dte == null) + throw new ArgumentNullException("dte"); + + if (dte.Solution != null && dte.Solution.SolutionBuild != null && dte.Solution.SolutionBuild.StartupProjects != null) + { + foreach (string startupProject in (Array) dte.Solution.SolutionBuild.StartupProjects) + { + foreach (Project project in dte.Solution.Projects) + { + if (project.UniqueName == startupProject) + { + return project; + } + } + } + } + + return null; + } + + #region Managing IntelliSense Error Reporting + + /// + /// Checks, if BlackBerry-dedicated MSBuild platform has been installed. + /// + public static bool IsMSBuildPlatformInstalled + { + get + { + var buildTasksAssemblyPath = Path.Combine(ConfigDefaults.MSBuildVCTargetsPath, "Platforms", "BlackBerry", "BlackBerry.BuildTasks.dll"); + return File.Exists(buildTasksAssemblyPath); + } + } + + /// + /// Checks the current plugin and Visual Studio state for most common errors to minimize developer's frustration, why things are not working. + /// + public void VerifyCommonErrors() + { + _errorManager.Clear(); + + // check if appropriate platform exists and matches expected version: + var buildTasksAssemblyPath = Path.Combine(ConfigDefaults.MSBuildVCTargetsPath, "Platforms", "BlackBerry", "BlackBerry.BuildTasks.dll"); + if (!File.Exists(buildTasksAssemblyPath)) + { + _errorManager.Add(TaskErrorCategory.Error, "MSBuild \"BlackBerry\" build platform was not found. Building projects won't be possible at all. Visit " + ConfigDefaults.GithubProjectWikiInstallation + " [double-click] for details, how to install it.", OpenInstallationPage); + } + else + { + try + { + var installedVersion = AssemblyName.GetAssemblyName(buildTasksAssemblyPath).Version; + var expectedVersion = Assembly.GetExecutingAssembly().GetName().Version; + + // verify versions: + if (installedVersion.Major != expectedVersion.Major || installedVersion.Minor != expectedVersion.Minor || installedVersion.Build != expectedVersion.Build) + { + _errorManager.Add(TaskErrorCategory.Warning, "Invalid version of existing MSBuild \"BlackBerry\" build platform (installed: " + ToShortVersion(installedVersion) + ", expected: " + ToShortVersion(expectedVersion) + "). Some features might simply stop working. Visit " + ConfigDefaults.GithubProjectWikiInstallation + " [double-click] for details, how to upgrade it.", OpenInstallationPage); + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to determine version of MSBuild \"BlackBerry\" build platform"); + } + } + + // is Java detected? + if (string.IsNullOrEmpty(ConfigDefaults.JavaHome) || !Directory.Exists(ConfigDefaults.JavaHome)) + { + _errorManager.Add(TaskErrorCategory.Warning, "Java was not detected. Underlying BlackBerry tools might stop working. Specify one at \"BlackBerry -> Options -> General\" [double-click].", OpenGeneralSettings); + } + + // check, if any project is placed on incorrect location, not supported by underlying makefile system: + if (_dte != null && _dte.Solution != null && _dte.Solution.Projects.Count > 0) + { + foreach (Project project in _dte.Solution.Projects) + { + if (IsBlackBerryProject(project)) + { + // is path valid? + var projectPath = Path.GetDirectoryName(project.FullName); + if (!string.IsNullOrEmpty(projectPath) && !IsValidProjectPath(projectPath)) + { + _errorManager.Add(TaskErrorCategory.Warning, string.Concat("Project path: \"", projectPath, "\" is invalid and might lead to problems in underlying makefile system. Move the project to the one without spaces and non-ASCII characters."), project, null, OpenGeneralSettings); + } + + // is name valid? + var projectName = project.Name; + if (!string.IsNullOrEmpty(projectPath) && !IsValidProjectName(projectName)) + { + _errorManager.Add(TaskErrorCategory.Error, string.Concat("Project name: \"", projectName, "\" is invalid. Remove all spaces and non-ASCII characters."), project, null, OpenGeneralSettings); + } + } + } + } + + // check if any NDK is installed: + if (InstalledNDKs.Length == 0) + { + _errorManager.Add(TaskErrorCategory.Error, "Missing any BlackBerry NativeCore SDK. Compilation won't be possible at all. Add one on \"BlackBerry -> Options -> API-Levels\" [double-click] to be able to perform builds your applications.", OpenApiLevelSettings); + + if (string.IsNullOrEmpty(ConfigDefaults.NdkDirectory) || !Directory.Exists(ConfigDefaults.NdkDirectory)) + { + _errorManager.Add(TaskErrorCategory.Warning, "Customized NDK for Visual Studio (bbndk_vs) was not found. It won't be possible to automatically download new versions of BlackBerry NativeCore SDKs, simulators nor runtime-libraries for debugging. Visit " + ConfigDefaults.GithubProjectWikiInstallation + " [double-click] for details, how to install it.", OpenInstallationPage); + } + } + + // verify targets defined: + if (TargetDevices.Length == 0) + { + _errorManager.Add(TaskErrorCategory.Warning, "No target device or simulator is defined. Specify one on \"BlackBerry -> Options -> Targets\" [double-click] to be able to deploy and test your applications.", OpenTargetsSettings); + } + + // bring errors to front: + if (_errorManager.Count > 0) + { + _errorManager.Show(); + } + } + + /// + /// Checks if given path matches the makefile assumptions used to build the BlackBerry projects. + /// + private static bool IsValidProjectPath(string path) + { + if (string.IsNullOrEmpty(path)) + return false; + + return path.IndexOf(' ') < 0; + } + + /// + /// Checks if given project name matches the makefile assumptions used to build the BlackBerry projects. + /// + private static bool IsValidProjectName(string path) + { + if (string.IsNullOrEmpty(path)) + return false; + + return path.IndexOf(' ') < 0; + } + + private void OnProjectRemoved(Project project) + { + if (_solutionOpened) + { + if (IsBlackBerryProject(project)) + { + _openedBlackBerryProjects--; + UpdateIntelliSenseState(); + } + + VerifyCommonErrors(); + } + } + + private void OnProjectAdded(Project project) + { + if (_solutionOpened) + { + if (IsBlackBerryProject(project)) + { + _openedBlackBerryProjects++; + UpdateIntelliSenseState(); + } + + VerifyCommonErrors(); + } + } + + private void OnSolutionClosed() + { + _errorManager.Clear(); + + _solutionOpened = false; + _openedBlackBerryProjects = 0; + UpdateIntelliSenseState(); + VerifyCommonErrors(); + } + + private void OnSolutionOpened() + { + _solutionOpened = true; + _openedBlackBerryProjects = 0; + + foreach (Project project in _dte.Solution.Projects) + { + if (IsBlackBerryProject(project)) + { + _openedBlackBerryProjects++; + } + } + + UpdateIntelliSenseState(); + VerifyCommonErrors(); + } + + private static string ToShortVersion(Version v) + { + return string.Concat("v", v.Major, ".", v.Minor, ".", v.Build); + } + + private void OpenInstallationPage(object sender, EventArgs e) + { + var url = ConfigDefaults.GithubProjectWikiInstallation; + + if (Navigate != null) + { + Navigate(url); + } + else + { + DialogHelper.StartURL(url); + } + } + + private void RequestSettingsOpened(Type optionPageType) + { + if (OpenSettingsPage != null) + { + OpenSettingsPage(optionPageType); + } + } + + private void OpenGeneralSettings(object sender, EventArgs e) + { + RequestSettingsOpened(typeof(GeneralOptionPage)); + } + + public void OpenTargetsSettings(object sender, EventArgs e) + { + RequestSettingsOpened(typeof(TargetsOptionPage)); + } + + public void OpenApiLevelSettings(object sender, EventArgs e) + { + RequestSettingsOpened(typeof(ApiLevelOptionPage)); + } + + private void UpdateIntelliSenseState() + { + UpdateIntelliSenseState(_openedBlackBerryProjects != 0); + } + + /// + /// Enables or disables error reporting detected by IntelliSense at runtime. + /// Unfortunately, no idea for now, how to extend the IntelliSense with extra Qt syntax. + /// + private void UpdateIntelliSenseState(bool state) + { + var intelliPropertyGroup = _dte.Properties["TextEditor", "C/C++ Specific"]; + if (intelliPropertyGroup != null) + { + var intelliProperty = intelliPropertyGroup.Item("DisableErrorReporting"); + if (intelliProperty != null) + { + intelliProperty.Value = state; + } + } + } + + #endregion + + #region Managing Configurations + + /// + /// Solution Platform command is shown in the Standard toolbar by default with Visual C++ settings. Add the + /// command if not in the Standard toolbar. + /// + private void ShowSolutionPlatformSelector() + { + CommandBars commandBars = (CommandBars)_dte.CommandBars; + CommandBar standardCommandBar = commandBars[ToolbarNameStandard]; + + int pos = 0; + foreach (CommandBarControl cmd in standardCommandBar.Controls) + { + if (cmd.Caption == SolutionConfigurationsName) + pos = cmd.Index; + if (cmd.Caption == SolutionPlatformsName) + return; + } + + Command sp = null; + string expectedGuid = VSConstants.VSStd2K.ToString("B"); + const int expectedID = (int) VSConstants.VSStd2KCmdID.SolutionPlatform; + + foreach (Command command in _dte.Commands) + { + if (string.Compare(command.Guid, expectedGuid, StringComparison.OrdinalIgnoreCase) == 0 + && command.ID == expectedID) + { + sp = command; + break; + } + } + if (sp != null) + sp.AddControl(standardCommandBar, pos + 1); + } + + /// + /// Adds BlackBerry specific target platforms. + /// + public bool AddPlatforms(Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + try + { + AddBarDescriptorToProject(project); + project.ConfigurationManager.AddPlatform(ConfigNameBlackBerry, ConfigNameBlackBerry, true); + EnableDeploymentForSolutionPlatforms(); + + project.ConfigurationManager.DeletePlatform("Win32"); + project.ConfigurationManager.DeletePlatform("x64"); + project.ConfigurationManager.DeletePlatform("ARM"); + project.ConfigurationManager.DeleteConfigurationRow("Win32"); + project.ConfigurationManager.DeleteConfigurationRow("x64"); + project.ConfigurationManager.DeleteConfigurationRow("ARM"); + return true; + } + catch (Exception e) + { + TraceLog.WriteException(e); + return false; + } + finally + { + // update IntelliSense state: + OnSolutionOpened(); + } + } + + /// + /// Enable deployment feature for all BlackBerry projects. + /// + private void EnableDeploymentForSolutionPlatforms() + { + SolutionConfigurations solutionConfigurations = _dte.Solution.SolutionBuild.SolutionConfigurations; + foreach (SolutionConfiguration configuration in solutionConfigurations) + { + foreach (SolutionContext context in configuration.SolutionContexts) + { + if (context.PlatformName == ConfigNameBlackBerry) + { + context.ShouldDeploy = true; + } + } + } + } + + private void AddBarDescriptorToProject(Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + ProjectItem existingBarItem = project.ProjectItems.Item(BarDescriptorFileName); + if (existingBarItem == null) + { + TraceLog.WriteLine("Adding bar descriptor file to the project"); + + string projectFolder = Path.GetDirectoryName(project.FullName); + + // Remove directory used in previous versions of this plug-in. + if (!string.IsNullOrEmpty(project.FullName)) + { + if (!string.IsNullOrEmpty(projectFolder)) + { + string oldFolder = Path.Combine(projectFolder, project.Name + "_barDescriptor"); + if (Directory.Exists(oldFolder)) + { + try + { + Directory.Delete(oldFolder, true); + } + catch (Exception ex) + { + TraceLog.WriteException(ex); + } + } + } + } + + string templatePath = Path.Combine(PuppetMasterWizardEngine.WizardDataFolder, BarDescriptorTemplate); + string destination = string.IsNullOrEmpty(projectFolder) ? BarDescriptorFileName : Path.Combine(projectFolder, BarDescriptorFileName); + + var tokenProcessor = PuppetMasterWizardEngine.CreateTokenProcessor(project.Name, projectFolder, destination, null); + tokenProcessor.UntokenFile(templatePath, destination); + project.ProjectItems.AddFromFile(destination); + } + } + + #endregion + + #region Build Event Handlers + + /// + /// New Platform After Execution Event Handler. + /// + /// Command GUID. + /// Command ID. + /// Custom IN Object. + /// Custom OUT Object. + private void OnNewPlatform_AfterExecute(string guid, int id, object customIn, object customOut) + { + EnableDeploymentForSolutionPlatforms(); + } + + /// + /// New Function Breakpoint After Execution Event Handler. + /// + /// Command GUID. + /// Command ID. + /// Custom IN Object. + /// Custom OUT Object. + private void OnNewFunctionBreakpoint_AfterExecute(string guid, int id, object customIn, object customOut) + { + Breakpoint functionBP = _dte.Debugger.Breakpoints.Item(_dte.Debugger.Breakpoints.Count); + + if (functionBP != null) + { + if ((functionBP.FunctionColumnOffset != 1) || (functionBP.FunctionLineOffset != 1)) + { + MessageBoxHelper.Show("The breakpoint cannot be set. Function breakpoints are only supported on the first line.", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + functionBP.Delete(); + } + } + } + + /// + /// This event is fired only when user wants to build, rebuild or clean the project. + /// + /// Represents the scope of the build. + /// Represents the type of build action that is occurring, such as a build or a deploy action. + private void OnBuildBegin(vsBuildScope scope, vsBuildAction action) + { + if (IsBlackBerrySolution() && ActiveNDK == null) + { + if (InstalledNDKs.Length > 0) + { + var form = new MissingNdkInstalledForm(); + form.ShowDialog(); + } + else + { + MessageBoxHelper.Show("Project build is impossible as any BlackBerry NativeCore SDK was detected. Install or add existing one in \"BlackBerry -> Options -> API-Levels\" and try again.", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return; + } + + if (action == vsBuildAction.vsBuildActionBuild || action == vsBuildAction.vsBuildActionRebuildAll) + { + if (!_hitPlay && !_isDeploying) + { + // means that the "play" building and deploying process was cancelled before, so we have to disable the + // OnBuildDone event to avoid deploying in case user only wants to build. + _buildEvents.OnBuildDone -= OnBuildDone; + } + _hitPlay = false; + } + + PrepareFlagFilesForDeployment(); + } + + + /// + /// New Start Debug Command Events Before Execution Event Handler. Call the method responsible for building the app. + /// + /// Command GUID. + /// Command ID. + /// Custom IN Object. + /// Custom OUT Object. + /// Cancel the default execution of the command. + private void StartNoDebugCommandEvents_BeforeExecute(string guid, int id, object customIn, object customOut, ref bool cancelDefault) + { + TraceLog.WriteLine("BUILD: Start no Debug"); + _startDebugger = false; + cancelDefault = StartBuild(); + } + + /// + /// New Start Debug Command Events Before Execution Event Handler. Call the method responsible for building the app. + /// + /// Command GUID. + /// Command ID. + /// Custom IN Object. + /// Custom OUT Object. + /// Cancel the default execution of the command. + private void StartDebugCommandEvents_BeforeExecute(string guid, int id, object customIn, object customOut, ref bool cancelDefault) + { + TraceLog.WriteLine("BUILD: Start Debug"); + _startDebugger = true; + cancelDefault = StartBuild(); + } + + /// + /// This event is fired only when the build/rebuild/clean process ends. + /// + /// Represents the scope of the build. + /// Represents the type of build action that is occurring, such as a build or a deploy action. + private void OnBuildDone(vsBuildScope scope, vsBuildAction action) + { + switch (action) + { + case vsBuildAction.vsBuildActionBuild: + _amountOfProjects--; + if (_amountOfProjects == 0) + { + _buildEvents.OnBuildDone -= OnBuildDone; + Built(); + } + break; + + case vsBuildAction.vsBuildActionDeploy: + _buildEvents.OnBuildDone -= OnBuildDone; + _isDeploying = false; + Deployed(); + break; + } + } + + private bool StartBuild() + { + if (DebugEngineStatus.IsRunning) + { + TraceLog.WriteLine("BUILD: StartBuild - Debugger running"); + + // Disable the override of F5 (this allows the debugged process to continue execution) + return false; + } + + if (!IsBlackBerryConfigurationActive()) + { + TraceLog.WriteLine("BUILD: StartBuild - not a BlackBerry project"); + + // Disable the override of F5 (this allows the debugged process to continue execution) + return false; + } + + try + { + _buildThese = new List(); + _startProject = GetBuildStartupProject(_dte); + + foreach (String startupProject in (Array) _dte.Solution.SolutionBuild.StartupProjects) + { + foreach (Project project in _dte.Solution.Projects) + { + if (project.UniqueName == startupProject) + { + _buildThese.Add(project.FullName); + } + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex); + } + + ActivateOutputWindowPane("Build"); + BuildBar(); + return true; + } + + private void ActivateOutputWindowPane(string build) + { + try + { + // create a reference to the Output Window and window pane: + OutputWindow ow = _dte.ToolWindows.OutputWindow; + + // and activate it: + var outputWindowPane = ow.OutputWindowPanes.Item(build); + outputWindowPane.Activate(); + } + catch + { + } + } + + /// + /// Identify the projects to be build and start the build process. + /// + /// TRUE if successful, FALSE if not. + private bool BuildBar() + { + TraceLog.WriteLine("BUILD: BuildBar"); + + bool success = true; + try + { + if (_buildThese.Count != 0) + { + _buildEvents.OnBuildDone += OnBuildDone; + + try + { + Solution2 solution = (Solution2)_dte.Solution; + _hitPlay = true; + _amountOfProjects = _buildThese.Count; // OnBuildDone will call build() only after receiving "amountOfProjects" events + foreach (string projectName in _buildThese) + { + solution.SolutionBuild.BuildProject(solution.SolutionBuild.ActiveConfiguration.Name, projectName, false); + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex); + success = false; + } + } + else + { + success = false; + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex); + success = false; + } + + return success; + } + + private static void DeleteFlagFile(string fileName) + { + try + { + if (File.Exists(fileName)) + { + File.Delete(fileName); + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to delete flag file (\"{0}\")", fileName); + } + } + + /// + /// Verify if the build process was successful. If so, start deploying the app. + /// + private void Built() + { + TraceLog.WriteLine("BUILD: Built"); + + // when build succeeded: + if (_dte.Solution.SolutionBuild.LastBuildInfo == 0) + { + foreach (string startupProject in (Array) _dte.Solution.SolutionBuild.StartupProjects) + { + foreach (SolutionContext sc in _dte.Solution.SolutionBuild.ActiveConfiguration.SolutionContexts) + { + var project = _dte.Solution.Item(sc.ProjectName); + var debugNativeFlagFileName = ProjectHelper.GetFlagFileNameForDebugNative(project); + + DeleteFlagFile(debugNativeFlagFileName); + + if (sc.ProjectName == startupProject) + { + sc.ShouldDeploy = true; + + if (_startDebugger) + { + // write file to flag the deploy task that it should use the -debugNative option: + File.WriteAllText(debugNativeFlagFileName, "Use -debugNative.\r\n"); + _buildEvents.OnBuildDone += OnBuildDone; + } + } + else + { + sc.ShouldDeploy = false; + } + } + } + + // OK, project builds, so make sure there is a connection to the device, to speed-up further debugging: + var target = ActiveTarget; + if (target != null) + { + Targets.Connect(ActiveTarget, ConfigDefaults.SshPublicKeyPath, ConfigDefaults.SshPrivateKeyPath, null); + } + + _isDeploying = true; + _dte.Solution.SolutionBuild.Deploy(true); + } + + OnWholeBuildDone(); + } + + private void OnWholeBuildDone() + { + // remove all temporary flag files created during build: + foreach (var fileName in _filesToDelete) + { + DeleteFlagFile(fileName); + } + + _filesToDelete.Clear(); + if (_buildThese != null) + { + _buildThese.Clear(); + } + _startProject = null; + _startDebugger = false; + _isDeploying = false; + _hitPlay = false; + } + + /// + /// Writes down all flag files used by MSBuild. + /// NOTE: somehow passing values via environment variables seems not to work, + /// that's why we use local files deleted automatically after the build/deployment is completed. + /// + private void PrepareFlagFilesForDeployment() + { + var developer = PackageViewModel.Instance.Developer; + bool shouldSaveLocally = developer != null && !developer.IsPasswordSaved && !string.IsNullOrEmpty(developer.CskPassword); + + // store CSK-password inside a local flag-file, in case dev doesn't want to store it persistently: + foreach (Project project in _dte.Solution.Projects) + { + try + { + var cskPasswordFileName = ProjectHelper.GetFlagFileNameForCSKPassword(project); + + // remove old value: + DeleteFlagFile(cskPasswordFileName); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to delete deployment temporary flag files (project: \"{0}\")", project != null ? project.Name : "unknown"); + } + } + + if (shouldSaveLocally) + { + foreach (Project project in (Array) _dte.Solution.SolutionBuild.StartupProjects) + { + WriteCskPassword(project, developer); + } + + foreach (Project project in (Array) _dte.ActiveSolutionProjects) + { + WriteCskPassword(project, developer); + } + } + } + + private void WriteCskPassword(Project project, DeveloperDefinition developer) + { + try + { + var cskPasswordFileName = ProjectHelper.GetFlagFileNameForCSKPassword(project); + + // write CSK-password, if not stored persistently inside registry, to let signing process to succeed: + File.WriteAllText(cskPasswordFileName, GlobalHelper.Encrypt(developer.CskPassword)); + _filesToDelete.Add(cskPasswordFileName); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to write deployment temporary flag files (project: \"{0}\")", project != null ? project.Name : "unknown"); + } + } + + /// + /// Get the process ID and launch an executable using the BlackBerry debug engine. + /// + private void Deployed() + { + TraceLog.WriteLine("BUILD: Deployed"); + + if (_startProject == null) + { + MessageBoxHelper.Show("Unable to determine the executable to start.", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + var executablePath = ProjectHelper.GetTargetFullName(_startProject); + var ndk = ActiveNDK; + var device = ActiveTarget; + var runtime = ActiveRuntime; + + if (ndk == null) + { + MessageBoxHelper.Show("Missing NDK selected. Install any and mark as active using BlackBerry menu options.", null, + MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (device == null) + { + MessageBoxHelper.Show("Missing target device selected. Define an IP, password and mark a device as active using BlackBerry menu options.", null, + MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + // if the path to binary is invalid GDB might have problems with loading correct symbols; + // maybe try to guess better or ask developer, what is wrong, why the project doesn't define it correctly + // (possible causes: dev is using any kind of makefile and plugin can't detect the outcomes automatically): + if (_startDebugger) + { + if (string.IsNullOrEmpty(executablePath) || !File.Exists(executablePath)) + { + executablePath = ProjectHelper.GuessTargetFullName(_startProject); + + if (string.IsNullOrEmpty(executablePath) || !File.Exists(executablePath)) + { + var attachDiscoveryService = (IAttachDiscoveryService) Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IAttachDiscoveryService)); + Debug.Assert(attachDiscoveryService != null, "Invalid project references (make sure VisualStudio.Shell.dll is not references, as it duplicates the Package definition from VisualStudio.Shell..dll)"); + + // ask the developer to specify the path: + executablePath = attachDiscoveryService.FindExecutable(null); + } + } + + if (LaunchDebugTarget(_startProject.Name, ndk, device, runtime, null, executablePath)) + { + ActivateOutputWindowPane("Debug"); + } + } + } + + /// + /// Launch an executable using the BlackBerry debug engine. + /// + /// Process ID in string format or the binary name for debugger to attach to. + /// TRUE if successful, False if not. + private bool LaunchDebugTarget(string pidOrTargetAppName, NdkInfo ndk, DeviceDefinition target, RuntimeInfo runtime, string sshPublicKeyPath, string executablePath) + { + TraceLog.WriteLine("BUILD: Starting debugger (\"{0}\", \"{1}\")", pidOrTargetAppName, executablePath); + + IVsDebugger dbg = (IVsDebugger) _serviceProvider.GetService(typeof(SVsShellDebugger)); + IVsUIShell shell = (IVsUIShell) _serviceProvider.GetService(typeof(SVsUIShell)); + + VsDebugTargetInfo info = new VsDebugTargetInfo(); + info.cbSize = (uint)Marshal.SizeOf(info); + info.dlo = DEBUG_LAUNCH_OPERATION.DLO_CreateProcess; + info.bstrExe = executablePath; // The executable path + + // Store all debugger arguments in a string + var nvc = new Dictionary(); + nvc["pidOrName"] = pidOrTargetAppName; + if (!string.IsNullOrEmpty(sshPublicKeyPath)) + { + nvc["sshKeyPath"] = sshPublicKeyPath; + } + CollectionHelper.AppendDevice(nvc, target); + CollectionHelper.AppendNDK(nvc, ndk.ToDefinition()); + if (runtime != null) + { + CollectionHelper.AppendRuntime(nvc, runtime.ToDefinition()); + } + info.bstrArg = CollectionHelper.Serialize(nvc); + + info.bstrRemoteMachine = null; // debug locally + info.fSendStdoutToOutputWindow = 0; // Let stdout stay with the application. + info.clsidCustom = new Guid(AD7Engine.DebugEngineGuid); // Set the launching engine as the BlackBerry debug-engine + info.grfLaunch = 0; + + IntPtr pInfo = Marshal.AllocCoTaskMem((int)info.cbSize); + Marshal.StructureToPtr(info, pInfo, false); + + try + { + int result = dbg.LaunchDebugTargets(1, pInfo); + if (result != VSConstants.S_OK) + { + string message; + shell.GetErrorInfo(out message); + message = message.Trim(); + + TraceLog.WriteLine("LaunchDebugTargets: " + message); + MessageBoxHelper.Show(message, null, MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + } + finally + { + if (pInfo != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(pInfo); + } + } + + return true; + } + + #endregion + + /// + /// Check to see if current solution is configured with a BlackBerry configurations. + /// + public bool IsBlackBerrySolution() + { + if (_dte.Solution != null) + { + var projects = _dte.Solution.Projects; + if (projects != null) + { + foreach (Project project in projects) + { + if (IsBlackBerryProject(project)) + return true; + } + } + } + + return false; + } + + /// + /// Checks if specified project supports build for BlackBerry device or simulator. + /// + public static bool IsBlackBerryProject(Project project) + { + if (project == null || !(project.Object is VCProject)) + return false; + + try + { + var platformName = project.ConfigurationManager != null && project.ConfigurationManager.ActiveConfiguration != null + ? project.ConfigurationManager.ActiveConfiguration.PlatformName + : null; + if (platformName == ConfigNameBlackBerry) + return true; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to determine type of native project"); + } + + return false; + } + + public bool IsBlackBerryConfigurationActive() + { + if (_dte.Solution != null && _dte.Solution.SolutionBuild != null && _dte.Solution.SolutionBuild.ActiveConfiguration != null) + { + foreach (SolutionContext context in _dte.Solution.SolutionBuild.ActiveConfiguration.SolutionContexts) + { + string platformName = context.PlatformName; + if (platformName == ConfigNameBlackBerry) + return true; + } + } + + return false; + } + } +} diff --git a/src_vs2012/Package/Components/ErrorManager.cs b/src_vs2012/Package/Components/ErrorManager.cs new file mode 100644 index 00000000..516acd04 --- /dev/null +++ b/src_vs2012/Package/Components/ErrorManager.cs @@ -0,0 +1,112 @@ +using System; +using EnvDTE; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace BlackBerry.Package.Components +{ + /// + /// Manager class to add dynamically BlackBerry plugin-owned errors and warnings. + /// + internal sealed class ErrorManager + { + private readonly IServiceProvider _serviceProvider; + private readonly ErrorListProvider _provider; + + /// + /// Init constructor. + /// + public ErrorManager(IServiceProvider serviceProvider, Guid guid, string name) + { + if (serviceProvider == null) + throw new ArgumentNullException("serviceProvider"); + + _serviceProvider = serviceProvider; + _provider = new ErrorListProvider(serviceProvider); + _provider.ProviderGuid = guid; + _provider.ProviderName = name; + } + + #region Properties + + public int Count + { + get { return _provider.Tasks.Count; } + } + + #endregion + + /// + /// Add item to the error-list. + /// + public void Add(TaskErrorCategory category, string message, EventHandler navigateHandler) + { + Add(category, message, null, null, navigateHandler); + } + + /// + /// Add item to the error-list. + /// + public void Add(TaskErrorCategory category, string message, Project project, ProjectItem projectItem, EventHandler navigateHandler) + { + if (string.IsNullOrEmpty(message)) + throw new ArgumentNullException("message"); + + var task = new ErrorTask(); + task.ErrorCategory = category; + task.Text = message; + task.IsTextEditable = false; + task.HierarchyItem = GetHierarchyItem(project); + + if (projectItem != null) + { + task.Document = projectItem.FileNames[0]; + } + + if (navigateHandler != null) + { + task.Navigate += navigateHandler; + } + + _provider.Tasks.Add(task); + } + + /// + /// Gets hierarchy item matching specified project. Accepts null values. + /// + private IVsHierarchy GetHierarchyItem(Project project) + { + if (project == null) + return null; + + var solution = _serviceProvider.GetService(typeof(SVsSolution)) as IVsSolution; + + if (solution == null) + return null; + + IVsHierarchy result; + ErrorHandler.ThrowOnFailure(solution.GetProjectOfUniqueName(project.UniqueName, out result)); + return result; + } + + /// + /// Remove all errors. + /// + public void Clear() + { + for (int i = _provider.Tasks.Count - 1; i >= 0; i--) + { + _provider.Tasks.RemoveAt(i); + } + } + + /// + /// Brings the Errors window to front. + /// + public void Show() + { + _provider.Show(); + } + } +} diff --git a/src_vs2012/Package/Components/LogManager.cs b/src_vs2012/Package/Components/LogManager.cs new file mode 100644 index 00000000..217d8eec --- /dev/null +++ b/src_vs2012/Package/Components/LogManager.cs @@ -0,0 +1,117 @@ +using System; +using System.Diagnostics; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.Package.Diagnostics; + +namespace BlackBerry.Package.Components +{ + /// + /// Manager class to record all logs of specified categories into persistent storage. + /// It also limits the number of files, if required. + /// + internal static class LogManager + { + private static string _path; + private static string[] _categories; + private static PersistentTraceListener _recorder; + + /// + /// Initializes recording logs. + /// + public static void Initialize(string path, int limitLogs, params string[] categories) + { + _path = path; + _categories = categories; + + MountLogRecorder(); + Cleanup(limitLogs); + } + + /// + /// Switches to another folder or disables existing recorder. + /// + public static void Update(string path, int limitLogs) + { + if (string.CompareOrdinal(path, _path) != 0) + { + _path = path; + + // remove the log recorder from old location and setup in new location: + UnmountLogRecorder(); + MountLogRecorder(); + } + + Cleanup(limitLogs); + } + + /// + /// Removes existing log recorder. + /// + private static void UnmountLogRecorder() + { + if (_recorder != null) + { + string name = _recorder.FileName; + + Trace.Listeners.Remove(_recorder); + _recorder.Dispose(); + _recorder = null; + + TraceLog.WriteLine("Removed log recorder: \"{0}\"", name); + } + } + + /// + /// Creates new log recorder. + /// + private static void MountLogRecorder() + { + if (_recorder == null && !string.IsNullOrEmpty(_path)) + { + try + { + _recorder = new PersistentTraceListener(_path, true, _categories); + Trace.Listeners.Add(_recorder); + TraceLog.WriteLine("Created log recorder: \"{0}\"", _recorder.FileName); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to setup persistent logger"); + } + } + } + + /// + /// Removes unnecessary log files, if their count is above the limit. + /// + private static void Cleanup(int limit) + { + if (limit > 0 && Directory.Exists(_path)) + { + try + { + var files = Directory.GetFiles(_path, PersistentTraceListener.Prefix + "*"); // get all file logs + if (files.Length > limit) + { + for (int i = 0; i < files.Length - limit; i++) + { + try + { + File.Delete(files[i]); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to delete file: \"{0}\"", files[i]); + } + } + } + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to clean up log folder"); + } + } + } + } +} diff --git a/src_vs2012/Package/Components/ProjectFolderTree.cs b/src_vs2012/Package/Components/ProjectFolderTree.cs new file mode 100644 index 00000000..d020b81a --- /dev/null +++ b/src_vs2012/Package/Components/ProjectFolderTree.cs @@ -0,0 +1,273 @@ +using System; +using System.Collections.Generic; +using System.IO; +using EnvDTE; +using Microsoft.VisualStudio.VCProjectEngine; + +namespace BlackBerry.Package.Components +{ + /// + /// Class to simplify adding files into the project. It places them into correct filter, that maps local directory structure. + /// All missing items on the relative path are automatically created. + /// + sealed class ProjectFolderTree + { + public const string FilterNameAssets = "assets"; + public const string FilterNameSourceFiles = "src"; + public const string FilterNameConfig = "config"; + public const string FilterNameTranslations = "trans"; + public const string DefaultFilters = FilterNameAssets + ";" + FilterNameConfig + ";" + FilterNameSourceFiles + ";" + FilterNameTranslations; + + private readonly VCProject _vcProject; + private readonly string _projectFolder; + private VCFilter _sourceFilter; + private VCFilter _assetFilter; + private VCFilter _translationFilter; + private Dictionary _filters; + + /// + /// Init constructor. + /// + public ProjectFolderTree(Project project, bool createDefaultFolders) + { + if (project == null) + throw new ArgumentNullException("project"); + + _vcProject = project.Object as VCProject; + if (_vcProject == null) + throw new ArgumentOutOfRangeException("project", "This is not Visual C++ project"); + + _projectFolder = Path.GetDirectoryName(_vcProject.ProjectFile) + Path.DirectorySeparatorChar; + Refresh(createDefaultFolders); + } + + /// + /// Init constructor. + /// + public ProjectFolderTree(VCProject project, bool createDefaultFolders) + { + if (project == null) + throw new ArgumentNullException("project"); + + _vcProject = project; + _projectFolder = Path.GetDirectoryName(_vcProject.ProjectFile) + Path.DirectorySeparatorChar; + Refresh(createDefaultFolders); + } + + /// + /// Refreshes info about existing top-level filters. + /// + public void Refresh(bool createNonExisting) + { + IVCCollection filters = _vcProject.Filters; + + _filters = new Dictionary(); + _sourceFilter = filters.Item("Source Files"); + if (_sourceFilter == null && createNonExisting) + { + _sourceFilter = CreateFilters(FilterNameSourceFiles, _vcProject)[0]; + } + + _assetFilter = filters.Item("Assets"); + if (_assetFilter == null && createNonExisting) + { + _assetFilter = CreateFilters(FilterNameAssets, _vcProject)[0]; + } + + _translationFilter = filters.Item("Translations"); + if (_translationFilter == null && createNonExisting) + { + _translationFilter = CreateFilters(FilterNameTranslations, _vcProject)[0]; + } + + // default directories already point to specific filters to shorten the path: + if (_sourceFilter != null) + { + _filters.Add("src", _sourceFilter); + _filters.Add("sources", _sourceFilter); + _filters.Add("code", _sourceFilter); + _filters.Add("classes", _sourceFilter); + } + + if (_assetFilter != null) + { + _filters.Add("asset", _assetFilter); + _filters.Add("assets", _assetFilter); + _filters.Add("data", _assetFilter); + } + + if (_translationFilter != null) + { + _filters.Add("translations", _translationFilter); + } + } + + /// + /// Adds new file into the project. It will try to evaluate the relativePath based on the project's location. + /// + public void AddFile(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + AddFile(path, path.StartsWith(_projectFolder, StringComparison.OrdinalIgnoreCase) ? path.Substring(_projectFolder.Length) : null); + } + + /// + /// Adds new file into the project. + /// + public void AddFile(string fullPath, string relativePath) + { + if (string.IsNullOrEmpty(fullPath)) + throw new ArgumentNullException("fullPath"); + + var filter = GetFileFilter(relativePath); + if (filter != null) + { + if (filter.CanAddFile(fullPath)) + { + filter.AddFile(fullPath); + } + } + else + { + if (_vcProject.CanAddFile(fullPath)) + { + _vcProject.AddFile(fullPath); + } + } + } + + private VCFilter GetFileFilter(string relativePath) + { + var dir = Path.GetDirectoryName(relativePath); + return GetFolderFilter(dir); + } + + private VCFilter GetFolderFilter(string relativePath) + { + // should be added directly into the project? + if (string.IsNullOrEmpty(relativePath)) + return null; + + VCFilter filter; + if (_filters.TryGetValue(relativePath, out filter)) + return filter; + + var parent = Path.GetDirectoryName(relativePath); + var parentFilter = GetFolderFilter(parent); + if (parentFilter == null) + return null; + + var name = Path.GetFileName(relativePath); + IVCCollection filters = parentFilter.Filters; + VCFilter currentFilter = filters.Item(name); + + if (currentFilter == null) + { + currentFilter = parentFilter.AddFilter(name); + } + + _filters[relativePath] = currentFilter; + return currentFilter; + } + + /// + /// Creates basic set of filters inside the project. + /// + public VCFilter[] CreateFilters(string filtersDefinition) + { + var result = CreateFilters(filtersDefinition, _vcProject); + + if (result != null) + { + Refresh(false); + } + + return result; + } + + /// + /// Creates basic set of filters inside the project. + /// + public static VCFilter[] CreateFilters(string filtersDefinition, Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + var vcProject = project.Object as VCProject; + if (vcProject != null) + { + return CreateFilters(filtersDefinition, vcProject); + } + + return null; + } + + /// + /// Creates basic set of filters inside the project. + /// + public static VCFilter[] CreateFilters(string filtersDefinition, VCProject vcProject) + { + if (string.IsNullOrEmpty(filtersDefinition)) + return null; + + var result = new List(); + + foreach (var filterName in filtersDefinition.Split(';', ',', ' ')) + { + if (string.Compare(filterName, "sources", StringComparison.OrdinalIgnoreCase) == 0) + { + VCFilter filter = FindOrAddFilter("Source Files", vcProject); + filter.Filter = "cpp;c;cc;cxx;asm"; + result.Add(filter); + } + + if (string.Compare(filterName, "headers", StringComparison.OrdinalIgnoreCase) == 0) + { + VCFilter filter = FindOrAddFilter("Header Files", vcProject); + filter.Filter = "h;hpp;hxx;hm;def;inl;inc"; + result.Add(filter); + } + + if (string.Compare(filterName, FilterNameSourceFiles, StringComparison.OrdinalIgnoreCase) == 0) + { + VCFilter filter = FindOrAddFilter("Source Files", vcProject); + filter.Filter = "cpp;c;cc;cxx;asm;h;hpp;hxx;hm;def;inl;inc"; + result.Add(filter); + } + + if (string.Compare(filterName, FilterNameAssets, StringComparison.OrdinalIgnoreCase) == 0) + { + VCFilter filter = FindOrAddFilter("Assets", vcProject); + filter.Filter = "qml;js;qmljs;jpg;png;gif;bmp;ico;amd;wav;mp3;mp4"; + result.Add(filter); + } + + if (string.Compare(filterName, FilterNameConfig, StringComparison.OrdinalIgnoreCase) == 0) + { + VCFilter filter = FindOrAddFilter("Config Files", vcProject); + filter.Filter = "pri;pro;mk;properties;project;cproject;xml;xsd;bat;cmd;ps;ps1"; + result.Add(filter); + } + + if (string.Compare(filterName, FilterNameTranslations, StringComparison.OrdinalIgnoreCase) == 0) + { + VCFilter filter = FindOrAddFilter("Translations", vcProject); + filter.Filter = "ts;qm"; + result.Add(filter); + } + } + + return result.ToArray(); + } + + private static VCFilter FindOrAddFilter(string name, VCProject vcProject) + { + IVCCollection filters = vcProject.Filters; + VCFilter filter = filters.Item(name); + + return filter ?? vcProject.AddFilter(name); + } + } +} diff --git a/src_vs2012/Package/Diagnostics/BlackBerryPaneTraceListener.cs b/src_vs2012/Package/Diagnostics/BlackBerryPaneTraceListener.cs new file mode 100644 index 00000000..4e4e7827 --- /dev/null +++ b/src_vs2012/Package/Diagnostics/BlackBerryPaneTraceListener.cs @@ -0,0 +1,108 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using BlackBerry.NativeCore.Diagnostics; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; + +namespace BlackBerry.Package.Diagnostics +{ + /// + /// Pane panel, that listens for BlackBerry-only trace log messages and displays on UI. + /// + internal sealed class BlackBerryPaneTraceListener : TraceListener + { + public const string SName = "BlackBerry Pane Trace Listener"; + + private readonly IVsOutputWindowPane _outputPane; + private readonly TimeTracker _time; + private readonly string _category; + + /// + /// Init constructor. + /// + public BlackBerryPaneTraceListener(string title, string category, bool printTime, IVsOutputWindow outputWindow, Guid paneGuid) + : base(SName) + { + if (string.IsNullOrEmpty(category)) + throw new ArgumentNullException("category"); + if (outputWindow == null) + throw new ArgumentNullException("outputWindow"); + + _category = category; + _outputPane = FindOrCreatePane(title, outputWindow, paneGuid); + if (printTime) + _time = new TimeTracker(); + } + + private static IVsOutputWindowPane FindOrCreatePane(string title, IVsOutputWindow outputWindow, Guid paneGuid) + { + IVsOutputWindowPane pane; + + // try to retrieve existing pane: + if (outputWindow.GetPane(ref paneGuid, out pane) == VSConstants.S_OK) + { + return pane; + } + + // if there is no particular pane, create new instance: + Marshal.ThrowExceptionForHR(outputWindow.CreatePane(ref paneGuid, title, 1, 0)); + return outputWindow.GetPane(ref paneGuid, out pane) == VSConstants.S_OK ? pane : null; + } + + /// + /// Brings this pane to front. + /// + public void Activate() + { + _outputPane.Activate(); + } + + #region TraceListener Overrides + + public override void Write(string message) + { + // do nothing, only want to capture filtered-by-category messages + } + + public override void WriteLine(string message) + { + // do nothing, only want to capture filtered-by-category messages + } + + public override void Write(string message, string category) + { + // print only messages of designated category: + if (string.CompareOrdinal(category, _category) != 0) + return; + + var timeString = _time != null ? _time.GetCurrent() : null; + if (!string.IsNullOrEmpty(timeString)) + ErrorHandler.ThrowOnFailure(_outputPane.OutputStringThreadSafe(timeString)); + + ErrorHandler.ThrowOnFailure(_outputPane.OutputStringThreadSafe(message)); + } + + public override void WriteLine(string message, string category) + { + // print only messages of designated category: + if (string.CompareOrdinal(category, _category) != 0) + return; + + try + { + var timeString = _time != null ? _time.GetCurrentAndReset() : null; + if (!string.IsNullOrEmpty(timeString)) + ErrorHandler.ThrowOnFailure(_outputPane.OutputStringThreadSafe(timeString)); + + ErrorHandler.ThrowOnFailure(_outputPane.OutputStringThreadSafe(message)); + ErrorHandler.ThrowOnFailure(_outputPane.OutputStringThreadSafe(Environment.NewLine)); + } + catch + { + } + } + + #endregion + } +} diff --git a/src_vs2012/Package/Diagnostics/PersistentTraceListener.cs b/src_vs2012/Package/Diagnostics/PersistentTraceListener.cs new file mode 100644 index 00000000..a0c7d689 --- /dev/null +++ b/src_vs2012/Package/Diagnostics/PersistentTraceListener.cs @@ -0,0 +1,142 @@ +using System; +using System.Diagnostics; +using System.IO; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.Package.Diagnostics +{ + /// + /// Trace log listener class that stores all logs from given categories into newly created file inside specified folder. + /// + internal sealed class PersistentTraceListener : TraceListener + { + /// + /// Prefix of the log file. + /// + public const string Prefix = "vsndk_log_"; + + private StreamWriter _output; + private readonly TimeTracker _time; + private readonly string[] _categories; + + /// + /// Init constructor. + /// It already creates the file. + /// + public PersistentTraceListener(string outputFolder, bool printTime, params string[] categories) + { + if (string.IsNullOrEmpty(outputFolder)) + throw new ArgumentNullException("outputFolder"); + + FileName = GenerateOutputFileName(outputFolder); + _categories = categories; + if (printTime) + _time = new TimeTracker(); + + _output = File.CreateText(FileName); + } + + #region Properties + + public string FileName + { + get; + private set; + } + + #endregion + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_output != null) + { + _output.Dispose(); + _output = null; + } + } + + base.Dispose(disposing); + } + + private static string GenerateFileName(int iteration) + { + return string.Concat(Prefix, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"), iteration > 0 ? "_" : string.Empty, iteration > 0 ? iteration.ToString() : string.Empty, ".txt"); + } + + private static string GenerateOutputFileName(string outputFolder) + { + if (string.IsNullOrEmpty(outputFolder)) + throw new ArgumentNullException("outputFolder"); + + if (!Directory.Exists(outputFolder)) + { + Directory.CreateDirectory(outputFolder); + } + + // try to come up with a file name, that doesn't exist yet in specified folder: + int iteration = 0; + string name; + do + { + name = Path.Combine(outputFolder, GenerateFileName(iteration)); + iteration++; + } while (File.Exists(name)); + + return name; + } + + private bool IsExpectedCategory(string category) + { + if (_categories == null || _categories.Length == 0) + return true; + + for (int i = 0; i < _categories.Length; i++) + { + if (string.CompareOrdinal(category, _categories[i]) == 0) + return true; + } + + return false; + } + + public override void Write(string message) + { + // do nothing, only want to capture filtered-by-category messages + } + + public override void WriteLine(string message) + { + // do nothing, only want to capture filtered-by-category messages + } + + public override void Write(string message, string category) + { + // print only messages of designated category: + if (_output == null || !IsExpectedCategory(category)) + return; + + var timeString = _time != null ? _time.GetCurrent() : null; + if (!string.IsNullOrEmpty(timeString)) + _output.Write(timeString); + + _output.Write(message); + _output.Flush(); + } + + public override void WriteLine(string message, string category) + { + // print only messages of designated category: + if (_output == null || !IsExpectedCategory(category)) + return; + + var timeString = _time != null ? _time.GetCurrentAndReset() : null; + if (!string.IsNullOrEmpty(timeString)) + _output.Write(timeString); + + _output.WriteLine(message); + _output.Flush(); + } + } +} diff --git a/src_vs2012/Package/Dialogs/AboutForm.Designer.cs b/src_vs2012/Package/Dialogs/AboutForm.Designer.cs new file mode 100644 index 00000000..6a97ba1a --- /dev/null +++ b/src_vs2012/Package/Dialogs/AboutForm.Designer.cs @@ -0,0 +1,265 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bttOK = new System.Windows.Forms.Button(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label1 = new System.Windows.Forms.Label(); + this.pictureLogo = new System.Windows.Forms.PictureBox(); + this.lblVersion = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.linkBugTracker = new System.Windows.Forms.LinkLabel(); + this.linkSourceCode = new System.Windows.Forms.LinkLabel(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.linkAuthor = new System.Windows.Forms.LinkLabel(); + this.linkTwitter = new System.Windows.Forms.LinkLabel(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureLogo)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttOK.Location = new System.Drawing.Point(519, 260); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 3; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + // + // panel1 + // + this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel1.BackColor = System.Drawing.Color.White; + this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel1.Controls.Add(this.label1); + this.panel1.Controls.Add(this.pictureLogo); + this.panel1.Location = new System.Drawing.Point(-11, -12); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(623, 125); + this.panel1.TabIndex = 0; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.label1.Location = new System.Drawing.Point(151, 80); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(453, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Native Plugin for Visual Studio"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // pictureLogo + // + this.pictureLogo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pictureLogo.BackColor = System.Drawing.Color.Transparent; + this.pictureLogo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; + this.pictureLogo.Location = new System.Drawing.Point(22, 23); + this.pictureLogo.Name = "pictureLogo"; + this.pictureLogo.Size = new System.Drawing.Size(582, 73); + this.pictureLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.pictureLogo.TabIndex = 0; + this.pictureLogo.TabStop = false; + // + // lblVersion + // + this.lblVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.lblVersion.AutoSize = true; + this.lblVersion.Location = new System.Drawing.Point(9, 265); + this.lblVersion.Name = "lblVersion"; + this.lblVersion.Size = new System.Drawing.Size(47, 13); + this.lblVersion.TabIndex = 2; + this.lblVersion.Text = "[version]"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(16, 35); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(509, 13); + this.label2.TabIndex = 0; + this.label2.Text = "This is open-source software. We encourage you to take part in its further develo" + + "pment and improvements."; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(16, 59); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(165, 13); + this.label3.TabIndex = 1; + this.label3.Text = "Report bugs and feature requests"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(16, 83); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(165, 13); + this.label4.TabIndex = 3; + this.label4.Text = "Full source code is also available "; + // + // linkBugTracker + // + this.linkBugTracker.AutoSize = true; + this.linkBugTracker.Location = new System.Drawing.Point(179, 59); + this.linkBugTracker.Name = "linkBugTracker"; + this.linkBugTracker.Size = new System.Drawing.Size(31, 13); + this.linkBugTracker.TabIndex = 2; + this.linkBugTracker.TabStop = true; + this.linkBugTracker.Text = "here."; + this.linkBugTracker.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkBugTracker_LinkClicked); + // + // linkSourceCode + // + this.linkSourceCode.AutoSize = true; + this.linkSourceCode.Location = new System.Drawing.Point(174, 83); + this.linkSourceCode.Name = "linkSourceCode"; + this.linkSourceCode.Size = new System.Drawing.Size(31, 13); + this.linkSourceCode.TabIndex = 4; + this.linkSourceCode.TabStop = true; + this.linkSourceCode.Text = "here."; + this.linkSourceCode.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkSourceCode_LinkClicked); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.linkBugTracker); + this.groupBox1.Controls.Add(this.linkAuthor); + this.groupBox1.Controls.Add(this.linkTwitter); + this.groupBox1.Controls.Add(this.linkSourceCode); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Location = new System.Drawing.Point(12, 119); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(582, 135); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(251, 108); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(304, 13); + this.label6.TabIndex = 8; + this.label6.Text = ", who has improved most of features and fixed gazillion of bugs."; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(16, 108); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(89, 13); + this.label5.TabIndex = 5; + this.label5.Text = "Special honors to"; + // + // linkAuthor + // + this.linkAuthor.AutoSize = true; + this.linkAuthor.Location = new System.Drawing.Point(105, 108); + this.linkAuthor.Name = "linkAuthor"; + this.linkAuthor.Size = new System.Drawing.Size(78, 13); + this.linkAuthor.TabIndex = 6; + this.linkAuthor.TabStop = true; + this.linkAuthor.Text = "Paweł Hofman"; + this.linkAuthor.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkAuthor_LinkClicked); + // + // linkTwitter + // + this.linkTwitter.AutoSize = true; + this.linkTwitter.Location = new System.Drawing.Point(182, 108); + this.linkTwitter.Name = "linkTwitter"; + this.linkTwitter.Size = new System.Drawing.Size(72, 13); + this.linkTwitter.TabIndex = 7; + this.linkTwitter.TabStop = true; + this.linkTwitter.Text = "@CodeTitans"; + this.linkTwitter.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkTwitter_LinkClicked); + // + // AboutForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttOK; + this.ClientSize = new System.Drawing.Size(606, 295); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.lblVersion); + this.Controls.Add(this.panel1); + this.Controls.Add(this.bttOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About"; + this.panel1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.pictureLogo)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.PictureBox pictureLogo; + private System.Windows.Forms.Label lblVersion; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.LinkLabel linkBugTracker; + private System.Windows.Forms.LinkLabel linkSourceCode; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.LinkLabel linkAuthor; + private System.Windows.Forms.LinkLabel linkTwitter; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/AboutForm.cs b/src_vs2012/Package/Dialogs/AboutForm.cs new file mode 100644 index 00000000..0a81c0e2 --- /dev/null +++ b/src_vs2012/Package/Dialogs/AboutForm.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class AboutForm : Form + { + public AboutForm() + { + InitializeComponent(); + pictureLogo.Image = LoadLogoImage(); + lblVersion.Text = LoadVersion(); + } + + private Image LoadLogoImage() + { + var resources = Assembly.GetExecutingAssembly().GetManifestResourceNames(); + string logoResourceName = FindLogoResource(resources); + + // and load logo image: + if (!string.IsNullOrEmpty(logoResourceName)) + { + using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(logoResourceName)) + { + if (stream != null) + { + return new Bitmap(stream); + } + } + } + + return null; + } + + private static string FindLogoResource(IEnumerable resources) + { + if (resources == null) + return null; + + foreach (var name in resources) + { + if (name.EndsWith(".Logo.png")) + return name; + } + + return null; + } + + private string LoadVersion() + { + var name = new AssemblyName(Assembly.GetExecutingAssembly().FullName); + return "Version: v" + name.Version; + } + + private void linkSourceCode_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL(ConfigDefaults.GithubProjectSourceCode); + } + + private void linkBugTracker_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL(ConfigDefaults.GithubProjectIssues); + } + + private void linkAuthor_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL(ConfigDefaults.GithubProjectAuthor); + } + + private void linkTwitter_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL(ConfigDefaults.GithubProjectAuthorTwitter); + } + } +} diff --git a/src/VSNDK.Package/Signing/Browser.resx b/src_vs2012/Package/Dialogs/AboutForm.resx similarity index 100% rename from src/VSNDK.Package/Signing/Browser.resx rename to src_vs2012/Package/Dialogs/AboutForm.resx diff --git a/src_vs2012/Package/Dialogs/AddLocalNdkForm.Designer.cs b/src_vs2012/Package/Dialogs/AddLocalNdkForm.Designer.cs new file mode 100644 index 00000000..f5487227 --- /dev/null +++ b/src_vs2012/Package/Dialogs/AddLocalNdkForm.Designer.cs @@ -0,0 +1,267 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class AddLocalNdkForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bttCancel = new System.Windows.Forms.Button(); + this.bttOK = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label6 = new System.Windows.Forms.Label(); + this.cmbFamilyType = new System.Windows.Forms.ComboBox(); + this.bttBrowseTarget = new System.Windows.Forms.Button(); + this.bttBrowseHost = new System.Windows.Forms.Button(); + this.txtVersion = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.txtTargetPath = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.txtHostPath = new System.Windows.Forms.TextBox(); + this.txtName = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.bttClear = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(587, 240); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 3; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.Location = new System.Drawing.Point(506, 240); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 2; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + this.bttOK.Click += new System.EventHandler(this.bttOK_Click); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.cmbFamilyType); + this.groupBox1.Controls.Add(this.bttBrowseTarget); + this.groupBox1.Controls.Add(this.bttBrowseHost); + this.groupBox1.Controls.Add(this.txtVersion); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.txtTargetPath); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.txtHostPath); + this.groupBox1.Controls.Add(this.txtName); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(650, 222); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Properties"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(18, 182); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(34, 13); + this.label6.TabIndex = 11; + this.label6.Text = "Type:"; + // + // cmbFamilyType + // + this.cmbFamilyType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbFamilyType.FormattingEnabled = true; + this.cmbFamilyType.Location = new System.Drawing.Point(106, 179); + this.cmbFamilyType.Name = "cmbFamilyType"; + this.cmbFamilyType.Size = new System.Drawing.Size(121, 21); + this.cmbFamilyType.TabIndex = 12; + // + // bttBrowseTarget + // + this.bttBrowseTarget.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttBrowseTarget.Location = new System.Drawing.Point(564, 123); + this.bttBrowseTarget.Name = "bttBrowseTarget"; + this.bttBrowseTarget.Size = new System.Drawing.Size(75, 23); + this.bttBrowseTarget.TabIndex = 8; + this.bttBrowseTarget.Text = "Browse..."; + this.bttBrowseTarget.UseVisualStyleBackColor = true; + this.bttBrowseTarget.Click += new System.EventHandler(this.bttBrowseTarget_Click); + // + // bttBrowseHost + // + this.bttBrowseHost.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttBrowseHost.Location = new System.Drawing.Point(564, 91); + this.bttBrowseHost.Name = "bttBrowseHost"; + this.bttBrowseHost.Size = new System.Drawing.Size(75, 23); + this.bttBrowseHost.TabIndex = 5; + this.bttBrowseHost.Text = "Browse..."; + this.bttBrowseHost.UseVisualStyleBackColor = true; + this.bttBrowseHost.Click += new System.EventHandler(this.bttBrowseHost_Click); + // + // txtVersion + // + this.txtVersion.Location = new System.Drawing.Point(106, 150); + this.txtVersion.Name = "txtVersion"; + this.txtVersion.Size = new System.Drawing.Size(100, 20); + this.txtVersion.TabIndex = 10; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(18, 153); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(45, 13); + this.label5.TabIndex = 9; + this.label5.Text = "Version:"; + // + // txtTargetPath + // + this.txtTargetPath.Location = new System.Drawing.Point(106, 120); + this.txtTargetPath.Name = "txtTargetPath"; + this.txtTargetPath.Size = new System.Drawing.Size(452, 20); + this.txtTargetPath.TabIndex = 7; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(18, 64); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(38, 13); + this.label4.TabIndex = 1; + this.label4.Text = "Name:"; + // + // txtHostPath + // + this.txtHostPath.Location = new System.Drawing.Point(106, 91); + this.txtHostPath.Name = "txtHostPath"; + this.txtHostPath.Size = new System.Drawing.Size(452, 20); + this.txtHostPath.TabIndex = 4; + // + // txtName + // + this.txtName.Location = new System.Drawing.Point(106, 61); + this.txtName.Name = "txtName"; + this.txtName.Size = new System.Drawing.Size(335, 20); + this.txtName.TabIndex = 2; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(18, 94); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(57, 13); + this.label3.TabIndex = 3; + this.label3.Text = "Host Path:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(18, 123); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(66, 13); + this.label2.TabIndex = 6; + this.label2.Text = "Target Path:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(18, 31); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(558, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Specify the location of a local NDK and name it uniquely. Use Browse buttons belo" + + "w, to automate the whole process."; + // + // bttClear + // + this.bttClear.Location = new System.Drawing.Point(12, 240); + this.bttClear.Name = "bttClear"; + this.bttClear.Size = new System.Drawing.Size(75, 23); + this.bttClear.TabIndex = 1; + this.bttClear.Text = "&Clear"; + this.bttClear.UseVisualStyleBackColor = true; + this.bttClear.Click += new System.EventHandler(this.bttClear_Click); + // + // AddLocalNdkForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(674, 275); + this.Controls.Add(this.bttClear); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.bttCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AddLocalNdkForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "New Custom NDK"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttBrowseTarget; + private System.Windows.Forms.Button bttBrowseHost; + private System.Windows.Forms.TextBox txtVersion; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox txtTargetPath; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox txtHostPath; + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.ComboBox cmbFamilyType; + private System.Windows.Forms.Button bttClear; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/AddLocalNdkForm.cs b/src_vs2012/Package/Dialogs/AddLocalNdkForm.cs new file mode 100644 index 00000000..6620698c --- /dev/null +++ b/src_vs2012/Package/Dialogs/AddLocalNdkForm.cs @@ -0,0 +1,173 @@ +using System; +using System.IO; +using System.Windows.Forms; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.Model.Integration; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class AddLocalNdkForm : Form + { + public AddLocalNdkForm() + { + InitializeComponent(); + + // fill in the combo-box with types: + cmbFamilyType.Items.Clear(); + AddItem(DeviceFamilyType.Tablet); + AddItem(DeviceFamilyType.Phone); + cmbFamilyType.SelectedIndex = 1; + } + + #region Properties + + public string NdkName + { + get { return txtName.Text; } + set { txtName.Text = value; } + } + + public string NdkTargetPath + { + get { return txtTargetPath.Text; } + set { txtTargetPath.Text = value; } + } + + public string NdkHostPath + { + get { return txtHostPath.Text; } + set { txtHostPath.Text = value; } + } + + public Version NdkVersion + { + get + { + if (string.IsNullOrEmpty(txtVersion.Text) || txtVersion.Text.IndexOf('.') < 0) + return null; + + try + { + return new Version(txtVersion.Text); + } + catch + { + return null; + } + } + set { txtVersion.Text = value != null ? value.ToString() : string.Empty; } + } + + public DeviceFamilyType NdkType + { + get { return cmbFamilyType.SelectedIndex == 0 ? DeviceFamilyType.Tablet : DeviceFamilyType.Phone; } + set { cmbFamilyType.SelectedIndex = value == DeviceFamilyType.Tablet ? 0 : 1; } + } + + internal NdkInfo NewNdk + { + get; + private set; + } + + #endregion + + private void AddItem(DeviceFamilyType type) + { + cmbFamilyType.Items.Add(new ComboBoxItem(type.ToString(), type)); + } + + private void bttBrowseHost_Click(object sender, EventArgs e) + { + UpdateByPathSelection(txtHostPath); + } + + private void bttBrowseTarget_Click(object sender, EventArgs e) + { + UpdateByPathSelection(txtTargetPath); + } + + private void UpdateByPathSelection(TextBox sourceControl) + { + var folder = DialogHelper.BrowseForFolder(null, "Specify target-path, host-path or the root folder of those two"); + + if (!string.IsNullOrEmpty(folder)) + { + var ndk = NdkInfo.Scan(folder); + + if (ndk == null) + { + MessageBoxHelper.Show("Specified folder is not a valid NDK root", folder, MessageBoxButtons.OK, MessageBoxIcon.Error); + sourceControl.Text = folder; + } + else + { + if (string.IsNullOrEmpty(NdkName)) + NdkName = ndk.Name; + if (string.IsNullOrEmpty(NdkHostPath)) + NdkHostPath = ndk.HostPath; + if (string.IsNullOrEmpty(NdkTargetPath)) + NdkTargetPath = ndk.TargetPath; + if (string.IsNullOrEmpty(txtVersion.Text)) + NdkVersion = ndk.Version; + NdkType = ndk.Type; + } + } + } + + private void bttOK_Click(object sender, EventArgs e) + { + // verify input data: + if (NdkVersion == null) + { + MessageBoxHelper.Show("Incorrect field value", "Version", MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = txtVersion; + return; + } + + if (string.IsNullOrEmpty(NdkHostPath) || !Directory.Exists(NdkHostPath)) + { + MessageBoxHelper.Show("Incorrect path or doesn't exist, no way to set it as an NDK root", "Host Path", MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = txtHostPath; + return; + } + + if (string.IsNullOrEmpty(NdkTargetPath) || !Directory.Exists(NdkTargetPath)) + { + MessageBoxHelper.Show("Incorrect path or doesn't exist, no way to set it as an NDK root", "Host Target", MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = txtHostPath; + return; + } + + // create result + NewNdk = new NdkInfo(null, NdkName, NdkVersion, NdkHostPath, NdkTargetPath, NdkType); + var existingIndex = PackageViewModel.Instance.IndexOfInstalled(NewNdk); + var existingNDK = existingIndex >= 0 ? PackageViewModel.Instance.InstalledNDKs[existingIndex] : null; + + if (existingNDK != null) + { + if (MessageBoxHelper.Show("Are you sure, you want to add it?\r\nIt won't probably show up to select as duplicates are ignored, when populating lists.", + "Configuration duplicates \"" + existingNDK.Name + "\"", + MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) + { + NewNdk = null; + return; + } + } + + DialogResult = DialogResult.OK; + Close(); + } + + private void bttClear_Click(object sender, EventArgs e) + { + NdkName = string.Empty; + NdkHostPath = string.Empty; + NdkTargetPath = string.Empty; + NdkVersion = null; + NdkType = DeviceFamilyType.Phone; + } + } +} diff --git a/src_vs2012/VSNDK.Package/Signing/Browser.resx b/src_vs2012/Package/Dialogs/AddLocalNdkForm.resx similarity index 100% rename from src_vs2012/VSNDK.Package/Signing/Browser.resx rename to src_vs2012/Package/Dialogs/AddLocalNdkForm.resx diff --git a/src_vs2012/Package/Dialogs/BinaryDiscoveryForm.Designer.cs b/src_vs2012/Package/Dialogs/BinaryDiscoveryForm.Designer.cs new file mode 100644 index 00000000..6fe2d11b --- /dev/null +++ b/src_vs2012/Package/Dialogs/BinaryDiscoveryForm.Designer.cs @@ -0,0 +1,163 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class BinaryDiscoveryForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttOpen = new System.Windows.Forms.Button(); + this.txtPath = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.cmbProjects = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.bttOK = new System.Windows.Forms.Button(); + this.bttCancel = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttOpen); + this.groupBox1.Controls.Add(this.txtPath); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.cmbProjects); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(507, 104); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Available Outputs"; + // + // bttOpen + // + this.bttOpen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttOpen.Location = new System.Drawing.Point(450, 58); + this.bttOpen.Name = "bttOpen"; + this.bttOpen.Size = new System.Drawing.Size(40, 23); + this.bttOpen.TabIndex = 4; + this.bttOpen.Text = "..."; + this.bttOpen.UseVisualStyleBackColor = true; + this.bttOpen.Click += new System.EventHandler(this.bttOpen_Click); + // + // txtPath + // + this.txtPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPath.Location = new System.Drawing.Point(69, 60); + this.txtPath.Name = "txtPath"; + this.txtPath.Size = new System.Drawing.Size(375, 20); + this.txtPath.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(20, 63); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(32, 13); + this.label2.TabIndex = 2; + this.label2.Text = "Path:"; + // + // cmbProjects + // + this.cmbProjects.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cmbProjects.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbProjects.FormattingEnabled = true; + this.cmbProjects.Location = new System.Drawing.Point(69, 26); + this.cmbProjects.Name = "cmbProjects"; + this.cmbProjects.Size = new System.Drawing.Size(287, 21); + this.cmbProjects.TabIndex = 1; + this.cmbProjects.SelectionChangeCommitted += new System.EventHandler(this.cmbProjects_SelectionChangeCommitted); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(20, 29); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Project:"; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.Location = new System.Drawing.Point(363, 122); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 1; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + this.bttOK.Click += new System.EventHandler(this.bttOK_Click); + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(444, 122); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 2; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // BinaryDiscoveryForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(531, 157); + this.Controls.Add(this.bttCancel); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "BinaryDiscoveryForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.TextBox txtPath; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox cmbProjects; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button bttOpen; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/BinaryDiscoveryForm.cs b/src_vs2012/Package/Dialogs/BinaryDiscoveryForm.cs new file mode 100644 index 00000000..275988e5 --- /dev/null +++ b/src_vs2012/Package/Dialogs/BinaryDiscoveryForm.cs @@ -0,0 +1,119 @@ +using System; +using System.IO; +using System.Windows.Forms; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.Model.Integration; +using EnvDTE; + +namespace BlackBerry.Package.Dialogs +{ + /// + /// Dialog to let to select a value from a predefined non-editable set. + /// By default used to display a set of projects and optionally 'custom...' item. + /// + internal partial class BinaryDiscoveryForm : Form + { + public BinaryDiscoveryForm(string title) + { + InitializeComponent(); + Text = title; + } + + #region Property + + public string SelectedPath + { + get { return txtPath.Text; } + } + + #endregion + + /// + /// Adds a project, that will be a read-only item with predefined outputPath as result. + /// + public void AddTarget(Project project, string outputPath, bool isSelected) + { + if (project == null) + throw new ArgumentNullException("project"); + + var item = new ComboBoxItem(project.Name, outputPath ?? ""); + int index = cmbProjects.Items.Add(item); + + if (isSelected) + { + cmbProjects.SelectedIndex = index; + RefreshUI(); + } + } + + /// + /// Adds a custom item, that will let the user specify any value. + /// + public void AddCustomTarget(string title) + { + if (string.IsNullOrEmpty(title)) + throw new ArgumentNullException("title"); + + var item = new ComboBoxItem(title, null); + int index = cmbProjects.Items.Add(item); + + if (cmbProjects.SelectedIndex < 0) + { + cmbProjects.SelectedIndex = index; + ActiveControl = txtPath; + RefreshUI(); + } + } + + private void cmbProjects_SelectionChangeCommitted(object sender, EventArgs e) + { + RefreshUI(); + } + + private void bttOpen_Click(object sender, EventArgs e) + { + var form = DialogHelper.OpenAnyFile("Locate executable with matching debug symbols"); + + if (form.ShowDialog() == DialogResult.OK) + { + txtPath.Text = form.FileName; + } + } + + private void RefreshUI() + { + var item = cmbProjects.SelectedItem as ComboBoxItem; + + if (item != null) + { + txtPath.Text = (string)item.Tag; + txtPath.Enabled = item.Tag == null; + bttOpen.Enabled = item.Tag == null; + } + } + + private void bttOK_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(SelectedPath)) + { + if (MessageBoxHelper.Show("Specifying an empty path will cause it to be ignored.\r\nYou won't be able to set a breakpoint in your application.\r\n\r\nContinue?", null, + MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) + { + return; + } + } + + if (!File.Exists(SelectedPath)) + { + if (MessageBoxHelper.Show("Specified binary doesn't exist. This path will be ignored.\r\nYou won't be able to set a breakpoint in your application.\r\n\r\nContinue?", null, + MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) + { + return; + } + } + + DialogResult = DialogResult.OK; + Close(); + } + } +} diff --git a/src_vs2013/VSNDK.Package/Signing/Browser.resx b/src_vs2012/Package/Dialogs/BinaryDiscoveryForm.resx similarity index 100% rename from src_vs2013/VSNDK.Package/Signing/Browser.resx rename to src_vs2012/Package/Dialogs/BinaryDiscoveryForm.resx diff --git a/src_vs2012/Package/Dialogs/CachedAuthorForm.Designer.cs b/src_vs2012/Package/Dialogs/CachedAuthorForm.Designer.cs new file mode 100644 index 00000000..f192d73d --- /dev/null +++ b/src_vs2012/Package/Dialogs/CachedAuthorForm.Designer.cs @@ -0,0 +1,189 @@ +namespace BlackBerry.Package.Dialogs +{ + partial class CachedAuthorForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CachedAuthorForm)); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttLoad = new System.Windows.Forms.Button(); + this.bttClear = new System.Windows.Forms.Button(); + this.txtID = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.txtName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.bttOK = new System.Windows.Forms.Button(); + this.bttCancel = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(399, 50); + this.label1.TabIndex = 0; + this.label1.Text = resources.GetString("label1.Text"); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttLoad); + this.groupBox1.Controls.Add(this.bttClear); + this.groupBox1.Controls.Add(this.txtID); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.txtName); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Location = new System.Drawing.Point(15, 62); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(396, 119); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Publisher"; + // + // bttLoad + // + this.bttLoad.Location = new System.Drawing.Point(157, 80); + this.bttLoad.Name = "bttLoad"; + this.bttLoad.Size = new System.Drawing.Size(152, 23); + this.bttLoad.TabIndex = 4; + this.bttLoad.Text = "Load from &debug-token..."; + this.bttLoad.UseVisualStyleBackColor = true; + this.bttLoad.Click += new System.EventHandler(this.bttLoad_Click); + // + // bttClear + // + this.bttClear.Location = new System.Drawing.Point(315, 80); + this.bttClear.Name = "bttClear"; + this.bttClear.Size = new System.Drawing.Size(75, 23); + this.bttClear.TabIndex = 5; + this.bttClear.Text = "C&lear"; + this.bttClear.UseVisualStyleBackColor = true; + this.bttClear.Click += new System.EventHandler(this.bttClear_Click); + // + // txtID + // + this.txtID.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtID.Location = new System.Drawing.Point(82, 54); + this.txtID.Name = "txtID"; + this.txtID.Size = new System.Drawing.Size(308, 20); + this.txtID.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(16, 57); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(50, 13); + this.label3.TabIndex = 2; + this.label3.Text = "Identifier:"; + // + // txtName + // + this.txtName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtName.Location = new System.Drawing.Point(82, 23); + this.txtName.Name = "txtName"; + this.txtName.Size = new System.Drawing.Size(308, 20); + this.txtName.TabIndex = 1; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(16, 26); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(38, 13); + this.label2.TabIndex = 0; + this.label2.Text = "Name:"; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttOK.Location = new System.Drawing.Point(249, 187); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 2; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(330, 187); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 3; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // CachedAuthorForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(423, 222); + this.Controls.Add(this.bttCancel); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CachedAuthorForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Cached Publisher Summary"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttLoad; + private System.Windows.Forms.Button bttClear; + private System.Windows.Forms.TextBox txtID; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.Button bttCancel; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/CachedAuthorForm.cs b/src_vs2012/Package/Dialogs/CachedAuthorForm.cs new file mode 100644 index 00000000..1e2bcba4 --- /dev/null +++ b/src_vs2012/Package/Dialogs/CachedAuthorForm.cs @@ -0,0 +1,94 @@ +using System.IO; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Dialogs +{ + /// + /// Dialog that let developer to specify publisher data, placed automatically in bar-descriptor.xml, when new project is created. + /// + public sealed partial class CachedAuthorForm : Form + { + private DebugTokenInfoRunner _debugTokenInfoRunner; + + /// + /// Init constructor. + /// + public CachedAuthorForm(string title, AuthorInfo info) + { + InitializeComponent(); + + if (!string.IsNullOrEmpty(title)) + { + Text = title; + } + + txtID.Text = info != null ? info.ID : null; + txtName.Text = info != null ? info.Name : null; + } + + /// + /// Gets the author info input on UI. + /// + public AuthorInfo ToAuthor() + { + if (string.IsNullOrWhiteSpace(txtID.Text) && string.IsNullOrWhiteSpace(txtName.Text)) + { + return null; + } + + return new AuthorInfo(txtID.Text.Trim(), txtName.Text.Trim()); + } + + private void bttClear_Click(object sender, System.EventArgs e) + { + txtID.Text = null; + txtName.Text = null; + } + + private void bttLoad_Click(object sender, System.EventArgs e) + { + // is running... + if (_debugTokenInfoRunner != null) + return; + + var form = DialogHelper.OpenBarFile("Select debug token", ConfigDefaults.DataDirectory); + if (form.ShowDialog() == DialogResult.OK) + { + if (!File.Exists(form.FileName)) + { + MessageBoxHelper.Show("Unable to locate the debug-token file", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + TraceLog.WarnLine("Unable to locate debug-token: \"{0}\"", form.FileName); + return; + } + + _debugTokenInfoRunner = new DebugTokenInfoRunner(form.FileName); + _debugTokenInfoRunner.Dispatcher = EventDispatcher.From(this); + _debugTokenInfoRunner.Finished += DebugTokenInfoLoaded; + _debugTokenInfoRunner.ExecuteAsync(); + } + } + + private void DebugTokenInfoLoaded(object sender, ToolRunnerEventArgs e) + { + var debugToken = _debugTokenInfoRunner.DebugToken; + _debugTokenInfoRunner = null; + + if (e.IsSuccessfull && debugToken != null && debugToken.Author != null) + { + txtName.Text = debugToken.Author.Name; + txtID.Text = debugToken.Author.ID; + } + else + { + // notify about the error: + MessageBoxHelper.Show("Unable to load author info from specified debug token", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + TraceLog.WarnLine("Unable to load info from debug-token"); + } + } + } +} diff --git a/src_vs2012/Package/Dialogs/CachedAuthorForm.resx b/src_vs2012/Package/Dialogs/CachedAuthorForm.resx new file mode 100644 index 00000000..753f77d5 --- /dev/null +++ b/src_vs2012/Package/Dialogs/CachedAuthorForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + This is info about the author of the application (known also as Publisher or Vendor). It is automatically put inside bar-descriptor.xml file, when new project is created. Also it is automatically updated, whenever you create or load debug token BAR file. + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/CertificateDetailsForm.Designer.cs b/src_vs2012/Package/Dialogs/CertificateDetailsForm.Designer.cs new file mode 100644 index 00000000..829cdc97 --- /dev/null +++ b/src_vs2012/Package/Dialogs/CertificateDetailsForm.Designer.cs @@ -0,0 +1,341 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class CertificateDetailsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + if (disposing) + { + if (_runner != null) + { + _runner.Dispose(); + _runner = null; + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.txtPath = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.bttShow = new System.Windows.Forms.Button(); + this.txtName = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.bttClose = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label9 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.txtMD5 = new System.Windows.Forms.TextBox(); + this.txtSHA1 = new System.Windows.Forms.TextBox(); + this.txtSerialNumber = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.txtValidTo = new System.Windows.Forms.TextBox(); + this.txtValidFrom = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.txtIssuer = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.txtAlias = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.txtPath); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.bttShow); + this.groupBox1.Controls.Add(this.txtName); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(528, 98); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "File Details"; + // + // txtPath + // + this.txtPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPath.Location = new System.Drawing.Point(95, 55); + this.txtPath.Name = "txtPath"; + this.txtPath.ReadOnly = true; + this.txtPath.Size = new System.Drawing.Size(330, 20); + this.txtPath.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(16, 60); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(32, 13); + this.label2.TabIndex = 2; + this.label2.Text = "Path:"; + // + // bttShow + // + this.bttShow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttShow.Location = new System.Drawing.Point(431, 55); + this.bttShow.Name = "bttShow"; + this.bttShow.Size = new System.Drawing.Size(75, 23); + this.bttShow.TabIndex = 1; + this.bttShow.Text = "&Show..."; + this.bttShow.UseVisualStyleBackColor = true; + this.bttShow.Click += new System.EventHandler(this.bttShow_Click); + // + // txtName + // + this.txtName.Location = new System.Drawing.Point(95, 29); + this.txtName.Name = "txtName"; + this.txtName.ReadOnly = true; + this.txtName.Size = new System.Drawing.Size(135, 20); + this.txtName.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(16, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Name:"; + // + // bttClose + // + this.bttClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttClose.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttClose.Location = new System.Drawing.Point(465, 341); + this.bttClose.Name = "bttClose"; + this.bttClose.Size = new System.Drawing.Size(75, 23); + this.bttClose.TabIndex = 2; + this.bttClose.Text = "&Close"; + this.bttClose.UseVisualStyleBackColor = true; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.label9); + this.groupBox2.Controls.Add(this.label8); + this.groupBox2.Controls.Add(this.label7); + this.groupBox2.Controls.Add(this.txtMD5); + this.groupBox2.Controls.Add(this.txtSHA1); + this.groupBox2.Controls.Add(this.txtSerialNumber); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Controls.Add(this.txtValidTo); + this.groupBox2.Controls.Add(this.txtValidFrom); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.txtIssuer); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.txtAlias); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Location = new System.Drawing.Point(12, 116); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(528, 219); + this.groupBox2.TabIndex = 3; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Attributes"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(16, 183); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(33, 13); + this.label9.TabIndex = 13; + this.label9.Text = "MD5:"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(16, 157); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(38, 13); + this.label8.TabIndex = 12; + this.label8.Text = "SHA1:"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(16, 131); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(74, 13); + this.label7.TabIndex = 11; + this.label7.Text = "Serial number:"; + // + // txtMD5 + // + this.txtMD5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtMD5.Location = new System.Drawing.Point(95, 180); + this.txtMD5.Name = "txtMD5"; + this.txtMD5.ReadOnly = true; + this.txtMD5.Size = new System.Drawing.Size(411, 20); + this.txtMD5.TabIndex = 10; + // + // txtSHA1 + // + this.txtSHA1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSHA1.Location = new System.Drawing.Point(95, 154); + this.txtSHA1.Name = "txtSHA1"; + this.txtSHA1.ReadOnly = true; + this.txtSHA1.Size = new System.Drawing.Size(411, 20); + this.txtSHA1.TabIndex = 9; + // + // txtSerialNumber + // + this.txtSerialNumber.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSerialNumber.Location = new System.Drawing.Point(95, 128); + this.txtSerialNumber.Name = "txtSerialNumber"; + this.txtSerialNumber.ReadOnly = true; + this.txtSerialNumber.Size = new System.Drawing.Size(411, 20); + this.txtSerialNumber.TabIndex = 8; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(16, 105); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(45, 13); + this.label6.TabIndex = 7; + this.label6.Text = "Valid to:"; + // + // txtValidTo + // + this.txtValidTo.Location = new System.Drawing.Point(95, 102); + this.txtValidTo.Name = "txtValidTo"; + this.txtValidTo.ReadOnly = true; + this.txtValidTo.Size = new System.Drawing.Size(200, 20); + this.txtValidTo.TabIndex = 6; + // + // txtValidFrom + // + this.txtValidFrom.Location = new System.Drawing.Point(95, 76); + this.txtValidFrom.Name = "txtValidFrom"; + this.txtValidFrom.ReadOnly = true; + this.txtValidFrom.Size = new System.Drawing.Size(200, 20); + this.txtValidFrom.TabIndex = 5; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(16, 79); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(56, 13); + this.label5.TabIndex = 4; + this.label5.Text = "Valid from:"; + // + // txtIssuer + // + this.txtIssuer.Location = new System.Drawing.Point(95, 50); + this.txtIssuer.Name = "txtIssuer"; + this.txtIssuer.ReadOnly = true; + this.txtIssuer.Size = new System.Drawing.Size(200, 20); + this.txtIssuer.TabIndex = 3; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(16, 53); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(38, 13); + this.label4.TabIndex = 2; + this.label4.Text = "Issuer:"; + // + // txtAlias + // + this.txtAlias.Location = new System.Drawing.Point(95, 24); + this.txtAlias.Name = "txtAlias"; + this.txtAlias.ReadOnly = true; + this.txtAlias.Size = new System.Drawing.Size(135, 20); + this.txtAlias.TabIndex = 1; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(16, 27); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(32, 13); + this.label3.TabIndex = 0; + this.label3.Text = "Alias:"; + // + // CertificateDetailsForm + // + this.AcceptButton = this.bttClose; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttClose; + this.ClientSize = new System.Drawing.Size(552, 376); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.bttClose); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CertificateDetailsForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Certificate Details"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttShow; + private System.Windows.Forms.Button bttClose; + private System.Windows.Forms.TextBox txtPath; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox txtValidTo; + private System.Windows.Forms.TextBox txtValidFrom; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox txtIssuer; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox txtAlias; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox txtMD5; + private System.Windows.Forms.TextBox txtSHA1; + private System.Windows.Forms.TextBox txtSerialNumber; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/CertificateDetailsForm.cs b/src_vs2012/Package/Dialogs/CertificateDetailsForm.cs new file mode 100644 index 00000000..d80e2033 --- /dev/null +++ b/src_vs2012/Package/Dialogs/CertificateDetailsForm.cs @@ -0,0 +1,111 @@ +using System; +using System.IO; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class CertificateDetailsForm : Form + { + private readonly DeveloperDefinition _developer; + private KeyToolInfoRunner _runner; + private bool _shouldLoad; + + public CertificateDetailsForm(DeveloperDefinition developer) + { + if (developer == null) + throw new ArgumentNullException("developer"); + _developer = developer; + + InitializeComponent(); + _shouldLoad = true; + Path = _developer.CertificateFullPath; + } + + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + + // load info about the certificate: + if (_shouldLoad && !string.IsNullOrEmpty(Path) && File.Exists(Path)) + { + txtAlias.Text = "Loading..."; + + // ask for password, if needed: + if (!_developer.HasPassword) + { + var form = new PasswordForm(); + + if (form.ShowDialog() != DialogResult.OK) + { + txtAlias.Text = string.Empty; + return; + } + + // store given password: + _developer.UpdatePassword(form.Password, form.ShouldRemember); + } + + _runner = new KeyToolInfoRunner(Path, _developer.CskPassword); + _runner.Dispatcher = EventDispatcher.From(this); + _runner.Finished += OnInfoLoaded; + _runner.ExecuteAsync(); + } + } + + #region Properties + + public string Path + { + get { return txtPath.Text; } + set + { + if (string.IsNullOrEmpty(value)) + { + txtName.Text = string.Empty; + txtPath.Text = "Certificate is missing"; + bttShow.Enabled = false; + } + else + { + txtName.Text = System.IO.Path.GetFileName(value); + txtPath.Text = value; + bttShow.Enabled = true; + } + } + } + + #endregion + + private void OnInfoLoaded(object sender, ToolRunnerEventArgs e) + { + if (e.IsSuccessfull && _runner.Info != null) + { + var info = _runner.Info; + + txtAlias.Text = info.Alias; + txtIssuer.Text = info.Issuer; + txtValidFrom.Text = info.ValidFrom.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"); + txtValidTo.Text = info.ValidTo.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"); + txtSerialNumber.Text = info.SerialNumber; + txtSHA1.Text = info.FingerprintSHA1; + txtMD5.Text = info.FingerprintMD5; + } + else + { + txtAlias.Text = "Unable to load info"; + } + } + + private void bttShow_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(Path)) + return; + + DialogHelper.StartExplorerForFile(Path); + } + } +} diff --git a/src_vs2012/Package/Dialogs/CertificateDetailsForm.resx b/src_vs2012/Package/Dialogs/CertificateDetailsForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/CertificateDetailsForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/CskRequestForm.Designer.cs b/src_vs2012/Package/Dialogs/CskRequestForm.Designer.cs new file mode 100644 index 00000000..18aa23ae --- /dev/null +++ b/src_vs2012/Package/Dialogs/CskRequestForm.Designer.cs @@ -0,0 +1,65 @@ +using BlackBerry.Package.Model.Integration; + +namespace BlackBerry.Package.Dialogs +{ + partial class CskRequestForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webBrowser = new WebBrowserTurbo(); + this.SuspendLayout(); + // + // webBrowser + // + this.webBrowser.Dock = System.Windows.Forms.DockStyle.Fill; + this.webBrowser.Location = new System.Drawing.Point(0, 0); + this.webBrowser.MinimumSize = new System.Drawing.Size(20, 20); + this.webBrowser.Name = "webBrowser"; + this.webBrowser.Size = new System.Drawing.Size(739, 424); + this.webBrowser.TabIndex = 0; + // + // CskRequestForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(739, 424); + this.Controls.Add(this.webBrowser); + this.MinimizeBox = false; + this.Name = "CskRequestForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Request BlackBerry ID token"; + this.ResumeLayout(false); + + } + + #endregion + + private WebBrowserTurbo webBrowser; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/CskRequestForm.cs b/src_vs2012/Package/Dialogs/CskRequestForm.cs new file mode 100644 index 00000000..9d412787 --- /dev/null +++ b/src_vs2012/Package/Dialogs/CskRequestForm.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web; +using System.Windows.Forms; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Model.Integration; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class CskRequestForm : Form + { + private const string CallbackURL = "http://127.0.0.1:12345/vs-plugin"; + + public CskRequestForm(string title) + { + // validate certificate by calling a function + InitializeComponent(); + + if (title != null) + Text = title; + + // navigate: + webBrowser.BeforeNavigating += OnBeforeNavigating; + webBrowser.NavigateError += OnNavigatingError; + } + + #region Properties + + public int StatusCode + { + get; + private set; + } + + public CskTokenInfo Token + { + get; + private set; + } + + #endregion + + public void StartRequest(string password) + { + string headers = "Content-Type: application/x-www-form-urlencoded"; + string data = "callbackURL=" + HttpUtility.UrlEncode(CallbackURL) + "&cskPassword=" + HttpUtility.UrlEncode(password); + + webBrowser.Navigate(new Uri("https://developer.blackberry.com/bdsc/ndk.pg", UriKind.Absolute), null, Encoding.UTF8.GetBytes(data), headers); + } + + /// + /// Method that handles all errors during spot on web-pages. + /// + private void OnNavigatingError(object sender, WebBrowserNavigateErrorEventArgs e) + { + StatusCode = e.StatusCode; + e.Cancel = true; + + Invoke(new Action(RequestFailed)); + + TraceLog.WarnLine("Error {0}, while loading URL: \"{1}\"", e.StatusCode, e.Url); + } + + /// + /// Method that handles the BeforeNavigating event of the browser. + /// + private void OnBeforeNavigating(object sender, WebBrowserBeforeNavigatingEventArgs e) + { + if (e.Url == CallbackURL) + { + if (e.PostData == null || e.PostData.Length == 0) + { + StatusCode = 404; + Token = new CskTokenInfo(null); + } + else + { + // this seems to be NUL-terminated string... + string postData = Encoding.UTF8.GetString(e.PostData, 0, e.PostData[e.PostData.Length - 1] == 0 ? e.PostData.Length - 1 : e.PostData.Length); + string[] data = postData.Split('&'); + + for (int i = 0; i < data.Length; i++) + { + data[i] = HttpUtility.UrlDecode(data[i]); + + // and remove some unwanted chars: + if (data[i] != null) + data[i] = data[i].TrimEnd('\t', ' '); + } + + StatusCode = 200; + Token = new CskTokenInfo(FindContentFor(data, "cskData=")); + } + + e.Cancel = true; + // And close the form + Invoke(new Action(RequestCompleted)); + } + } + + private void RequestFailed() + { + DialogResult = DialogResult.Cancel; + Close(); + } + + private void RequestCompleted() + { + DialogResult = DialogResult.OK; + Close(); + } + + /// + /// Get the rest of the line from specified collection that starts with specified string key. + /// + private static string FindContentFor(IEnumerable collection, string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException("key"); + + if (collection != null) + { + foreach (var item in collection) + { + if (item != null && item.StartsWith(key, StringComparison.OrdinalIgnoreCase)) + { + return item.Substring(key.Length); + } + } + } + + return null; + } + } +} diff --git a/src_vs2012/Package/Dialogs/CskRequestForm.resx b/src_vs2012/Package/Dialogs/CskRequestForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/CskRequestForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.Designer.cs b/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.Designer.cs new file mode 100644 index 00000000..75a89943 --- /dev/null +++ b/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.Designer.cs @@ -0,0 +1,301 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class DebugTokenDeploymentForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + + if (disposing) + { + if (_deviceInfoRunner != null) + { + _deviceInfoRunner.Dispose(); + _deviceInfoRunner = null; + } + if (_tokenCreateRunner != null) + { + _tokenCreateRunner.Dispose(); + _tokenCreateRunner = null; + } + if (_tokenInfoRunner != null) + { + _tokenInfoRunner.Dispose(); + _tokenInfoRunner = null; + } + if (_tokenRemoveRunner != null) + { + _tokenRemoveRunner.Dispose(); + _tokenRemoveRunner = null; + } + if (_tokenUploadRunner != null) + { + _tokenUploadRunner.Dispose(); + _tokenUploadRunner = null; + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttTokenCreate = new System.Windows.Forms.Button(); + this.txtDebugTokenLog = new System.Windows.Forms.TextBox(); + this.bttTokenBrowse = new System.Windows.Forms.Button(); + this.txtDebugTokenPath = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.bttOK = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.bttAdd = new System.Windows.Forms.Button(); + this.bttUpload = new System.Windows.Forms.Button(); + this.txtDeviceLog = new System.Windows.Forms.TextBox(); + this.cmbDevices = new System.Windows.Forms.ComboBox(); + this.bttDeviceLoad = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.lblError = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttTokenCreate); + this.groupBox1.Controls.Add(this.txtDebugTokenLog); + this.groupBox1.Controls.Add(this.bttTokenBrowse); + this.groupBox1.Controls.Add(this.txtDebugTokenPath); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(523, 145); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Debug Token"; + // + // bttTokenCreate + // + this.bttTokenCreate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttTokenCreate.Location = new System.Drawing.Point(442, 51); + this.bttTokenCreate.Name = "bttTokenCreate"; + this.bttTokenCreate.Size = new System.Drawing.Size(75, 23); + this.bttTokenCreate.TabIndex = 3; + this.bttTokenCreate.Text = "Cr&eate..."; + this.bttTokenCreate.UseVisualStyleBackColor = true; + this.bttTokenCreate.Click += new System.EventHandler(this.bttTokenCreate_Click); + // + // txtDebugTokenLog + // + this.txtDebugTokenLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtDebugTokenLog.Location = new System.Drawing.Point(20, 51); + this.txtDebugTokenLog.Multiline = true; + this.txtDebugTokenLog.Name = "txtDebugTokenLog"; + this.txtDebugTokenLog.ReadOnly = true; + this.txtDebugTokenLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtDebugTokenLog.Size = new System.Drawing.Size(416, 88); + this.txtDebugTokenLog.TabIndex = 5; + // + // bttTokenBrowse + // + this.bttTokenBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttTokenBrowse.Location = new System.Drawing.Point(442, 22); + this.bttTokenBrowse.Name = "bttTokenBrowse"; + this.bttTokenBrowse.Size = new System.Drawing.Size(75, 23); + this.bttTokenBrowse.TabIndex = 2; + this.bttTokenBrowse.Text = "&Open..."; + this.bttTokenBrowse.UseVisualStyleBackColor = true; + this.bttTokenBrowse.Click += new System.EventHandler(this.bttTokenBrowse_Click); + // + // txtDebugTokenPath + // + this.txtDebugTokenPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtDebugTokenPath.Location = new System.Drawing.Point(75, 22); + this.txtDebugTokenPath.Name = "txtDebugTokenPath"; + this.txtDebugTokenPath.ReadOnly = true; + this.txtDebugTokenPath.Size = new System.Drawing.Size(361, 20); + this.txtDebugTokenPath.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(17, 25); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(32, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Path:"; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttOK.Location = new System.Drawing.Point(460, 381); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 3; + this.bttOK.Text = "&Close"; + this.bttOK.UseVisualStyleBackColor = true; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.bttAdd); + this.groupBox2.Controls.Add(this.bttUpload); + this.groupBox2.Controls.Add(this.txtDeviceLog); + this.groupBox2.Controls.Add(this.cmbDevices); + this.groupBox2.Controls.Add(this.bttDeviceLoad); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Location = new System.Drawing.Point(12, 163); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(523, 212); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Onto Device"; + // + // bttAdd + // + this.bttAdd.Location = new System.Drawing.Point(270, 19); + this.bttAdd.Name = "bttAdd"; + this.bttAdd.Size = new System.Drawing.Size(30, 23); + this.bttAdd.TabIndex = 6; + this.bttAdd.Text = "+"; + this.bttAdd.UseVisualStyleBackColor = true; + this.bttAdd.Click += new System.EventHandler(this.bttAdd_Click); + // + // bttUpload + // + this.bttUpload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttUpload.Enabled = false; + this.bttUpload.Location = new System.Drawing.Point(442, 46); + this.bttUpload.Name = "bttUpload"; + this.bttUpload.Size = new System.Drawing.Size(75, 23); + this.bttUpload.TabIndex = 2; + this.bttUpload.Text = "&Upload"; + this.bttUpload.UseVisualStyleBackColor = true; + this.bttUpload.Click += new System.EventHandler(this.bttUpload_Click); + // + // txtDeviceLog + // + this.txtDeviceLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtDeviceLog.Location = new System.Drawing.Point(20, 46); + this.txtDeviceLog.Multiline = true; + this.txtDeviceLog.Name = "txtDeviceLog"; + this.txtDeviceLog.ReadOnly = true; + this.txtDeviceLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtDeviceLog.Size = new System.Drawing.Size(416, 160); + this.txtDeviceLog.TabIndex = 5; + // + // cmbDevices + // + this.cmbDevices.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbDevices.Enabled = false; + this.cmbDevices.FormattingEnabled = true; + this.cmbDevices.Location = new System.Drawing.Point(75, 19); + this.cmbDevices.MaxDropDownItems = 25; + this.cmbDevices.Name = "cmbDevices"; + this.cmbDevices.Size = new System.Drawing.Size(189, 21); + this.cmbDevices.TabIndex = 1; + this.cmbDevices.SelectedIndexChanged += new System.EventHandler(this.cmbDevices_SelectedIndexChanged); + // + // bttDeviceLoad + // + this.bttDeviceLoad.Enabled = false; + this.bttDeviceLoad.Location = new System.Drawing.Point(442, 75); + this.bttDeviceLoad.Name = "bttDeviceLoad"; + this.bttDeviceLoad.Size = new System.Drawing.Size(75, 23); + this.bttDeviceLoad.TabIndex = 3; + this.bttDeviceLoad.Text = "Re&load info"; + this.bttDeviceLoad.UseVisualStyleBackColor = true; + this.bttDeviceLoad.Click += new System.EventHandler(this.bttDeviceLoad_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(17, 22); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(41, 13); + this.label2.TabIndex = 0; + this.label2.Text = "Target:"; + // + // lblError + // + this.lblError.ForeColor = System.Drawing.Color.Red; + this.lblError.Location = new System.Drawing.Point(30, 378); + this.lblError.Name = "lblError"; + this.lblError.Size = new System.Drawing.Size(418, 35); + this.lblError.TabIndex = 2; + this.lblError.Text = "- error -"; + this.lblError.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.lblError.Visible = false; + // + // DebugTokenDeploymentForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttOK; + this.ClientSize = new System.Drawing.Size(547, 411); + this.Controls.Add(this.lblError); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DebugTokenDeploymentForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Debug Token Deployment"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttTokenCreate; + private System.Windows.Forms.TextBox txtDebugTokenLog; + private System.Windows.Forms.Button bttTokenBrowse; + private System.Windows.Forms.TextBox txtDebugTokenPath; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Button bttDeviceLoad; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox cmbDevices; + private System.Windows.Forms.TextBox txtDeviceLog; + private System.Windows.Forms.Button bttUpload; + private System.Windows.Forms.Label lblError; + private System.Windows.Forms.Button bttAdd; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.cs b/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.cs new file mode 100644 index 00000000..3e5bd3d1 --- /dev/null +++ b/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.cs @@ -0,0 +1,646 @@ +using System; +using System.IO; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.Model.Integration; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class DebugTokenDeploymentForm : Form + { + private TargetsOptionViewModel _vm; + private DeviceDefinition _device; + private DebugTokenInfoRunner _tokenInfoRunner; + private DeviceInfoRunner _deviceInfoRunner; + private DebugTokenUploadRunner _tokenUploadRunner; + private ApplicationRemoveRunner _tokenRemoveRunner; + private DebugTokenCreateRunner _tokenCreateRunner; + private DebugTokenInfo _tokenInfo; + private bool _startup; + + public DebugTokenDeploymentForm(TargetsOptionViewModel vm, DeviceDefinition device) + { + InitializeComponent(); + + ErrorText = string.Empty; + _startup = true; + + SetVM(vm, device); + } + + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + + if (_startup) + { + _startup = false; + + // if there is no path do debug-token, ask for it: + if (string.IsNullOrEmpty(DebugTokenPath)) + { + bttTokenBrowse_Click(null, EventArgs.Empty); + } + + LoadDeviceInfo(_device, false); + } + } + + #region Properties + + public bool AskOnStartup + { + get { return _startup; } + set { _startup = value; } + } + + public bool IsLoadingTokenInfo + { + get { return _tokenInfoRunner != null; } + } + + public bool IsUploadingToken + { + get { return _tokenUploadRunner != null; } + } + + public bool IsRemovingToken + { + get { return _tokenRemoveRunner != null; } + } + + public bool IsCreatingToken + { + get { return _tokenCreateRunner != null; } + } + + public bool IsLoadingDeviceInfo + { + get { return _deviceInfoRunner != null; } + } + + public string DebugTokenPath + { + get { return txtDebugTokenPath.Text; } + set { txtDebugTokenPath.Text = value; } + } + + public string ErrorText + { + get { return lblError.Text; } + set + { + lblError.Text = value; + lblError.Visible = !string.IsNullOrEmpty(value); + } + } + + public bool ErrorVisible + { + get { return lblError.Visible; } + set { lblError.Visible = value; } + } + + #endregion + + /// + /// Provides the view-model for populating data. + /// + internal void SetVM(TargetsOptionViewModel vm, DeviceDefinition device) + { + if (vm == null) + throw new ArgumentNullException("vm"); + if (device == null) + throw new ArgumentNullException("device"); + _vm = vm; + _device = device; + + PopulateDevices(device); + } + + private void PopulateDevices(DeviceDefinition select) + { + cmbDevices.Items.Clear(); + + ComboBoxItem selectedItem = null; + foreach (var device in _vm.Devices) + { + var item = new ComboBoxItem(device.ShortName); + item.Tag = device; + + if (device == select) + selectedItem = item; + + cmbDevices.Items.Add(item); + } + + cmbDevices.SelectedItem = selectedItem; + } + + #region Logs Support Methods + + private void ClearTokenLogs() + { + txtDebugTokenLog.Text = string.Empty; + txtDebugTokenLog.SelectionLength = 0; + txtDebugTokenLog.SelectionStart = 0; + } + + private void AppendTokenLog(string message) + { + if (string.IsNullOrEmpty(message)) + return; + + if (InvokeRequired) + Invoke(new Action(AppendTokenLog), message); + else + txtDebugTokenLog.Text += message + Environment.NewLine; + } + + private void ClearDeviceLogs() + { + txtDeviceLog.Text = string.Empty; + txtDeviceLog.SelectionLength = 0; + txtDeviceLog.SelectionStart = 0; + } + + private void AppendDeviceLog(string message) + { + if (string.IsNullOrEmpty(message)) + return; + + if (InvokeRequired) + Invoke(new Action(AppendDeviceLog), message); + else + txtDeviceLog.Text += message + Environment.NewLine; + } + + #endregion + + #region Token Info Runner + + private void LoadTokenInfo(string fileName) + { + if (IsLoadingTokenInfo) + return; + + ClearTokenLogs(); + AppendTokenLog("Loading debug token info..."); + _tokenInfo = null; + DebugTokenPath = fileName; + UpdateTokenStatusUI(false); + + // and load token info asynchronously: + _tokenInfoRunner = new DebugTokenInfoRunner(fileName); + _tokenInfoRunner.Dispatcher = EventDispatcher.From(this); + _tokenInfoRunner.Finished += TokenInfoRunnerOnFinished; + _tokenInfoRunner.ExecuteAsync(); + } + + private void TokenInfoRunnerOnFinished(object sender, ToolRunnerEventArgs e) + { + bool success = string.IsNullOrEmpty(_tokenInfoRunner.LastError) && _tokenInfoRunner.DebugToken != null; + AppendTokenLog("--- DONE with " + (success ? "success" : "failure") + Environment.NewLine); + + if (success) + { + _tokenInfo = _tokenInfoRunner.DebugToken; + if (_tokenInfo != null) + { + _vm.Update(_tokenInfo.Author); + } + + TraceLog.WriteLine("Loaded debug token: {0}", _tokenInfoRunner.DebugToken); + AppendTokenLog("Debug token found:" + Environment.NewLine + _tokenInfoRunner.DebugToken.ToLongDescription(true)); + } + else + { + TraceLog.WriteLine("Failed to load info about debug token: \"{0}\"", _tokenInfoRunner.DebugTokenLocation); + AppendTokenLog(_tokenInfoRunner.LastError); + } + + _tokenInfoRunner.Finished -= TokenInfoRunnerOnFinished; + _tokenInfoRunner = null; + + UpdateTokenStatusUI(true); + UpdateDeviceStatusUI(!IsLoadingDeviceInfo); + } + + private void UpdateTokenStatusUI(bool completed) + { + bttTokenBrowse.Enabled = completed; + bttTokenCreate.Enabled = completed; + + if (!completed) + { + ErrorText = string.Empty; + } + else + { + UpdateErrorUI(); + } + } + + private void UpdateErrorUI() + { + if (_tokenInfo == null) + { + ErrorText = "Missing debug token to upload"; + return; + } + + if (_tokenInfo.ExpiryDate < DateTime.UtcNow) + { + ErrorText = "Debug token already expired"; + return; + } + + var deviceInfo = _vm.GetDetails(_device); + if (deviceInfo == null) + { + ErrorText = "Missing connected device"; + return; + } + + if (deviceInfo.PIN == 0) + { + ErrorText = "Invalid device PIN"; + return; + } + + if (!_tokenInfo.Contains(deviceInfo.PIN)) + { + ErrorText = "Debug token is not created against this device, recreate it adding connected device's PIN to list of target devices"; + return; + } + } + + #endregion + + #region Device Info Runner + + private void LoadDeviceInfo(DeviceDefinition device, bool forceReload) + { + if (IsLoadingDeviceInfo) + return; + + ClearDeviceLogs(); + _device = device; + if (_device == null) + { + AppendDeviceLog("Invalid device to load info"); + return; + } + + // load device info or get it from cache: + var deviceInfo = _vm.GetDetails(_device); + if (deviceInfo == null || forceReload) + { + AppendDeviceLog("Loading device info..."); + _vm.SetDetails(_device, null); + UpdateDeviceStatusUI(false); + + // load info asynchronously: + _deviceInfoRunner = new DeviceInfoRunner(_device.IP, _device.Password); + _deviceInfoRunner.Dispatcher = EventDispatcher.From(this); + _deviceInfoRunner.Finished += DeviceInfoRunnerOnFinished; + _deviceInfoRunner.ExecuteAsync(); + } + else + { + PrintDeviceInfo(deviceInfo); + UpdateDeviceStatusUI(true); + } + } + + private void DeviceInfoRunnerOnFinished(object sender, ToolRunnerEventArgs toolRunnerEventArgs) + { + bool success = string.IsNullOrEmpty(_deviceInfoRunner.LastError) && _deviceInfoRunner.DeviceInfo != null; + AppendDeviceLog("--- DONE with " + (success ? "success" : "failure") + Environment.NewLine); + + if (success) + { + TraceLog.WriteLine("Loaded info about device: {0}", _deviceInfoRunner.DeviceInfo); + + // update cache: + var deviceInfo = _deviceInfoRunner.DeviceInfo; + _vm.SetDetails(_device, deviceInfo); + + PrintDeviceInfo(deviceInfo); + } + else + { + TraceLog.WriteLine("Failed to load info about device: {0}", _device); + TraceLog.WarnLine(_deviceInfoRunner.LastOutput); + AppendDeviceLog(_deviceInfoRunner.LastError); + } + + _deviceInfoRunner.Finished -= DeviceInfoRunnerOnFinished; + _deviceInfoRunner = null; + + UpdateDeviceStatusUI(true); + } + + private void PrintDeviceInfo(DeviceInfo deviceInfo) + { + if (deviceInfo == null) + return; + + string debugTokenDescription = deviceInfo.DebugToken != null ? deviceInfo.DebugToken.ToLongDescription() : "Error: not found"; + + AppendDeviceLog("Debug token found: " + Environment.NewLine + debugTokenDescription); + AppendDeviceLog("Device found:" + Environment.NewLine + deviceInfo.ToLongDescription()); + } + + private void UpdateDeviceStatusUI(bool completed) + { + var details = _vm.GetDetails(_device); + + cmbDevices.Enabled = completed; + bttAdd.Enabled = completed; + bttDeviceLoad.Enabled = completed && !IsLoadingDeviceInfo; + bttUpload.Enabled = completed && details != null && _tokenInfo != null /*&& _tokenInfo.ExpiryDate > DateTime.UtcNow && _tokenInfo.Contains(details.PIN) */; + + if (!completed) + { + ErrorText = string.Empty; + } + else + { + UpdateErrorUI(); + } + } + + #endregion + + #region Debug Token Upload Runner + + private void UploadDebugToken(string fileName) + { + if (IsUploadingToken) + return; + + ClearDeviceLogs(); + if (_device == null) + { + AppendDeviceLog("Invalid device to upload debug token"); + return; + } + + AppendDeviceLog("Uploading debug token to " + _device + "..."); + UpdateDeviceStatusUI(false); + + // upload token asynchronously: + _tokenUploadRunner = new DebugTokenUploadRunner(fileName, _device.IP, _device.Password); + _tokenUploadRunner.Dispatcher = EventDispatcher.From(this); + _tokenUploadRunner.Finished += DebugTokenUploadRunnerOnFinished; + _tokenUploadRunner.ExecuteAsync(); + } + + private void DebugTokenUploadRunnerOnFinished(object sender, ToolRunnerEventArgs e) + { + bool success = string.IsNullOrEmpty(_tokenUploadRunner.LastError) && _tokenUploadRunner.UploadedSuccessfully; + AppendDeviceLog("--- DONE with " + (success ? "success" : "failure") + Environment.NewLine); + + if (success) + { + TraceLog.WriteLine("Uploaded debug token to device: {0}", _device); + } + else + { + TraceLog.WriteLine("Failed to upload debug token to device: {0}", _device); + TraceLog.WarnLine(_tokenUploadRunner.LastError); + AppendDeviceLog(_tokenUploadRunner.LastError); + } + + _tokenUploadRunner.Finished -= DeviceInfoRunnerOnFinished; + _tokenUploadRunner = null; + + UpdateDeviceStatusUI(true); + + if (success) + { + // reload device info: + LoadDeviceInfo(_device, true); + } + } + + #endregion + + #region Debug Token Removal Runner + + private void RemoveDebugToken() + { + if (IsRemovingToken) + return; + + if (MessageBoxHelper.Show("Remove debug-token from that device?", _device.ShortName, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) + return; + + ClearDeviceLogs(); + if (_device == null) + { + AppendDeviceLog("Invalid device to remove debug token"); + return; + } + if (_tokenInfo == null || string.IsNullOrEmpty(_tokenInfo.ID)) + { + AppendDeviceLog("Invalid debug token info, to remove it from device"); + return; + } + + AppendDeviceLog("Removing debug token from " + _device + "..."); + UpdateDeviceStatusUI(false); + + // remove token asynchronously: + _tokenRemoveRunner = new ApplicationRemoveRunner(_tokenInfo.ID, _device.IP, _device.Password); + _tokenRemoveRunner.Dispatcher = EventDispatcher.From(this); + _tokenRemoveRunner.Finished += DebugTokenRemoveRunnerOnFinished; + _tokenRemoveRunner.ExecuteAsync(); + } + + private void DebugTokenRemoveRunnerOnFinished(object sender, ToolRunnerEventArgs e) + { + bool success = string.IsNullOrEmpty(_tokenRemoveRunner.LastError) && _tokenRemoveRunner.RemovedSuccessfully; + AppendDeviceLog("--- DONE with " + (success ? "success" : "failure") + Environment.NewLine); + + if (success) + { + TraceLog.WriteLine("Removed debug token a device: {0}", _device); + } + else + { + TraceLog.WriteLine("Failed to remove debug token to device: {0}", _device); + TraceLog.WarnLine(_tokenRemoveRunner.LastOutput); + TraceLog.WarnLine(_tokenRemoveRunner.LastError); + AppendDeviceLog(_tokenRemoveRunner.LastError); + } + + _tokenRemoveRunner.Finished -= DebugTokenRemoveRunnerOnFinished; + _tokenRemoveRunner = null; + + UpdateDeviceStatusUI(true); + + if (success) + { + // reload device info: + LoadDeviceInfo(_device, true); + } + } + + #endregion + + #region Debug Token Create Runner + + private void CreateDebugToken(string fileName, ulong[] devicePins) + { + if (IsCreatingToken) + return; + + ClearTokenLogs(); + AppendTokenLog("Creating new debug token..."); + _tokenInfo = null; + DebugTokenPath = fileName; + UpdateTokenStatusUI(false); + + // and create token asynchronously: + _tokenCreateRunner = new DebugTokenCreateRunner(fileName, _vm.Developer.CskPassword, devicePins, _vm.Developer.CertificateFullPath); + _tokenCreateRunner.Dispatcher = EventDispatcher.From(this); + _tokenCreateRunner.Finished += TokenCreateRunnerOnFinished; + _tokenCreateRunner.ExecuteAsync(); + } + + private void TokenCreateRunnerOnFinished(object sender, ToolRunnerEventArgs e) + { + bool success = string.IsNullOrEmpty(_tokenCreateRunner.LastError) && _tokenCreateRunner.CreatedSuccessfully; + AppendTokenLog("--- DONE with " + (success ? "success" : "failure") + Environment.NewLine); + + string path = success ? _tokenCreateRunner.DebugTokenLocation : null; + + if (success) + { + TraceLog.WriteLine("Created new debug token at: \"{0}\"", path); + AppendTokenLog("Debug token created at:" + Environment.NewLine + path); + } + else + { + TraceLog.WriteLine("Failed to create debug token at: \"{0}\"", path); + AppendTokenLog(_tokenCreateRunner.LastError); + } + + _tokenCreateRunner.Finished -= TokenCreateRunnerOnFinished; + _tokenCreateRunner = null; + + UpdateTokenStatusUI(true); + UpdateDeviceStatusUI(!IsLoadingDeviceInfo); + + if (success) + { + // reload token info: + LoadTokenInfo(path); + } + } + + #endregion + + private void bttTokenBrowse_Click(object sender, EventArgs e) + { + if (IsLoadingTokenInfo) + return; + + var openFile = DialogHelper.OpenBarFile("Load Debug Token", + string.IsNullOrEmpty(DebugTokenPath) ? ConfigDefaults.DataDirectory : DebugTokenPath); + + if (openFile.ShowDialog() == DialogResult.OK) + { + LoadTokenInfo(openFile.FileName); + } + } + + private void cmbDevices_SelectedIndexChanged(object sender, EventArgs e) + { + var item = cmbDevices.SelectedItem as ComboBoxItem; + var device = item != null ? item.Tag as DeviceDefinition : null; + + // load and display detailed info about newly selected device: + if (device != null) + { + LoadDeviceInfo(device, false); + } + } + + private void bttDeviceLoad_Click(object sender, EventArgs e) + { + // force data reload: + LoadDeviceInfo(_device, true); + } + + private void bttUpload_Click(object sender, EventArgs e) + { + UploadDebugToken(DebugTokenPath); + } + + private void bttTokenCreate_Click(object sender, EventArgs e) + { + var details = _vm.GetDetails(_device); + if (details == null || details.PIN == 0) + { + MessageBoxHelper.Show("Connect to the device first and load its properties", "Missing device PIN", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + if (string.IsNullOrEmpty(_vm.Developer.CskPassword)) + { + var form = new PasswordForm(); + + if (form.ShowDialog() != DialogResult.OK) + { + TraceLog.WarnLine("Update of BBID Token CSK password rejected"); + return; + } + + // save password (for current session only for persistantly): + _vm.Developer.UpdatePassword(form.Password, form.ShouldRemember); + } + + // ask where to store the debug-token: + var startupPath = string.IsNullOrEmpty(DebugTokenPath) ? ConfigDefaults.DataDirectory : Path.GetDirectoryName(DebugTokenPath); + var saveFile = DialogHelper.SaveBarFile("Renewed debug token location", startupPath, "debugtoken-" + DateTime.Now.ToString("yyyy-MM-dd") + ".bar"); + + if (saveFile.ShowDialog() == DialogResult.OK) + { + // show PINs editor: + var form = new PinListForm(); + form.OptionalDevices = _vm.Devices; + form.Add(_tokenInfo != null ? _tokenInfo.Devices : null); + form.Add(details.PIN); + + if (form.ShowDialog() == DialogResult.OK) + { + var devicePINs = form.PINs; + if (devicePINs == null || devicePINs.Length == 0) + devicePINs = new[] { details.PIN }; + + CreateDebugToken(saveFile.FileName, devicePINs); + } + } + } + + private void bttAdd_Click(object sender, EventArgs e) + { + var form = new DeviceForm("Add new Target Device"); + + if (form.ShowDialog() == DialogResult.OK) + { + var device = form.ToDevice(); + _vm.Add(device); + PopulateDevices(device); + } + } + } +} diff --git a/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.resx b/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/DebugTokenDeploymentForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/DeviceForm.Designer.cs b/src_vs2012/Package/Dialogs/DeviceForm.Designer.cs new file mode 100644 index 00000000..324b4f1d --- /dev/null +++ b/src_vs2012/Package/Dialogs/DeviceForm.Designer.cs @@ -0,0 +1,305 @@ +namespace BlackBerry.Package.Dialogs +{ + partial class DeviceForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + if (disposing) + { + if (_runner != null) + { + _runner.Dispose(); + _runner = null; + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttSetName = new System.Windows.Forms.Button(); + this.txtPassword = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.txtIP = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.txtName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.lblType = new System.Windows.Forms.Label(); + this.cmbType = new System.Windows.Forms.ComboBox(); + this.cmbNames = new System.Windows.Forms.ComboBox(); + this.txtLogs = new System.Windows.Forms.TextBox(); + this.bttTest = new System.Windows.Forms.Button(); + this.bttOK = new System.Windows.Forms.Button(); + this.bttCancel = new System.Windows.Forms.Button(); + this.bttDiscover = new System.Windows.Forms.Button(); + this.txtPIN = new System.Windows.Forms.TextBox(); + this.lblPIN = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttSetName); + this.groupBox1.Controls.Add(this.txtPassword); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.txtIP); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.txtName); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.lblType); + this.groupBox1.Controls.Add(this.cmbType); + this.groupBox1.Controls.Add(this.cmbNames); + this.groupBox1.Controls.Add(this.txtPIN); + this.groupBox1.Controls.Add(this.lblPIN); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(404, 141); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Target Device Properties"; + // + // bttSetName + // + this.bttSetName.Location = new System.Drawing.Point(260, 50); + this.bttSetName.Name = "bttSetName"; + this.bttSetName.Size = new System.Drawing.Size(138, 23); + this.bttSetName.TabIndex = 7; + this.bttSetName.Text = "Set "; + this.bttSetName.UseVisualStyleBackColor = true; + this.bttSetName.Visible = false; + this.bttSetName.Click += new System.EventHandler(this.bttSetName_Click); + // + // txtPassword + // + this.txtPassword.Location = new System.Drawing.Point(89, 103); + this.txtPassword.Name = "txtPassword"; + this.txtPassword.PasswordChar = '*'; + this.txtPassword.Size = new System.Drawing.Size(156, 20); + this.txtPassword.TabIndex = 11; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(17, 106); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(56, 13); + this.label4.TabIndex = 10; + this.label4.Text = "Password:"; + // + // txtIP + // + this.txtIP.Location = new System.Drawing.Point(89, 76); + this.txtIP.Name = "txtIP"; + this.txtIP.Size = new System.Drawing.Size(126, 20); + this.txtIP.TabIndex = 9; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(17, 79); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(20, 13); + this.label3.TabIndex = 8; + this.label3.Text = "IP:"; + // + // txtName + // + this.txtName.Location = new System.Drawing.Point(89, 50); + this.txtName.Name = "txtName"; + this.txtName.Size = new System.Drawing.Size(156, 20); + this.txtName.TabIndex = 6; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(17, 53); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(38, 13); + this.label2.TabIndex = 4; + this.label2.Text = "Name:"; + // + // lblType + // + this.lblType.AutoSize = true; + this.lblType.Location = new System.Drawing.Point(17, 26); + this.lblType.Name = "lblType"; + this.lblType.Size = new System.Drawing.Size(34, 13); + this.lblType.TabIndex = 0; + this.lblType.Text = "Type:"; + // + // cmbType + // + this.cmbType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbType.FormattingEnabled = true; + this.cmbType.Items.AddRange(new object[] { + "Wi-Fi device", + "USB device", + "Simulator"}); + this.cmbType.Location = new System.Drawing.Point(89, 23); + this.cmbType.Name = "cmbType"; + this.cmbType.Size = new System.Drawing.Size(126, 21); + this.cmbType.TabIndex = 2; + this.cmbType.SelectedIndexChanged += new System.EventHandler(this.cmbType_SelectedIndexChanged); + // + // cmbNames + // + this.cmbNames.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cmbNames.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbNames.FormattingEnabled = true; + this.cmbNames.Location = new System.Drawing.Point(89, 50); + this.cmbNames.MaxDropDownItems = 25; + this.cmbNames.Name = "cmbNames"; + this.cmbNames.Size = new System.Drawing.Size(156, 21); + this.cmbNames.TabIndex = 5; + this.cmbNames.Visible = false; + this.cmbNames.SelectedIndexChanged += new System.EventHandler(this.cmbNames_SelectedIndexChanged); + // + // txtLogs + // + this.txtLogs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtLogs.Location = new System.Drawing.Point(12, 159); + this.txtLogs.Multiline = true; + this.txtLogs.Name = "txtLogs"; + this.txtLogs.ReadOnly = true; + this.txtLogs.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtLogs.Size = new System.Drawing.Size(404, 85); + this.txtLogs.TabIndex = 1; + // + // bttTest + // + this.bttTest.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttTest.Location = new System.Drawing.Point(12, 250); + this.bttTest.Name = "bttTest"; + this.bttTest.Size = new System.Drawing.Size(75, 23); + this.bttTest.TabIndex = 3; + this.bttTest.Text = "&Test"; + this.bttTest.UseVisualStyleBackColor = true; + this.bttTest.Click += new System.EventHandler(this.bttTest_Click); + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.Location = new System.Drawing.Point(260, 250); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 4; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + this.bttOK.Click += new System.EventHandler(this.bttOK_Click); + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(341, 250); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 5; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // bttDiscover + // + this.bttDiscover.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttDiscover.Location = new System.Drawing.Point(10, 250); + this.bttDiscover.Name = "bttDiscover"; + this.bttDiscover.Size = new System.Drawing.Size(75, 23); + this.bttDiscover.TabIndex = 2; + this.bttDiscover.Text = "&Discover"; + this.bttDiscover.UseVisualStyleBackColor = true; + this.bttDiscover.Visible = false; + this.bttDiscover.Click += new System.EventHandler(this.bttTest_Click); + // + // txtPIN + // + this.txtPIN.Location = new System.Drawing.Point(89, 23); + this.txtPIN.Name = "txtPIN"; + this.txtPIN.ReadOnly = true; + this.txtPIN.Size = new System.Drawing.Size(126, 20); + this.txtPIN.TabIndex = 3; + this.txtPIN.Visible = false; + // + // lblPIN + // + this.lblPIN.AutoSize = true; + this.lblPIN.Location = new System.Drawing.Point(17, 26); + this.lblPIN.Name = "lblPIN"; + this.lblPIN.Size = new System.Drawing.Size(28, 13); + this.lblPIN.TabIndex = 1; + this.lblPIN.Text = "PIN:"; + this.lblPIN.Visible = false; + // + // DeviceForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(428, 285); + this.Controls.Add(this.bttCancel); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.bttTest); + this.Controls.Add(this.txtLogs); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.bttDiscover); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DeviceForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "DeviceForm"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox txtPassword; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox txtIP; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label lblType; + private System.Windows.Forms.ComboBox cmbType; + private System.Windows.Forms.TextBox txtLogs; + private System.Windows.Forms.Button bttTest; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.Button bttSetName; + private System.Windows.Forms.ComboBox cmbNames; + private System.Windows.Forms.Button bttDiscover; + private System.Windows.Forms.Label lblPIN; + private System.Windows.Forms.TextBox txtPIN; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/DeviceForm.cs b/src_vs2012/Package/Dialogs/DeviceForm.cs new file mode 100644 index 00000000..9f3b7b41 --- /dev/null +++ b/src_vs2012/Package/Dialogs/DeviceForm.cs @@ -0,0 +1,367 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.Model.Integration; + +namespace BlackBerry.Package.Dialogs +{ + /// + /// Internal dialog for adding and testing target device. + /// + internal partial class DeviceForm : Form + { + enum DialogDeviceClass + { + WiFiDevice, + UsbDevice, + Simulator + } + + private const string DefaultPasswordForSimulator = "not-required"; // anything non-empty string, as simulator doesn't require any password + + private DeviceInfoRunner _runner; + private ulong _pin; + private string _loadedDeviceName; + + public DeviceForm(string title) + { + InitializeComponent(); + + Text = title; + cmbType.SelectedIndex = 0; + IsConnected = false; + GoToIPControl(); + } + + #region Properties + + private DialogDeviceClass DeviceClass + { + get { return (DialogDeviceClass) cmbType.SelectedIndex; } + set { cmbType.SelectedIndex = (int) value; } + } + + public string DeviceName + { + get { return txtName.Text; } + set { txtName.Text = value; } + } + + public string DeviceIP + { + get { return txtIP.Text; } + set { txtIP.Text = value; } + } + + public string DevicePassword + { + get { return txtPassword.Text; } + set { txtPassword.Text = value; } + } + + public bool IsConnected + { + get; + private set; + } + + public bool IsDiscoverMode + { + get { return cmbNames.Visible; } + } + + public string LoadedDeviceName + { + get { return _loadedDeviceName; } + set + { + if (string.IsNullOrEmpty(value)) + { + _loadedDeviceName = null; + bttSetName.Text = string.Empty; + bttSetName.Visible = false; + } + else + { + _loadedDeviceName = value; + bttSetName.Text = "<< " + (value.Length > 14 ? value.Substring(0, 14) + "..." : value); // up to 15chars + bttSetName.Visible = txtName.Visible; + } + } + } + + private DeviceDefinition SelectedDevice + { + get + { + if (cmbNames.Enabled && cmbNames.Visible) + { + var item = cmbNames.SelectedItem as ComboBoxItem; + var device = item != null ? item.Tag as DeviceDefinition : null; + + return device; + } + + return null; + } + } + + public ulong PIN + { + get { return _pin; } + private set + { + _pin = value; + txtPIN.Text = value == 0 ? string.Empty : value.ToString("X"); + } + } + + #endregion + + public DeviceDefinition ToDevice() + { + if (string.IsNullOrEmpty(DeviceIP) || string.IsNullOrEmpty(DevicePassword)) + return null; + + return new DeviceDefinition(DeviceName, DeviceIP, DevicePassword, DeviceClass == DialogDeviceClass.Simulator ? DeviceDefinitionType.Simulator : DeviceDefinitionType.Device); + } + + /// + /// Fills the fields of the form based on the given device. + /// + public void FromDevice(DeviceDefinition device) + { + if (device == null) + { + DeviceClass = DialogDeviceClass.WiFiDevice; + DeviceName = string.Empty; + DeviceIP = string.Empty; + DevicePassword = string.Empty; + return; + } + + DeviceClass = GetDeviceClass(device.Type, device.IP); + DeviceName = device.Name; + DeviceIP = device.IP; + DevicePassword = DeviceClass == DialogDeviceClass.Simulator ? DefaultPasswordForSimulator : device.Password; + + GoToIPControl(); + } + + private void GoToIPControl() + { + ActiveControl = txtIP; + txtIP.SelectionLength = 0; + txtIP.SelectionStart = txtIP.Text.Length; + } + + /// + /// Switches the default to PIN-discover mode. + /// In this mode name field is hidden, instead the combo-box with known devices along with PIN field are shown. + /// + public void SetDiscoverMode(IEnumerable devices) + { + cmbType.Enabled = false; + txtName.Visible = false; + cmbNames.Visible = true; + bttTest.Visible = false; + bttDiscover.Visible = true; + bttOK.Enabled = false; + lblType.Visible = false; + lblPIN.Visible = true; + cmbType.Visible = false; + txtPIN.Visible = true; + + cmbNames.Items.Clear(); + cmbNames.Items.Add(new ComboBoxItem(string.Empty)); + if (devices != null) + { + foreach (var device in devices) + { + cmbNames.Items.Add(new ComboBoxItem(device.ShortName, device)); + } + } + cmbNames.SelectedIndex = 0; + cmbNames.Enabled = cmbNames.Items.Count > 1; + + ActiveControl = txtIP; + } + + private DialogDeviceClass GetDeviceClass(DeviceDefinitionType type, string ip) + { + if (type == DeviceDefinitionType.Simulator) + return DialogDeviceClass.Simulator; + + return ip != null && ip.StartsWith("169.254.0.") ? DialogDeviceClass.UsbDevice : DialogDeviceClass.WiFiDevice; + } + + private void ClearLog() + { + txtLogs.Text = string.Empty; + txtLogs.SelectionLength = 0; + txtLogs.SelectionStart = 0; + } + + private void AppendLog(string text) + { + if (string.IsNullOrEmpty(text)) + return; + + if (InvokeRequired) + { + Invoke(new Action(AppendLog), text); + } + else + { + txtLogs.Text += text + Environment.NewLine; + } + } + + private void bttTest_Click(object sender, EventArgs e) + { + ClearLog(); + + // verify arguments: + if (_runner != null) + { + AppendLog("Operation is still in progress."); + return; + } + + if (string.IsNullOrEmpty(DeviceIP)) + { + AppendLog("IP address can not be empty"); + return; + } + + if (string.IsNullOrEmpty(DevicePassword)) + { + AppendLog("Password can not be empty"); + return; + } + + IsConnected = false; + LoadedDeviceName = null; + PIN = 0; + _runner = new DeviceInfoRunner(DeviceIP, DevicePassword); + _runner.Dispatcher = EventDispatcher.From(this); + _runner.Finished += RunnerOnFinished; + + AppendLog("Testing connection..."); + _runner.ExecuteAsync(); + } + + private void RunnerOnFinished(object sender, ToolRunnerEventArgs e) + { + bool success = string.IsNullOrEmpty(_runner.LastError) && _runner.DeviceInfo != null; + AppendLog("--- DONE with " + (success ? "success" : "failure") + Environment.NewLine); + + if (success) + { + TraceLog.WriteLine("Found device: {0} with IP: {1}", _runner.DeviceInfo.ToString(), DeviceIP); + AppendLog("Device found:" + Environment.NewLine + _runner.DeviceInfo.ToLongDescription()); + LoadedDeviceName = _runner.DeviceInfo != null ? _runner.DeviceInfo.Name : null; + PIN = _runner.DeviceInfo != null ? _runner.DeviceInfo.PIN : 0; + IsConnected = true; + } + else + { + TraceLog.WriteLine("Failed to connect to: {0}", DeviceIP); + TraceLog.WarnLine(_runner.LastOutput); + AppendLog(_runner.LastError); + } + + _runner.Finished -= RunnerOnFinished; + _runner = null; + + if (IsDiscoverMode) + { + bttOK.Enabled = PIN > 0; + } + } + + private void cmbType_SelectedIndexChanged(object sender, EventArgs e) + { + txtPassword.ReadOnly = DeviceClass == DialogDeviceClass.Simulator; + + if (DeviceClass == DialogDeviceClass.Simulator) + { + if (DeviceName != "Simulator") + { + DeviceName = "Simulator"; + DeviceIP = "192.168.32.1"; + DevicePassword = DefaultPasswordForSimulator; + } + } + else if (DeviceClass == DialogDeviceClass.UsbDevice) + { + if (DeviceName != "USB") + { + DeviceName = "USB"; + DeviceIP = "169.254.0.1"; + } + + // got to Password control: + ActiveControl = txtPassword; + txtPassword.SelectionLength = 0; + txtPassword.SelectionStart = txtPassword.Text.Length; + return; + } + else + { + DeviceName = ""; + DeviceIP = ""; + DevicePassword = ""; + } + + // and to IP control: + GoToIPControl(); + } + + private void bttOK_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(DeviceIP) || string.IsNullOrEmpty(DevicePassword)) + { + MessageBoxHelper.Show("Sorry, some information is still missing. Fill in all fields", "Target Device", MessageBoxIcon.Error); + ActiveControl = string.IsNullOrEmpty(DeviceIP) ? txtIP : txtPassword; + return; + } + + if (IsDiscoverMode && PIN == 0) + { + MessageBoxHelper.Show("Sorry, no PIN found yet", "Target Device", MessageBoxIcon.Error); + ActiveControl = bttDiscover; + return; + } + + DialogResult = DialogResult.OK; + Close(); + } + + private void bttSetName_Click(object sender, EventArgs e) + { + txtName.Text = LoadedDeviceName; + } + + private void cmbNames_SelectedIndexChanged(object sender, EventArgs e) + { + var item = cmbNames.SelectedItem as ComboBoxItem; + var info = item != null ? item.Tag as DeviceDefinition : null; + + if (info != null) + { + DeviceIP = info.IP; + DevicePassword = info.Password; + } + else + { + DeviceIP = string.Empty; + DevicePassword = string.Empty; + } + } + } +} diff --git a/src_vs2012/Package/Dialogs/DeviceForm.resx b/src_vs2012/Package/Dialogs/DeviceForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/DeviceForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/FolderForm.Designer.cs b/src_vs2012/Package/Dialogs/FolderForm.Designer.cs new file mode 100644 index 00000000..6ac8c1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/FolderForm.Designer.cs @@ -0,0 +1,149 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class FolderForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.txtFolderName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.txtLocation = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.bttCancel = new System.Windows.Forms.Button(); + this.bttOK = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.txtFolderName); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.txtLocation); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(570, 106); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Properties"; + // + // txtFolderName + // + this.txtFolderName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtFolderName.Location = new System.Drawing.Point(75, 60); + this.txtFolderName.Name = "txtFolderName"; + this.txtFolderName.Size = new System.Drawing.Size(249, 20); + this.txtFolderName.TabIndex = 2; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(19, 63); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(38, 13); + this.label2.TabIndex = 1; + this.label2.Text = "Name:"; + // + // txtLocation + // + this.txtLocation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtLocation.Location = new System.Drawing.Point(75, 26); + this.txtLocation.Name = "txtLocation"; + this.txtLocation.ReadOnly = true; + this.txtLocation.Size = new System.Drawing.Size(474, 20); + this.txtLocation.TabIndex = 3; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(19, 29); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(51, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Location:"; + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(507, 124); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 2; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.Location = new System.Drawing.Point(426, 124); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 1; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + this.bttOK.Click += new System.EventHandler(this.bttOK_Click); + // + // FolderForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(594, 159); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.bttCancel); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FolderForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.TextBox txtFolderName; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox txtLocation; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/FolderForm.cs b/src_vs2012/Package/Dialogs/FolderForm.cs new file mode 100644 index 00000000..680a7f77 --- /dev/null +++ b/src_vs2012/Package/Dialogs/FolderForm.cs @@ -0,0 +1,44 @@ +using System.Windows.Forms; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class FolderForm : Form + { + public FolderForm(string title) + { + InitializeComponent(); + + Text = title; + } + + #region Properties + + public string FolderLocation + { + get { return txtLocation.Text; } + set { txtLocation.Text = value; } + } + + public string FolderName + { + get { return txtFolderName.Text; } + set { txtFolderName.Text = value; } + } + + #endregion + + private void bttOK_Click(object sender, System.EventArgs e) + { + if (string.IsNullOrEmpty(FolderName)) + { + MessageBoxHelper.Show("Name cannot be empty", null, MessageBoxButtons.OK, MessageBoxIcon.Warning); + ActiveControl = txtFolderName; + return; + } + + DialogResult = DialogResult.OK; + Close(); + } + } +} diff --git a/src_vs2012/Package/Dialogs/FolderForm.resx b/src_vs2012/Package/Dialogs/FolderForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/FolderForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/ImportProjectForm.Designer.cs b/src_vs2012/Package/Dialogs/ImportProjectForm.Designer.cs new file mode 100644 index 00000000..3e346603 --- /dev/null +++ b/src_vs2012/Package/Dialogs/ImportProjectForm.Designer.cs @@ -0,0 +1,436 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class ImportProjectForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.bttOK = new System.Windows.Forms.Button(); + this.bttCancel = new System.Windows.Forms.Button(); + this.txtSourceProject = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.txtIncludes = new System.Windows.Forms.TextBox(); + this.txtDependencies = new System.Windows.Forms.TextBox(); + this.txtDefines = new System.Windows.Forms.TextBox(); + this.chkAtSourceLocation = new System.Windows.Forms.CheckBox(); + this.chkCopyFiles = new System.Windows.Forms.CheckBox(); + this.txtDestinationName = new System.Windows.Forms.TextBox(); + this.cmbProjects = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.bttFindProject = new System.Windows.Forms.Button(); + this.txtWarnings = new System.Windows.Forms.TextBox(); + this.listFiles = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuFiles = new System.Windows.Forms.ContextMenuStrip(this.components); + this.contextToggleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextSeparatorMenuItem = new System.Windows.Forms.ToolStripSeparator(); + this.contextCheckMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.xToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextUncheckMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.yToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextRemoveMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.zToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.checkAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.uncheckAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.groupBox1.SuspendLayout(); + this.contextMenuFiles.SuspendLayout(); + this.SuspendLayout(); + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.Location = new System.Drawing.Point(406, 528); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 0; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + this.bttOK.Click += new System.EventHandler(this.bttOK_Click); + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(487, 528); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 1; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // txtSourceProject + // + this.txtSourceProject.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSourceProject.Location = new System.Drawing.Point(103, 22); + this.txtSourceProject.Name = "txtSourceProject"; + this.txtSourceProject.ReadOnly = true; + this.txtSourceProject.Size = new System.Drawing.Size(400, 20); + this.txtSourceProject.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(18, 25); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(79, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Source project:"; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.txtIncludes); + this.groupBox1.Controls.Add(this.txtDependencies); + this.groupBox1.Controls.Add(this.txtDefines); + this.groupBox1.Controls.Add(this.chkAtSourceLocation); + this.groupBox1.Controls.Add(this.chkCopyFiles); + this.groupBox1.Controls.Add(this.txtDestinationName); + this.groupBox1.Controls.Add(this.cmbProjects); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.bttFindProject); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.txtSourceProject); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(550, 186); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Project info"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(18, 154); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(66, 13); + this.label5.TabIndex = 12; + this.label5.Text = "Include Dirs:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(18, 128); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(49, 13); + this.label4.TabIndex = 10; + this.label4.Text = "Libraries:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(18, 102); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(46, 13); + this.label3.TabIndex = 8; + this.label3.Text = "Defines:"; + // + // txtIncludes + // + this.txtIncludes.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtIncludes.Location = new System.Drawing.Point(103, 151); + this.txtIncludes.Name = "txtIncludes"; + this.txtIncludes.Size = new System.Drawing.Size(400, 20); + this.txtIncludes.TabIndex = 13; + // + // txtDependencies + // + this.txtDependencies.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtDependencies.Location = new System.Drawing.Point(103, 125); + this.txtDependencies.Name = "txtDependencies"; + this.txtDependencies.Size = new System.Drawing.Size(400, 20); + this.txtDependencies.TabIndex = 11; + // + // txtDefines + // + this.txtDefines.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtDefines.Location = new System.Drawing.Point(103, 99); + this.txtDefines.Name = "txtDefines"; + this.txtDefines.Size = new System.Drawing.Size(400, 20); + this.txtDefines.TabIndex = 9; + // + // chkAtSourceLocation + // + this.chkAtSourceLocation.AutoSize = true; + this.chkAtSourceLocation.Checked = true; + this.chkAtSourceLocation.CheckState = System.Windows.Forms.CheckState.Checked; + this.chkAtSourceLocation.Enabled = false; + this.chkAtSourceLocation.ForeColor = System.Drawing.Color.Red; + this.chkAtSourceLocation.Location = new System.Drawing.Point(320, 76); + this.chkAtSourceLocation.Name = "chkAtSourceLocation"; + this.chkAtSourceLocation.Size = new System.Drawing.Size(179, 17); + this.chkAtSourceLocation.TabIndex = 7; + this.chkAtSourceLocation.Text = "Create at source project location"; + this.chkAtSourceLocation.UseVisualStyleBackColor = true; + this.chkAtSourceLocation.CheckedChanged += new System.EventHandler(this.chkAtSourceLocation_CheckedChanged); + // + // chkCopyFiles + // + this.chkCopyFiles.AutoSize = true; + this.chkCopyFiles.Checked = true; + this.chkCopyFiles.CheckState = System.Windows.Forms.CheckState.Checked; + this.chkCopyFiles.Location = new System.Drawing.Point(103, 76); + this.chkCopyFiles.Name = "chkCopyFiles"; + this.chkCopyFiles.Size = new System.Drawing.Size(106, 17); + this.chkCopyFiles.TabIndex = 6; + this.chkCopyFiles.Text = "Copy source files"; + this.chkCopyFiles.UseVisualStyleBackColor = true; + // + // txtDestinationName + // + this.txtDestinationName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtDestinationName.Location = new System.Drawing.Point(320, 48); + this.txtDestinationName.Name = "txtDestinationName"; + this.txtDestinationName.ReadOnly = true; + this.txtDestinationName.Size = new System.Drawing.Size(183, 20); + this.txtDestinationName.TabIndex = 5; + this.txtDestinationName.TextChanged += new System.EventHandler(this.txtDestinationName_TextChanged); + // + // cmbProjects + // + this.cmbProjects.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbProjects.FormattingEnabled = true; + this.cmbProjects.Location = new System.Drawing.Point(103, 48); + this.cmbProjects.Name = "cmbProjects"; + this.cmbProjects.Size = new System.Drawing.Size(211, 21); + this.cmbProjects.TabIndex = 4; + this.cmbProjects.SelectedIndexChanged += new System.EventHandler(this.cmbProjects_SelectedIndexChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(18, 51); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(63, 13); + this.label2.TabIndex = 3; + this.label2.Text = "Destination:"; + // + // bttFindProject + // + this.bttFindProject.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttFindProject.Location = new System.Drawing.Point(509, 21); + this.bttFindProject.Name = "bttFindProject"; + this.bttFindProject.Size = new System.Drawing.Size(35, 23); + this.bttFindProject.TabIndex = 2; + this.bttFindProject.Text = "..."; + this.bttFindProject.UseVisualStyleBackColor = true; + this.bttFindProject.Click += new System.EventHandler(this.bttFindProject_Click); + // + // txtWarnings + // + this.txtWarnings.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtWarnings.Location = new System.Drawing.Point(12, 462); + this.txtWarnings.Multiline = true; + this.txtWarnings.Name = "txtWarnings"; + this.txtWarnings.ReadOnly = true; + this.txtWarnings.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtWarnings.Size = new System.Drawing.Size(550, 60); + this.txtWarnings.TabIndex = 4; + this.txtWarnings.Text = "All colliding files will be overwritten without notice."; + // + // listFiles + // + this.listFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listFiles.CheckBoxes = true; + this.listFiles.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1}); + this.listFiles.ContextMenuStrip = this.contextMenuFiles; + this.listFiles.FullRowSelect = true; + this.listFiles.GridLines = true; + this.listFiles.HideSelection = false; + this.listFiles.Location = new System.Drawing.Point(12, 204); + this.listFiles.Name = "listFiles"; + this.listFiles.Size = new System.Drawing.Size(550, 252); + this.listFiles.TabIndex = 3; + this.listFiles.UseCompatibleStateImageBehavior = false; + this.listFiles.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Relative location"; + this.columnHeader1.Width = 520; + // + // contextMenuFiles + // + this.contextMenuFiles.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.contextToggleMenuItem, + this.contextSeparatorMenuItem, + this.contextCheckMenuItem, + this.contextUncheckMenuItem, + this.contextRemoveMenuItem, + this.checkAllToolStripMenuItem, + this.uncheckAllToolStripMenuItem}); + this.contextMenuFiles.Name = "contextMenuFiles"; + this.contextMenuFiles.Size = new System.Drawing.Size(139, 142); + this.contextMenuFiles.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuFiles_Opening); + // + // contextToggleMenuItem + // + this.contextToggleMenuItem.Name = "contextToggleMenuItem"; + this.contextToggleMenuItem.Size = new System.Drawing.Size(138, 22); + this.contextToggleMenuItem.Text = "&Toggle item"; + this.contextToggleMenuItem.Click += new System.EventHandler(this.contextToggleMenuItem_Click); + // + // contextSeparatorMenuItem + // + this.contextSeparatorMenuItem.Name = "contextSeparatorMenuItem"; + this.contextSeparatorMenuItem.Size = new System.Drawing.Size(135, 6); + // + // contextCheckMenuItem + // + this.contextCheckMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.xToolStripMenuItem}); + this.contextCheckMenuItem.Name = "contextCheckMenuItem"; + this.contextCheckMenuItem.Size = new System.Drawing.Size(138, 22); + this.contextCheckMenuItem.Text = "&Check"; + // + // xToolStripMenuItem + // + this.xToolStripMenuItem.Name = "xToolStripMenuItem"; + this.xToolStripMenuItem.Size = new System.Drawing.Size(79, 22); + this.xToolStripMenuItem.Text = "x"; + // + // contextUncheckMenuItem + // + this.contextUncheckMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.yToolStripMenuItem}); + this.contextUncheckMenuItem.Name = "contextUncheckMenuItem"; + this.contextUncheckMenuItem.Size = new System.Drawing.Size(138, 22); + this.contextUncheckMenuItem.Text = "&Uncheck"; + // + // yToolStripMenuItem + // + this.yToolStripMenuItem.Name = "yToolStripMenuItem"; + this.yToolStripMenuItem.Size = new System.Drawing.Size(80, 22); + this.yToolStripMenuItem.Text = "y"; + // + // contextRemoveMenuItem + // + this.contextRemoveMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.zToolStripMenuItem}); + this.contextRemoveMenuItem.Name = "contextRemoveMenuItem"; + this.contextRemoveMenuItem.Size = new System.Drawing.Size(138, 22); + this.contextRemoveMenuItem.Text = "&Remove"; + // + // zToolStripMenuItem + // + this.zToolStripMenuItem.Name = "zToolStripMenuItem"; + this.zToolStripMenuItem.Size = new System.Drawing.Size(79, 22); + this.zToolStripMenuItem.Text = "z"; + // + // checkAllToolStripMenuItem + // + this.checkAllToolStripMenuItem.Name = "checkAllToolStripMenuItem"; + this.checkAllToolStripMenuItem.Size = new System.Drawing.Size(138, 22); + this.checkAllToolStripMenuItem.Text = "Check all"; + this.checkAllToolStripMenuItem.Click += new System.EventHandler(this.checkAllToolStripMenuItem_Click); + // + // uncheckAllToolStripMenuItem + // + this.uncheckAllToolStripMenuItem.Name = "uncheckAllToolStripMenuItem"; + this.uncheckAllToolStripMenuItem.Size = new System.Drawing.Size(138, 22); + this.uncheckAllToolStripMenuItem.Text = "&Uncheck all"; + this.uncheckAllToolStripMenuItem.Click += new System.EventHandler(this.uncheckAllToolStripMenuItem_Click); + // + // ImportProjectForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(574, 563); + this.Controls.Add(this.listFiles); + this.Controls.Add(this.txtWarnings); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.bttCancel); + this.Controls.Add(this.bttOK); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(460, 360); + this.Name = "ImportProjectForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Import Momentics Project"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.contextMenuFiles.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.TextBox txtSourceProject; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttFindProject; + private System.Windows.Forms.CheckBox chkCopyFiles; + private System.Windows.Forms.TextBox txtDestinationName; + private System.Windows.Forms.ComboBox cmbProjects; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox txtWarnings; + private System.Windows.Forms.CheckBox chkAtSourceLocation; + private System.Windows.Forms.ListView listFiles; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtDependencies; + private System.Windows.Forms.TextBox txtDefines; + private System.Windows.Forms.ContextMenuStrip contextMenuFiles; + private System.Windows.Forms.ToolStripMenuItem contextToggleMenuItem; + private System.Windows.Forms.ToolStripSeparator contextSeparatorMenuItem; + private System.Windows.Forms.ToolStripMenuItem contextUncheckMenuItem; + private System.Windows.Forms.ToolStripMenuItem contextRemoveMenuItem; + private System.Windows.Forms.ToolStripMenuItem contextCheckMenuItem; + private System.Windows.Forms.ToolStripMenuItem xToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem yToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem zToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem checkAllToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem uncheckAllToolStripMenuItem; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox txtIncludes; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/ImportProjectForm.cs b/src_vs2012/Package/Dialogs/ImportProjectForm.cs new file mode 100644 index 00000000..8d60c4ec --- /dev/null +++ b/src_vs2012/Package/Dialogs/ImportProjectForm.cs @@ -0,0 +1,592 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Text; +using System.Windows.Forms; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Components; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.Model.Integration; +using BlackBerry.Package.ViewModels; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.VCProjectEngine; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class ImportProjectForm : Form + { + private const string SeparatorChar = ";"; + private readonly char[] Separators = { ' ', '\t', ';' }; + + private readonly ImportProjectViewModel _vm; + private Solution _solution; + private string _newProjectName; + + public ImportProjectForm() + { + InitializeComponent(); + _vm = new ImportProjectViewModel(); + } + + #region Properties + + public string SourceProjectPath + { + get { return txtSourceProject.Text; } + set + { + if (!string.IsNullOrEmpty(value)) + { + SetSourceProject(value); + } + } + } + + public string SourcePath + { + get; + private set; + } + + public bool CopyFiles + { + get { return chkCopyFiles.Checked; } + set { chkCopyFiles.Checked = value; } + } + + public bool IsNativeCoreAppSelected + { + get { return cmbProjects.SelectedIndex == 0; } + set { cmbProjects.SelectedIndex = 0; } + } + + public bool IsCascadesAppSelected + { + get { return cmbProjects.SelectedIndex == 1; } + set + { + if (cmbProjects.Items.Count > 1) + { + cmbProjects.SelectedIndex = 1; + } + } + } + + public bool IsNewProjectSelected + { + get { return IsNativeCoreAppSelected || IsCascadesAppSelected; } + } + + public bool IsSaveAtSourceLocation + { + get { return chkAtSourceLocation.Checked; } + set { chkAtSourceLocation.Checked = value; } + } + + public bool BuildOutputDependsOnTargetArch + { + get; + private set; + } + + #endregion + + public void SetSourceProject(string path) + { + if (string.IsNullOrEmpty(path)) + throw new ArgumentNullException("path"); + + txtSourceProject.Text = path; + SourcePath = Path.GetDirectoryName(path); + + // load info about the project: + var info = ImportProjectInfo.Load(SourcePath); + + _newProjectName = info != null ? info.Name : "NewProject"; + txtDestinationName.Text = _newProjectName; + txtDefines.Text = info != null ? AsString(SeparatorChar, info.Defines) : null; + txtDependencies.Text = info != null ? AsString(SeparatorChar, info.Dependencies) : null; + txtIncludes.Text = info != null ? AsString(SeparatorChar, info.IncludeDirectories) : null; + BuildOutputDependsOnTargetArch = info != null && info.BuildOutputDependsOnTargetArch; + listFiles.Items.Clear(); + + bool isCascadesProject = false; + + if (info != null && info.Files.Length > 0) + { + foreach (var file in info.Files) + { + if (file.EndsWith(".qml")) + { + isCascadesProject = true; + } + + var item = new ListViewItem(string.IsNullOrEmpty(SourcePath) || !file.StartsWith(SourcePath) ? file : file.Substring(SourcePath.Length + 1)); + item.Checked = true; + item.Tag = file; + listFiles.Items.Add(item); + } + } + + cmbProjects.SelectedIndex = isCascadesProject ? 1 : 0; + UpdateSummary(); + } + + private static string AsString(string separator, IEnumerable list) + { + return string.Join(separator, list); + } + + /// + /// Start a file-open dialog for the Momentics project file. + /// + public bool UpdateSourceProject() + { + var form = DialogHelper.OpenNativeCoreProject("Open Momentics Project", null); + + if (form.ShowDialog() == DialogResult.OK) + { + SetSourceProject(form.FileName); + return true; + } + + return false; + } + + /// + /// Initializes the UI with 'new projects' section and projects from the current solution. + /// + public void AddTargetProjects(Solution solution) + { + cmbProjects.Items.Clear(); + cmbProjects.Items.Add(new ComboBoxItem("New Native Core project", null)); + cmbProjects.Items.Add(new ComboBoxItem("New Cascades project", null)); + + _solution = solution; + if (solution != null) + { + foreach (Project project in solution.Projects) + { + if (BuildPlatformsManager.IsBlackBerryProject(project)) + { + cmbProjects.Items.Add(new ComboBoxItem(project.Name, project)); + } + } + } + } + + private void bttFindProject_Click(object sender, EventArgs e) + { + UpdateSourceProject(); + } + + private void cmbProjects_SelectedIndexChanged(object sender, EventArgs e) + { + var item = cmbProjects.SelectedItem; + object tag = item != null ? ((ComboBoxItem) item).Tag : null; + var itemAsProject = tag as Project; + + txtDestinationName.ReadOnly = item == null || itemAsProject != null; + txtDestinationName.Text = itemAsProject != null ? itemAsProject.Name : _newProjectName; + chkAtSourceLocation.Enabled = !txtDestinationName.ReadOnly; + + UpdateSummary(); + } + + /// + /// Creates new project or returns existing one (selected by developer), where all new sources should be placed. + /// + public Project PrepareProject(DTE2 dte) + { + if (dte == null) + throw new ArgumentNullException("dte"); + + var item = cmbProjects.SelectedItem; + object tag = ((ComboBoxItem) item).Tag; + var itemAsProject = tag as Project; + + if (itemAsProject != null) + { + _vm.UpdateProject(itemAsProject, txtDefines.Text.Split(Separators, StringSplitOptions.RemoveEmptyEntries), + txtDependencies.Text.Split(Separators, StringSplitOptions.RemoveEmptyEntries), + txtIncludes.Text.Split(Separators, StringSplitOptions.RemoveEmptyEntries), + false, false); + return itemAsProject; + } + + // create new NativeCore or Cascades project: + return _vm.CreateProject(dte, _newProjectName, IsNativeCoreAppSelected, IsSaveAtSourceLocation ? SourcePath : null, + txtDefines.Text.Split(Separators, StringSplitOptions.RemoveEmptyEntries), + txtDependencies.Text.Split(Separators, StringSplitOptions.RemoveEmptyEntries), + txtIncludes.Text.Split(Separators, StringSplitOptions.RemoveEmptyEntries), + BuildOutputDependsOnTargetArch); + } + + /// + /// Creates new project or takes existing (depending on developer selection) and puts there all the sources. + /// + public Project FillProject(DTE2 dte) + { + if (dte == null) + throw new ArgumentNullException("dte"); + + var project = PrepareProject(dte); + if (project == null) + return null; + + // copy files and add them into project: + VCProject vcProject = project.Object as VCProject; + if (vcProject == null) + return null; + + bool copyFile = IsNativeCoreAppSelected || IsCascadesAppSelected ? CopyFiles && !IsSaveAtSourceLocation : CopyFiles; + string projectDir = Path.GetDirectoryName(project.FullName); + + // add only checked items to the project: + foreach (ListViewItem item in listFiles.CheckedItems) + { + _vm.AddFileToProject(projectDir, item.Tag.ToString(), item.Text, copyFile, true); + } + + project.Save(); + return project; + } + + private void txtDestinationName_TextChanged(object sender, EventArgs e) + { + var item = cmbProjects.SelectedItem as ComboBoxItem; + if (item != null) + { + _newProjectName = txtDestinationName.Text; + } + + UpdateSummary(); + } + + private void UpdateSummary() + { + var comment = new StringBuilder(); + + comment.AppendLine("All colliding files will be overwritten without notice."); + + if (IsNewProjectSelected) + { + if (string.IsNullOrEmpty(_newProjectName)) + { + comment.AppendLine("Project creation will fail as its name is empty!"); + } + else + { + if (SolutionHasProject(_solution, _newProjectName)) + { + comment.AppendLine("Project creation will fail as its already taken."); + if (cmbProjects.Items.Count > 2) + { + comment.AppendLine("To merged it, select project with the same name from the list."); + } + } + else + { + if (chkAtSourceLocation.Checked) + { + comment.AppendLine("Project will be placed next to the existing source-code."); + } + } + } + + if (_vm.Author != null) + { + comment.AppendLine("Author will be updated to: " + _vm.Author.Name); + } + } + + txtWarnings.Text = comment.ToString(); + } + + private void bttOK_Click(object sender, EventArgs e) + { + // verify inputs: + if (IsNewProjectSelected) + { + if (string.IsNullOrEmpty(_newProjectName)) + { + MessageBoxHelper.Show("Sorry, name of the new project can't be empty", "Validation failed", MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = txtDestinationName; + return; + } + + if (SolutionHasProject(_solution, _newProjectName)) + { + MessageBoxHelper.Show("Project with name \"" + _newProjectName + "\" already exists inside the solution", "Validation failed", MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = txtDestinationName; + return; + } + } + + DialogResult = DialogResult.OK; + Close(); + } + + /// + /// Checks, if project with specified name is already inside the solution. + /// + private static bool SolutionHasProject(Solution solution, string projectName) + { + if (solution == null) + return false; + if (string.IsNullOrEmpty(projectName)) + return false; + + foreach (Project project in solution.Projects) + { + if (string.Compare(projectName, project.Name, StringComparison.OrdinalIgnoreCase) == 0) + return true; + } + + return false; + } + + private void contextMenuFiles_Opening(object sender, CancelEventArgs e) + { + if (listFiles.SelectedItems.Count == 0) + { + e.Cancel = true; + return; + } + + e.Cancel = false; + var folders = GetFolderNames(listFiles.SelectedItems, SourcePath); + + contextCheckMenuItem.DropDownItems.Clear(); + contextUncheckMenuItem.DropDownItems.Clear(); + contextRemoveMenuItem.DropDownItems.Clear(); + + contextToggleMenuItem.Text = listFiles.SelectedItems.Count > 1 ? "Toggle items" : "Toggle item"; + + if (folders != null) + { + bool allChecked = AreAllChecked(listFiles.SelectedItems); + bool allUnchecked = AreAllUnchecked(listFiles.SelectedItems); + + if (!allChecked) + { + foreach (var folder in folders) + { + var item = new ToolStripMenuItem(folder + "/*"); + item.Click += CheckForFolderButton; + item.Tag = folder; + + contextCheckMenuItem.DropDownItems.Add(item); + } + } + + if (!allUnchecked) + { + foreach (var folder in folders) + { + var item = new ToolStripMenuItem(folder + "/*"); + item.Click += UncheckForFolderButton; + item.Tag = folder; + + contextUncheckMenuItem.DropDownItems.Add(item); + } + } + + foreach (var folder in folders) + { + var item = new ToolStripMenuItem(folder + "/*"); + item.Click += RemoveForFolderButton; + item.Tag = folder; + + contextRemoveMenuItem.DropDownItems.Add(item); + } + + checkAllToolStripMenuItem.Visible = false; + uncheckAllToolStripMenuItem.Visible = false; + } + else + { + checkAllToolStripMenuItem.Visible = true; + uncheckAllToolStripMenuItem.Visible = true; + } + + contextCheckMenuItem.Visible = contextCheckMenuItem.DropDownItems.Count > 0; + contextUncheckMenuItem.Visible = contextUncheckMenuItem.DropDownItems.Count > 0; + contextRemoveMenuItem.Visible = contextRemoveMenuItem.DropDownItems.Count > 0; + } + + private bool AreAllUnchecked(ListView.SelectedListViewItemCollection items) + { + if (items == null) + return false; + + foreach (ListViewItem item in items) + { + if (item.Checked) + return false; + } + + return true; + } + + private bool AreAllChecked(ListView.SelectedListViewItemCollection items) + { + if (items == null) + return false; + + foreach (ListViewItem item in items) + { + if (!item.Checked) + return false; + } + + return true; + } + + private static IEnumerable GetFolderNames(ListView.SelectedListViewItemCollection activeItems, string sourcePath) + { + if (activeItems == null || activeItems.Count == 0) + return null; + + var result = new List(); + var buffer = new StringBuilder(); + + foreach (ListViewItem item in activeItems) + { + var fileName = item.Tag != null ? item.Tag.ToString() : null; + if (string.IsNullOrEmpty(fileName)) + continue; + + if (!string.IsNullOrEmpty(sourcePath) && fileName.StartsWith(sourcePath)) + { + fileName = fileName.Substring(sourcePath.Length); + } + else + { + if (fileName.Length > 1 && fileName[1] == Path.VolumeSeparatorChar) + { + fileName = fileName.Substring(2); + } + } + + var chunks = fileName.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); + + for (int i = 0; i < chunks.Length - 1; i++) + { + buffer.Remove(0, buffer.Length); + + for (int j = 0; j <= i; j++) + { + buffer.Append(chunks[j]); + if (j != i) + { + buffer.Append('/'); + } + } + + var pathPart = buffer.ToString(); + if (!result.Contains(pathPart)) + { + result.Add(pathPart); + } + } + } + + return result.Count == 0 ? null : result; + } + + private static bool Matches(ListViewItem item, string path) + { + return item != null && !string.IsNullOrEmpty(path) && item.Text.StartsWith(path, StringComparison.Ordinal); + } + + private void CheckForFolderButton(object sender, EventArgs eventArgs) + { + var contextMenu = (ToolStripMenuItem) sender; + var partPath = contextMenu != null && contextMenu.Tag != null ? contextMenu.Tag.ToString().Replace('/', '\\') : null; + + if (partPath != null) + { + foreach (ListViewItem item in listFiles.Items) + { + if (Matches(item, partPath)) + { + item.Checked = true; + } + } + } + } + + private void UncheckForFolderButton(object sender, EventArgs eventArgs) + { + var contextMenu = (ToolStripMenuItem)sender; + var partPath = contextMenu != null && contextMenu.Tag != null ? contextMenu.Tag.ToString().Replace('/', '\\') : null; + + if (partPath != null) + { + foreach (ListViewItem item in listFiles.Items) + { + if (Matches(item, partPath)) + { + item.Checked = false; + } + } + } + } + + private void RemoveForFolderButton(object sender, EventArgs eventArgs) + { + var contextMenu = (ToolStripMenuItem)sender; + var partPath = contextMenu != null && contextMenu.Tag != null ? contextMenu.Tag.ToString().Replace('/', '\\') : null; + + if (partPath != null) + { + var toRemove = new List(); + + foreach (ListViewItem item in listFiles.Items) + { + if (Matches(item, partPath)) + { + toRemove.Add(item); + } + } + + foreach (var item in toRemove) + { + listFiles.Items.Remove(item); + } + } + } + + private void contextToggleMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem item in listFiles.SelectedItems) + { + item.Checked = !item.Checked; + } + } + + private void checkAllToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem item in listFiles.SelectedItems) + { + item.Checked = true; + } + } + + private void uncheckAllToolStripMenuItem_Click(object sender, EventArgs e) + { + foreach (ListViewItem item in listFiles.SelectedItems) + { + item.Checked = false; + } + } + + private void chkAtSourceLocation_CheckedChanged(object sender, EventArgs e) + { + UpdateSummary(); + } + } +} diff --git a/src_vs2012/Package/Dialogs/ImportProjectForm.resx b/src_vs2012/Package/Dialogs/ImportProjectForm.resx new file mode 100644 index 00000000..57f3574d --- /dev/null +++ b/src_vs2012/Package/Dialogs/ImportProjectForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/InstallConfirmationForm.Designer.cs b/src_vs2012/Package/Dialogs/InstallConfirmationForm.Designer.cs new file mode 100644 index 00000000..082fac02 --- /dev/null +++ b/src_vs2012/Package/Dialogs/InstallConfirmationForm.Designer.cs @@ -0,0 +1,142 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class InstallConfirmationForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.bttCancel = new System.Windows.Forms.Button(); + this.bttInstall = new System.Windows.Forms.Button(); + this.listView = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(9, 13); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(118, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Select version to install:"; + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(347, 212); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 3; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // bttInstall + // + this.bttInstall.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttInstall.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttInstall.Enabled = false; + this.bttInstall.Location = new System.Drawing.Point(266, 212); + this.bttInstall.Name = "bttInstall"; + this.bttInstall.Size = new System.Drawing.Size(75, 23); + this.bttInstall.TabIndex = 2; + this.bttInstall.Text = "&Install"; + this.bttInstall.UseVisualStyleBackColor = true; + // + // listView + // + this.listView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.listView.FullRowSelect = true; + this.listView.GridLines = true; + this.listView.HideSelection = false; + this.listView.Location = new System.Drawing.Point(12, 29); + this.listView.Name = "listView"; + this.listView.Size = new System.Drawing.Size(410, 173); + this.listView.TabIndex = 1; + this.listView.UseCompatibleStateImageBehavior = false; + this.listView.View = System.Windows.Forms.View.Details; + this.listView.SelectedIndexChanged += new System.EventHandler(this.listView_SelectedIndexChanged); + this.listView.DoubleClick += new System.EventHandler(this.listView_DoubleClick); + // + // columnHeader1 + // + this.columnHeader1.Text = "Name"; + this.columnHeader1.Width = 200; + // + // columnHeader2 + // + this.columnHeader2.Text = "Version"; + this.columnHeader2.Width = 80; + // + // columnHeader3 + // + this.columnHeader3.Text = "State"; + this.columnHeader3.Width = 90; + // + // InstallConfirmationForm + // + this.AcceptButton = this.bttInstall; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(434, 247); + this.Controls.Add(this.listView); + this.Controls.Add(this.bttInstall); + this.Controls.Add(this.bttCancel); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InstallConfirmationForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Confirmation"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.Button bttInstall; + private System.Windows.Forms.ListView listView; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/InstallConfirmationForm.cs b/src_vs2012/Package/Dialogs/InstallConfirmationForm.cs new file mode 100644 index 00000000..9328c3b9 --- /dev/null +++ b/src_vs2012/Package/Dialogs/InstallConfirmationForm.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.Package.Dialogs +{ + /// + /// Dialog to show and select list of available versions per particular API Level. + /// + internal partial class InstallConfirmationForm : Form + { + public InstallConfirmationForm(string nameOverride, IEnumerable items, ApiLevelTarget target, Func installationCheckHandler, Func processingCheckHandler) + { + if (items == null) + throw new ArgumentNullException("items"); + + InitializeComponent(); + + foreach (var item in items) + { + var i = new ListViewItem(); + i.Tag = item; + i.Text = string.IsNullOrEmpty(nameOverride) || item.IsBeta ? CleanName(item.Name, item.Version, item.Level) : nameOverride; + i.SubItems.Add(item.Version.ToString()); + + // display status, if it's installed or is still under processing: + if (processingCheckHandler != null && processingCheckHandler(item, target)) + { + i.SubItems.Add("Processing..."); + } + else + { + if (installationCheckHandler != null && installationCheckHandler(item, target)) + i.SubItems.Add("Installed"); + } + + listView.Items.Insert(0, i); + } + } + + private static string CleanName(string text, Version version, Version level) + { + return text.Replace(version.ToString(), string.Empty).Replace(level.ToString(), string.Empty).Trim(); + } + + #region Properties + + public ApiInfo SelectedItem + { + get { return listView.SelectedItems.Count > 0 ? (ApiInfo) listView.SelectedItems[0].Tag : null; } + } + + #endregion + + private void listView_SelectedIndexChanged(object sender, EventArgs e) + { + bttInstall.Enabled = listView.SelectedIndices.Count > 0 && listView.SelectedItems[0].SubItems.Count <= 2; + } + + private void listView_DoubleClick(object sender, EventArgs e) + { + if (bttInstall.Enabled && SelectedItem != null) + { + DialogResult = bttInstall.DialogResult; + Close(); + } + } + } +} diff --git a/src_vs2012/Package/Dialogs/InstallConfirmationForm.resx b/src_vs2012/Package/Dialogs/InstallConfirmationForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/InstallConfirmationForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/InstallForm.Designer.cs b/src_vs2012/Package/Dialogs/InstallForm.Designer.cs new file mode 100644 index 00000000..e11dd3e2 --- /dev/null +++ b/src_vs2012/Package/Dialogs/InstallForm.Designer.cs @@ -0,0 +1,320 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class InstallForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bttOK = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.panelInstalledNDKs = new System.Windows.Forms.FlowLayoutPanel(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.panelAvailableNDKs = new System.Windows.Forms.FlowLayoutPanel(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.panelAvailableSimulators = new System.Windows.Forms.FlowLayoutPanel(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.panelInstalledSimulators = new System.Windows.Forms.FlowLayoutPanel(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabControl = new System.Windows.Forms.TabControl(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.panelAvailableRuntimes = new System.Windows.Forms.FlowLayoutPanel(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.panelInstalledRuntimes = new System.Windows.Forms.FlowLayoutPanel(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabControl.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.groupBox6.SuspendLayout(); + this.SuspendLayout(); + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttOK.Location = new System.Drawing.Point(758, 462); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 0; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.panelInstalledNDKs); + this.groupBox1.Location = new System.Drawing.Point(6, 6); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(804, 197); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Installed"; + // + // panelInstalledNDKs + // + this.panelInstalledNDKs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panelInstalledNDKs.AutoScroll = true; + this.panelInstalledNDKs.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.panelInstalledNDKs.Location = new System.Drawing.Point(6, 19); + this.panelInstalledNDKs.Name = "panelInstalledNDKs"; + this.panelInstalledNDKs.Size = new System.Drawing.Size(792, 172); + this.panelInstalledNDKs.TabIndex = 0; + this.panelInstalledNDKs.WrapContents = false; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.panelAvailableNDKs); + this.groupBox2.Location = new System.Drawing.Point(6, 210); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(804, 197); + this.groupBox2.TabIndex = 2; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Available"; + // + // panelAvailableNDKs + // + this.panelAvailableNDKs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panelAvailableNDKs.AutoScroll = true; + this.panelAvailableNDKs.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.panelAvailableNDKs.Location = new System.Drawing.Point(6, 19); + this.panelAvailableNDKs.Name = "panelAvailableNDKs"; + this.panelAvailableNDKs.Size = new System.Drawing.Size(792, 172); + this.panelAvailableNDKs.TabIndex = 0; + this.panelAvailableNDKs.WrapContents = false; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.groupBox4); + this.tabPage2.Controls.Add(this.groupBox3); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(819, 418); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Simulator"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // groupBox4 + // + this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox4.Controls.Add(this.panelAvailableSimulators); + this.groupBox4.Location = new System.Drawing.Point(6, 210); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(804, 197); + this.groupBox4.TabIndex = 3; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Available"; + // + // panelAvailableSimulators + // + this.panelAvailableSimulators.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panelAvailableSimulators.AutoScroll = true; + this.panelAvailableSimulators.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.panelAvailableSimulators.Location = new System.Drawing.Point(6, 19); + this.panelAvailableSimulators.Name = "panelAvailableSimulators"; + this.panelAvailableSimulators.Size = new System.Drawing.Size(792, 172); + this.panelAvailableSimulators.TabIndex = 0; + this.panelAvailableSimulators.WrapContents = false; + // + // groupBox3 + // + this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox3.Controls.Add(this.panelInstalledSimulators); + this.groupBox3.Location = new System.Drawing.Point(6, 6); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(804, 197); + this.groupBox3.TabIndex = 2; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Installed"; + // + // panelInstalledSimulators + // + this.panelInstalledSimulators.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panelInstalledSimulators.AutoScroll = true; + this.panelInstalledSimulators.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.panelInstalledSimulators.Location = new System.Drawing.Point(6, 19); + this.panelInstalledSimulators.Name = "panelInstalledSimulators"; + this.panelInstalledSimulators.Size = new System.Drawing.Size(792, 172); + this.panelInstalledSimulators.TabIndex = 0; + this.panelInstalledSimulators.WrapContents = false; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.groupBox1); + this.tabPage1.Controls.Add(this.groupBox2); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(819, 418); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Native SDK"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabControl + // + this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabControl.Controls.Add(this.tabPage1); + this.tabControl.Controls.Add(this.tabPage2); + this.tabControl.Controls.Add(this.tabPage3); + this.tabControl.Location = new System.Drawing.Point(6, 6); + this.tabControl.Name = "tabControl"; + this.tabControl.SelectedIndex = 0; + this.tabControl.Size = new System.Drawing.Size(827, 444); + this.tabControl.TabIndex = 3; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.groupBox5); + this.tabPage3.Controls.Add(this.groupBox6); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(819, 418); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Runtime Library"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // groupBox5 + // + this.groupBox5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox5.Controls.Add(this.panelAvailableRuntimes); + this.groupBox5.Location = new System.Drawing.Point(6, 210); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(804, 197); + this.groupBox5.TabIndex = 5; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Available"; + // + // panelAvailableRuntimes + // + this.panelAvailableRuntimes.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panelAvailableRuntimes.AutoScroll = true; + this.panelAvailableRuntimes.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.panelAvailableRuntimes.Location = new System.Drawing.Point(6, 19); + this.panelAvailableRuntimes.Name = "panelAvailableRuntimes"; + this.panelAvailableRuntimes.Size = new System.Drawing.Size(792, 172); + this.panelAvailableRuntimes.TabIndex = 0; + this.panelAvailableRuntimes.WrapContents = false; + // + // groupBox6 + // + this.groupBox6.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox6.Controls.Add(this.panelInstalledRuntimes); + this.groupBox6.Location = new System.Drawing.Point(6, 6); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(804, 197); + this.groupBox6.TabIndex = 4; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Installed"; + // + // panelInstalledRuntimes + // + this.panelInstalledRuntimes.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panelInstalledRuntimes.AutoScroll = true; + this.panelInstalledRuntimes.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.panelInstalledRuntimes.Location = new System.Drawing.Point(6, 19); + this.panelInstalledRuntimes.Name = "panelInstalledRuntimes"; + this.panelInstalledRuntimes.Size = new System.Drawing.Size(792, 172); + this.panelInstalledRuntimes.TabIndex = 0; + this.panelInstalledRuntimes.WrapContents = false; + // + // InstallForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttOK; + this.ClientSize = new System.Drawing.Size(845, 497); + this.Controls.Add(this.tabControl); + this.Controls.Add(this.bttOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InstallForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Installation"; + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.groupBox4.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabControl.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.groupBox5.ResumeLayout(false); + this.groupBox6.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.FlowLayoutPanel panelInstalledNDKs; + private System.Windows.Forms.FlowLayoutPanel panelAvailableNDKs; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabControl tabControl; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.FlowLayoutPanel panelAvailableSimulators; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.FlowLayoutPanel panelInstalledSimulators; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.FlowLayoutPanel panelAvailableRuntimes; + private System.Windows.Forms.GroupBox groupBox6; + private System.Windows.Forms.FlowLayoutPanel panelInstalledRuntimes; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/InstallForm.cs b/src_vs2012/Package/Dialogs/InstallForm.cs new file mode 100644 index 00000000..2fd4ef22 --- /dev/null +++ b/src_vs2012/Package/Dialogs/InstallForm.cs @@ -0,0 +1,254 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class InstallForm : Form + { + #region Private Classes + + /// + /// Class to order APIs from higher to lower numbers. + /// + class DescApiComparer : IComparer + { + public int Compare(ApiInfoArray x, ApiInfoArray y) + { + if (x == null && y == null) + return 0; + if (x == null) + return 1; + if (y == null) + return -1; + + return y.Version.CompareTo(x.Version); + } + } + + #endregion + + private readonly ApiLevelOptionViewModel _vm; + + public InstallForm(ApiLevelOptionViewModel vm) + { + if (vm == null) + throw new ArgumentNullException("vm"); + + InitializeComponent(); + _vm = vm; + _vm.NdkListLoaded += NdkListLoaded; + _vm.SimulatorListLoaded += SimulatorListLoaded; + _vm.RuntimeListLoaded += RuntimeListLoaded; + _vm.UpdateManager.Completed += ApiLevelChanged; + + UpdateUI(); + } + + + #region Properties + + /// + /// Gets or sets the active tab. + /// + public int ActiveTab + { + get { return tabControl.SelectedIndex; } + set { tabControl.SelectedIndex = value; } + } + + #endregion + + private void UpdateUI() + { + PopulateList(panelInstalledNDKs, _vm.InstalledNDKs, ApiLevelTarget.NDK, (info, target) => _vm.GetTask(info, target), "No installed Native SDK found", ApiLevelTask.Hide); + PopulateList(panelInstalledSimulators, _vm.InstalledSimulators, ApiLevelTarget.Simulator, (info, target) => _vm.GetTask(info, target), "No installed simulators found", ApiLevelTask.Hide); + PopulateList(panelInstalledRuntimes, _vm.InstalledRuntimes, ApiLevelTarget.Runtime, (info, target) => _vm.GetTask(info, target), "No installed runtimes found", ApiLevelTask.Hide); + + LoadList(panelAvailableNDKs, ApiLevelTarget.NDK, false); + LoadList(panelAvailableSimulators, ApiLevelTarget.Simulator, false); + LoadList(panelAvailableRuntimes, ApiLevelTarget.Runtime, false); + } + + private void LoadList(Panel panel, ApiLevelTarget target, bool refresh) + { + if (_vm.Load(target, refresh)) + { + PopulateList(panel, null, target, null, "Loading...", ApiLevelTask.Hide); + } + } + + protected override void OnClosed(EventArgs e) + { + _vm.NdkListLoaded -= NdkListLoaded; + _vm.SimulatorListLoaded -= SimulatorListLoaded; + _vm.RuntimeListLoaded -= RuntimeListLoaded; + _vm.UpdateManager.Completed -= ApiLevelChanged; + base.OnClosed(e); + } + + private void NdkListLoaded(object sender, EventArgs eventArgs) + { + var suggested = (ApiInfoArray[]) _vm.RemoteNDKs.Clone(); + Array.Sort(suggested, new DescApiComparer()); + + PopulateList(panelAvailableNDKs, suggested, ApiLevelTarget.NDK, (info, target) => _vm.GetTask(info, target), "There was an error, while loading list of Native SDKs", ApiLevelTask.Refresh); + } + + private void SimulatorListLoaded(object sender, EventArgs e) + { + var suggested = (ApiInfoArray[])_vm.RemoteSimulators.Clone(); + Array.Sort(suggested, new DescApiComparer()); + + PopulateList(panelAvailableSimulators, suggested, ApiLevelTarget.Simulator, (info, target) => _vm.GetTask(info, target), "There was an error, while loading list of Simulators", ApiLevelTask.Refresh); + } + + private void RuntimeListLoaded(object sender, EventArgs e) + { + var suggested = (ApiInfoArray[])_vm.RemoteRuntimes.Clone(); + Array.Sort(suggested, new DescApiComparer()); + + PopulateList(panelAvailableRuntimes, suggested, ApiLevelTarget.Runtime, (info, target) => _vm.GetTask(info, target), "There was an error, while loading list of Runtime Libraries", ApiLevelTask.Refresh); + } + + private void ApiLevelChanged(object sender, EventArgs e) + { + _vm.Dispatcher.Invoke(UpdateUI); + } + + private void PopulateList(Panel panel, IEnumerable items, ApiLevelTarget target, Func actionEvaluation, string missingItemsMessage, ApiLevelTask missingItemsAction) + { + if (panel == null) + return; + + int itemsAdded = 0; + + panel.Controls.Clear(); + if (items != null) + { + foreach (var definition in items) + { + var item = new ListItemControl(); + + item.Width = panel.Width - SystemInformation.VerticalScrollBarWidth - 10; + item.Title = definition.Name; + item.Details = definition.Details; + item.Target = target; + item.Action = actionEvaluation != null ? actionEvaluation(definition, target) : ApiLevelTask.Hide; + item.Tag = definition; + item.ParentPanel = panel; + item.ExecuteAction += ItemOnExecuteAction; + + panel.Controls.Add(item); + itemsAdded++; + } + } + + if (itemsAdded == 0) + { + var item = new ListItemControl(); + item.Width = panel.Width - SystemInformation.VerticalScrollBarWidth - 10; + item.Title = missingItemsMessage; + item.Details = string.Empty; + item.Target = target; + item.ParentPanel = panel; + item.Action = missingItemsAction; + item.ExecuteAction += ItemOnExecuteAction; + + panel.Controls.Add(item); + } + } + + private void ItemOnExecuteAction(object sender, EventArgs eventArgs) + { + var listItem = (ListItemControl) sender; + var definition = listItem != null ? (ApiInfo) listItem.Tag : null; + var actionTarget = listItem != null ? listItem.Target : ApiLevelTarget.NDK; + var panel = listItem != null ? listItem.ParentPanel : null; + var action = listItem != null ? listItem.Action : ApiLevelTask.Nothing; + + if (definition != null) + { + object argument; + action = _vm.GetTask(definition, actionTarget, out argument); + + switch (action) + { + case ApiLevelTask.Install: + var apiInfoArray = definition as ApiInfoArray; + if (apiInfoArray != null) + { + var form = new InstallConfirmationForm(apiInfoArray.Name, apiInfoArray.Items, actionTarget, (info, target) => _vm.CheckIfInstalled(info, target), (info, target) => _vm.IsProcessing(info, target)); + if (form.ShowDialog() == DialogResult.OK) + { + var info = form.SelectedItem; + _vm.RequestInstall(info, actionTarget); + + MessageBoxHelper.Show("Scheduled \"" + info + "\" for installation. Be patient, this might take some time.\r\n\r\nProgress can be monitored by clicking Status in the BlackBerry -> Options -> API-Levels window.", + null, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + break; + case ApiLevelTask.InstallManually: + DialogHelper.StartURL((string)argument); + break; + case ApiLevelTask.AddExisting: + AddExistingNDK(); + break; + case ApiLevelTask.Forget: + if (MessageBoxHelper.Show(definition.ToString(), "Remove own reference to existing NDK?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + _vm.Forget(definition); + UpdateUI(); + } + break; + case ApiLevelTask.Uninstall: + if (MessageBoxHelper.Show(definition.ToString(), "Do you want to remove this item?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + _vm.RequestRemoval(definition, actionTarget); + UpdateUI(); + + MessageBoxHelper.Show("Scheduled \"" + definition + "\" for removal. Be patient, this might take some time.", + null, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + break; + } + } + + switch (action) + { + case ApiLevelTask.Refresh: + LoadList(panel, actionTarget, true); + break; + } + } + + private void AddExistingNDK() + { + var form = new AddLocalNdkForm(); + + if (form.ShowDialog() == DialogResult.OK) + { + var ndk = form.NewNdk; + if (ndk != null) + { + // save inside 'installation config' directory: + if (ndk.Save(ConfigDefaults.PluginInstallationConfigDirectory)) + { + // reload NDKs + _vm.Reset(ApiLevelTarget.NDK); + UpdateUI(); + } + else + { + MessageBoxHelper.Show("Unable to save NDK information", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + } + } +} diff --git a/src_vs2012/Package/Dialogs/InstallForm.resx b/src_vs2012/Package/Dialogs/InstallForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/InstallForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/ListItemControl.Designer.cs b/src_vs2012/Package/Dialogs/ListItemControl.Designer.cs new file mode 100644 index 00000000..dd3d5220 --- /dev/null +++ b/src_vs2012/Package/Dialogs/ListItemControl.Designer.cs @@ -0,0 +1,89 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class ListItemControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.lblTitle = new System.Windows.Forms.Label(); + this.lblDetails = new System.Windows.Forms.Label(); + this.bttAction = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // lblTitle + // + this.lblTitle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lblTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.lblTitle.Location = new System.Drawing.Point(3, 0); + this.lblTitle.Name = "lblTitle"; + this.lblTitle.Size = new System.Drawing.Size(444, 18); + this.lblTitle.TabIndex = 0; + this.lblTitle.Text = "[Title]"; + // + // lblDetails + // + this.lblDetails.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lblDetails.AutoEllipsis = true; + this.lblDetails.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.lblDetails.Location = new System.Drawing.Point(3, 19); + this.lblDetails.Name = "lblDetails"; + this.lblDetails.Size = new System.Drawing.Size(444, 13); + this.lblDetails.TabIndex = 1; + this.lblDetails.Text = "[Details]"; + // + // bttAction + // + this.bttAction.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttAction.Location = new System.Drawing.Point(453, 5); + this.bttAction.Name = "bttAction"; + this.bttAction.Size = new System.Drawing.Size(75, 23); + this.bttAction.TabIndex = 2; + this.bttAction.Text = "[Action]"; + this.bttAction.UseVisualStyleBackColor = true; + this.bttAction.Click += new System.EventHandler(this.bttAction_Click); + // + // ListItemControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.bttAction); + this.Controls.Add(this.lblDetails); + this.Controls.Add(this.lblTitle); + this.Name = "ListItemControl"; + this.Size = new System.Drawing.Size(528, 36); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label lblTitle; + private System.Windows.Forms.Label lblDetails; + private System.Windows.Forms.Button bttAction; + } +} diff --git a/src_vs2012/Package/Dialogs/ListItemControl.cs b/src_vs2012/Package/Dialogs/ListItemControl.cs new file mode 100644 index 00000000..25815b7a --- /dev/null +++ b/src_vs2012/Package/Dialogs/ListItemControl.cs @@ -0,0 +1,122 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore.Model; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class ListItemControl : UserControl + { + public event EventHandler ExecuteAction; + + private ApiLevelTask _action; + + public ListItemControl() + { + InitializeComponent(); + + Action = ApiLevelTask.Hide; + OnActionChanged(); + } + + #region Properties + + public string Title + { + get { return lblTitle.Text; } + set { lblTitle.Text = value; } + } + + public string Details + { + get { return lblDetails.Text; } + set { lblDetails.Text = value; } + } + + public string ActionName + { + get { return bttAction.Text; } + set { bttAction.Text = value; } + } + + public ApiLevelTask Action + { + get { return _action; } + set + { + if (_action != value) + { + _action = value; + OnActionChanged(); + } + } + } + + public ApiLevelTarget Target + { + get; + set; + } + + public Panel ParentPanel + { + get; + set; + } + + private void OnActionChanged() + { + bttAction.Enabled = true; + bttAction.Visible = true; + + switch (_action) + { + case ApiLevelTask.Hide: + ActionName = string.Empty; + bttAction.Visible = false; + break; + case ApiLevelTask.Nothing: + ActionName = "Locked"; + bttAction.Enabled = false; + break; + case ApiLevelTask.Install: + ActionName = "Install"; + break; + case ApiLevelTask.InstallManually: + ActionName = "Download..."; + break; + case ApiLevelTask.AddExisting: + ActionName = "Add..."; + break; + case ApiLevelTask.Uninstall: + ActionName = "Uninstall"; + break; + case ApiLevelTask.Forget: + ActionName = "Forget"; + break; + case ApiLevelTask.Refresh: + ActionName = "Reload"; + break; + + default: + throw new ArgumentOutOfRangeException("Specified action is not supported"); + } + } + + public object ActionArgument + { + get; + set; + } + + #endregion + + private void bttAction_Click(object sender, EventArgs e) + { + var actionHandler = ExecuteAction; + + // notify, that user requested to perform the action: + if (actionHandler != null) + actionHandler(this, e); + } + } +} diff --git a/src_vs2012/Package/Dialogs/ListItemControl.resx b/src_vs2012/Package/Dialogs/ListItemControl.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/ListItemControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.Designer.cs b/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.Designer.cs new file mode 100644 index 00000000..9d3af62e --- /dev/null +++ b/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.Designer.cs @@ -0,0 +1,169 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class MissingNdkInstalledForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + + if (disposing) + { + if (_vm != null) + { + _vm.Dispose(); + _vm = null; + } + } + + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bttClose = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.cmbNDKs = new System.Windows.Forms.ComboBox(); + this.bttInstall = new System.Windows.Forms.Button(); + this.bttStatus = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // bttClose + // + this.bttClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttClose.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttClose.Location = new System.Drawing.Point(361, 148); + this.bttClose.Name = "bttClose"; + this.bttClose.Size = new System.Drawing.Size(75, 23); + this.bttClose.TabIndex = 0; + this.bttClose.Text = "&Close"; + this.bttClose.UseVisualStyleBackColor = true; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.cmbNDKs); + this.groupBox1.Controls.Add(this.bttInstall); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(424, 130); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Selection"; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Location = new System.Drawing.Point(15, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(403, 66); + this.label1.TabIndex = 2; + this.label1.Text = "Toolset for building BlackBerry native application is missing. Make sure t" + + "here is any NDK installed and select it from the list below."; + // + // cmbNDKs + // + this.cmbNDKs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cmbNDKs.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbNDKs.FormattingEnabled = true; + this.cmbNDKs.Location = new System.Drawing.Point(15, 91); + this.cmbNDKs.Name = "cmbNDKs"; + this.cmbNDKs.Size = new System.Drawing.Size(322, 21); + this.cmbNDKs.TabIndex = 1; + this.cmbNDKs.SelectedIndexChanged += new System.EventHandler(this.cmbNDKs_SelectedIndexChanged); + // + // bttInstall + // + this.bttInstall.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttInstall.Location = new System.Drawing.Point(343, 89); + this.bttInstall.Name = "bttInstall"; + this.bttInstall.Size = new System.Drawing.Size(75, 23); + this.bttInstall.TabIndex = 0; + this.bttInstall.Text = "Install..."; + this.bttInstall.UseVisualStyleBackColor = true; + this.bttInstall.Click += new System.EventHandler(this.bttInstall_Click); + // + // bttStatus + // + this.bttStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttStatus.Location = new System.Drawing.Point(12, 148); + this.bttStatus.Name = "bttStatus"; + this.bttStatus.Size = new System.Drawing.Size(75, 23); + this.bttStatus.TabIndex = 2; + this.bttStatus.Text = "&Status..."; + this.bttStatus.UseVisualStyleBackColor = true; + this.bttStatus.Click += new System.EventHandler(this.bttStatus_Click); + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label2.Location = new System.Drawing.Point(15, 53); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(403, 32); + this.label2.TabIndex = 3; + this.label2.Text = "NOTE: It might take some time to download everything. You can close this dialog a" + + "nd continue coding, but you won\'t be able to build and deploy until all is finis" + + "hed."; + // + // MissingNdkInstalledForm + // + this.AcceptButton = this.bttClose; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttClose; + this.ClientSize = new System.Drawing.Size(448, 183); + this.Controls.Add(this.bttStatus); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.bttClose); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MissingNdkInstalledForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Default BlackBerry API Level selection"; + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button bttClose; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox cmbNDKs; + private System.Windows.Forms.Button bttInstall; + private System.Windows.Forms.Button bttStatus; + private System.Windows.Forms.Label label2; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.cs b/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.cs new file mode 100644 index 00000000..fc226d1e --- /dev/null +++ b/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.cs @@ -0,0 +1,97 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class MissingNdkInstalledForm : Form + { + private ApiLevelOptionViewModel _vm = new ApiLevelOptionViewModel(); + + public MissingNdkInstalledForm() + { + InitializeComponent(); + + _vm.Dispatcher = EventDispatcher.From(this); + _vm.UpdateManager.Completed += OnApiLevelChanged; + + PopulateNDKs(true); + } + + protected override void OnClosed(EventArgs e) + { + _vm.ActiveNDK = SelectedNDK; + _vm.UpdateManager.Completed -= OnApiLevelChanged; + base.OnClosed(e); + } + + private void OnApiLevelChanged(object sender, UpdateManagerCompletedEventArgs e) + { + PopulateNDKs(false); + } + + #region Properties + + public NdkInfo SelectedNDK + { + get { return cmbNDKs.SelectedItem as NdkInfo; } + set { cmbNDKs.SelectedItem = value; } + } + + #endregion + + private void PopulateNDKs(bool ignoreCurrentSelection) + { + NdkInfo currentlySelected = null; + + if (ignoreCurrentSelection) + { + currentlySelected = _vm.ActiveNDK; + } + else + { + if (SelectedNDK == null) + { + // select the last from the list, if possible: + SelectedNDK = _vm.GetLatestInstalledNDK(); + } + else + { + currentlySelected = SelectedNDK; + } + } + + // populate list of NDKs: + cmbNDKs.Items.Clear(); + foreach (var ndk in _vm.InstalledNDKs) + { + cmbNDKs.Items.Add(ndk); + } + + _vm.ActiveNDK = currentlySelected; // here the currentlySelected will cause a match-by-folders-search + cmbNDKs.SelectedItem = _vm.ActiveNDK; // and _vm.ActiveNDK != currentlySelected instances + } + + private void bttStatus_Click(object sender, EventArgs e) + { + var form = new UpdateManagerStatusForm(_vm); + form.ShowDialog(); + PopulateNDKs(false); + } + + private void bttInstall_Click(object sender, EventArgs e) + { + var form = new InstallForm(_vm); + form.ShowDialog(); + PopulateNDKs(false); + } + + private void cmbNDKs_SelectedIndexChanged(object sender, EventArgs e) + { + _vm.ActiveNDK = SelectedNDK; + } + } +} diff --git a/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.resx b/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/MissingNdkInstalledForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/PasswordForm.Designer.cs b/src_vs2012/Package/Dialogs/PasswordForm.Designer.cs new file mode 100644 index 00000000..8b2c68c6 --- /dev/null +++ b/src_vs2012/Package/Dialogs/PasswordForm.Designer.cs @@ -0,0 +1,153 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class PasswordForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label2 = new System.Windows.Forms.Label(); + this.txtPassword = new System.Windows.Forms.TextBox(); + this.bttCancel = new System.Windows.Forms.Button(); + this.bttOK = new System.Windows.Forms.Button(); + this.chkRemember = new System.Windows.Forms.CheckBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(20, 25); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(56, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Password:"; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.txtPassword); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(310, 79); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Input"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(20, 50); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(281, 13); + this.label2.TabIndex = 2; + this.label2.Text = "(password set when the BlackBerry ID token was created)"; + // + // txtPassword + // + this.txtPassword.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPassword.Location = new System.Drawing.Point(101, 22); + this.txtPassword.Name = "txtPassword"; + this.txtPassword.PasswordChar = '*'; + this.txtPassword.Size = new System.Drawing.Size(200, 20); + this.txtPassword.TabIndex = 1; + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(247, 97); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 3; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.Location = new System.Drawing.Point(166, 97); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 2; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + this.bttOK.Click += new System.EventHandler(this.bttOK_Click); + // + // chkRemember + // + this.chkRemember.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.chkRemember.AutoSize = true; + this.chkRemember.Location = new System.Drawing.Point(12, 101); + this.chkRemember.Name = "chkRemember"; + this.chkRemember.Size = new System.Drawing.Size(77, 17); + this.chkRemember.TabIndex = 1; + this.chkRemember.Text = "Remember"; + this.chkRemember.UseVisualStyleBackColor = true; + // + // PasswordForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(334, 132); + this.Controls.Add(this.chkRemember); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.bttCancel); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "PasswordForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Password Request"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.TextBox txtPassword; + private System.Windows.Forms.CheckBox chkRemember; + private System.Windows.Forms.Label label2; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/PasswordForm.cs b/src_vs2012/Package/Dialogs/PasswordForm.cs new file mode 100644 index 00000000..e3f7dfd1 --- /dev/null +++ b/src_vs2012/Package/Dialogs/PasswordForm.cs @@ -0,0 +1,52 @@ +using System; +using System.Windows.Forms; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class PasswordForm : Form + { + public PasswordForm() + { + InitializeComponent(); + } + + #region Properties + + public string Password + { + get { return txtPassword.Text; } + set { txtPassword.Text = value; } + } + + public bool ShouldRemember + { + get { return chkRemember.Checked; } + set { chkRemember.Checked = value; } + } + + /// + /// Shows the option to indicate, if password should be remembered or not. + /// + public bool ShowRemember + { + get { return chkRemember.Visible; } + set { chkRemember.Visible = value; } + } + + #endregion + + private void bttOK_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(Password)) + { + MessageBoxHelper.Show("You must specify value for password", "Password error", MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = txtPassword; + return; + } + + DialogResult = DialogResult.OK; + Close(); + } + } +} diff --git a/src_vs2012/Package/Dialogs/PasswordForm.resx b/src_vs2012/Package/Dialogs/PasswordForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/PasswordForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/PinListForm.Designer.cs b/src_vs2012/Package/Dialogs/PinListForm.Designer.cs new file mode 100644 index 00000000..1c96c0c8 --- /dev/null +++ b/src_vs2012/Package/Dialogs/PinListForm.Designer.cs @@ -0,0 +1,224 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class PinListForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bttCancel = new System.Windows.Forms.Button(); + this.bttOK = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.txtPIN = new System.Windows.Forms.TextBox(); + this.bttDiscover = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttAdd = new System.Windows.Forms.Button(); + this.listPINs = new System.Windows.Forms.ListView(); + this.label2 = new System.Windows.Forms.Label(); + this.columnPIN = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.bttClear = new System.Windows.Forms.Button(); + this.bttRemove = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // bttCancel + // + this.bttCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bttCancel.Location = new System.Drawing.Point(312, 275); + this.bttCancel.Name = "bttCancel"; + this.bttCancel.Size = new System.Drawing.Size(75, 23); + this.bttCancel.TabIndex = 2; + this.bttCancel.Text = "&Cancel"; + this.bttCancel.UseVisualStyleBackColor = true; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttOK.Location = new System.Drawing.Point(231, 275); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 1; + this.bttOK.Text = "&OK"; + this.bttOK.UseVisualStyleBackColor = true; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(28, 13); + this.label1.TabIndex = 0; + this.label1.Text = "PIN:"; + // + // txtPIN + // + this.txtPIN.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPIN.Location = new System.Drawing.Point(72, 19); + this.txtPIN.Name = "txtPIN"; + this.txtPIN.Size = new System.Drawing.Size(216, 20); + this.txtPIN.TabIndex = 1; + // + // bttDiscover + // + this.bttDiscover.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttDiscover.Location = new System.Drawing.Point(294, 48); + this.bttDiscover.Name = "bttDiscover"; + this.bttDiscover.Size = new System.Drawing.Size(75, 23); + this.bttDiscover.TabIndex = 3; + this.bttDiscover.Text = "&Discover..."; + this.bttDiscover.UseVisualStyleBackColor = true; + this.bttDiscover.Click += new System.EventHandler(this.bttDiscover_Click); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttRemove); + this.groupBox1.Controls.Add(this.bttClear); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.listPINs); + this.groupBox1.Controls.Add(this.bttAdd); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.bttDiscover); + this.groupBox1.Controls.Add(this.txtPIN); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(375, 257); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "New"; + // + // bttAdd + // + this.bttAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttAdd.Location = new System.Drawing.Point(294, 19); + this.bttAdd.Name = "bttAdd"; + this.bttAdd.Size = new System.Drawing.Size(75, 23); + this.bttAdd.TabIndex = 2; + this.bttAdd.Text = "&Add"; + this.bttAdd.UseVisualStyleBackColor = true; + this.bttAdd.Click += new System.EventHandler(this.bttAdd_Click); + // + // listPINs + // + this.listPINs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listPINs.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnPIN}); + this.listPINs.FullRowSelect = true; + this.listPINs.GridLines = true; + this.listPINs.HideSelection = false; + this.listPINs.Location = new System.Drawing.Point(72, 84); + this.listPINs.MultiSelect = false; + this.listPINs.Name = "listPINs"; + this.listPINs.Size = new System.Drawing.Size(216, 158); + this.listPINs.TabIndex = 5; + this.listPINs.UseCompatibleStateImageBehavior = false; + this.listPINs.View = System.Windows.Forms.View.Details; + this.listPINs.SelectedIndexChanged += new System.EventHandler(this.listPINs_SelectedIndexChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(17, 84); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(26, 13); + this.label2.TabIndex = 4; + this.label2.Text = "List:"; + // + // columnPIN + // + this.columnPIN.Text = "PINs"; + this.columnPIN.Width = 180; + // + // bttClear + // + this.bttClear.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttClear.Enabled = false; + this.bttClear.Location = new System.Drawing.Point(294, 113); + this.bttClear.Name = "bttClear"; + this.bttClear.Size = new System.Drawing.Size(75, 23); + this.bttClear.TabIndex = 7; + this.bttClear.Text = "&Clear"; + this.bttClear.UseVisualStyleBackColor = true; + this.bttClear.Click += new System.EventHandler(this.bttClear_Click); + // + // bttRemove + // + this.bttRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttRemove.Enabled = false; + this.bttRemove.Location = new System.Drawing.Point(294, 84); + this.bttRemove.Name = "bttRemove"; + this.bttRemove.Size = new System.Drawing.Size(75, 23); + this.bttRemove.TabIndex = 6; + this.bttRemove.Text = "&Remove"; + this.bttRemove.UseVisualStyleBackColor = true; + this.bttRemove.Click += new System.EventHandler(this.bttRemove_Click); + // + // PinListForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttCancel; + this.ClientSize = new System.Drawing.Size(399, 310); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.bttCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "PinListForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "PIN Editor"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button bttCancel; + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox txtPIN; + private System.Windows.Forms.Button bttDiscover; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttAdd; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ListView listPINs; + private System.Windows.Forms.ColumnHeader columnPIN; + private System.Windows.Forms.Button bttRemove; + private System.Windows.Forms.Button bttClear; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/PinListForm.cs b/src_vs2012/Package/Dialogs/PinListForm.cs new file mode 100644 index 00000000..5b7d4284 --- /dev/null +++ b/src_vs2012/Package/Dialogs/PinListForm.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Dialogs +{ + /// + /// Dialog for creating list of device PINs. + /// + internal partial class PinListForm : Form + { + private List _pins; + + public PinListForm() + { + InitializeComponent(); + + _pins = new List(); + } + + #region Properties + + public string NewPIN + { + get { return txtPIN.Text; } + set { txtPIN.Text = value; } + } + + public ulong[] PINs + { + get { return _pins.ToArray(); } + set + { + if (value == null) + _pins = new List(); + else + _pins = new List(value); + + PopulateList(); + } + } + + internal IEnumerable OptionalDevices + { + get; + set; + } + + #endregion + + private void PopulateList() + { + listPINs.Items.Clear(); + + for (int i = 0; i < _pins.Count; i++) + listPINs.Items.Add(_pins[i].ToString("X")); + + bttClear.Enabled = _pins.Count > 0; + } + + /// + /// Adds new PIN to the collection. + /// + public int Add(ulong pin) + { + if (_pins.IndexOf(pin) < 0) + { + _pins.Insert(0, pin); + + PopulateList(); + return 1; + } + + return 0; + } + + /// + /// Adds a list of PINs to the collection. + /// + public int Add(IEnumerable pins) + { + if (pins == null) + return 0; + + int count = 0; + foreach (var p in pins) + { + if (_pins.IndexOf(p) < 0) + { + _pins.Insert(count, p); + count++; + } + } + + PopulateList(); + return count; + } + + /// + /// Adds new PINs read from specified string (can be a comma-separated list of values). + /// + public int Add(string pin) + { + if (string.IsNullOrEmpty(pin)) + return 0; + + var items = pin.Split(new[] { ' ', ',', ';', '|', '#', '*', '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); + var pins = new ulong[items.Length]; + + for(int i = 0; i < items.Length; i++) + { + ulong value; + + // try to parse all or NONE! + if (!ulong.TryParse(items[i], NumberStyles.HexNumber, null, out value)) + return -1; + + pins[i] = value; + } + + // add all to the existing list: + _pins.AddRange(pins); + PopulateList(); + return pins.Length; + } + + private void bttAdd_Click(object sender, EventArgs e) + { + if (Add(NewPIN) < 0) + { + MessageBoxHelper.Show("PIN number contains errors. Correct them and try again", "Invalid PIN value", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + NewPIN = string.Empty; + } + + private void bttClear_Click(object sender, EventArgs e) + { + if (MessageBoxHelper.Show("Clear the list?", "PIN List", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + _pins.Clear(); + PopulateList(); + } + } + + private void listPINs_SelectedIndexChanged(object sender, EventArgs e) + { + bttRemove.Enabled = listPINs.SelectedItems.Count > 0; + } + + private void bttRemove_Click(object sender, EventArgs e) + { + if (MessageBoxHelper.Show("Remove this item?", _pins[listPINs.SelectedIndices[0]].ToString("X"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + _pins.RemoveAt(listPINs.SelectedIndices[0]); + PopulateList(); + } + } + + private void bttDiscover_Click(object sender, EventArgs e) + { + var form = new DeviceForm("Discover Device PIN"); + form.SetDiscoverMode(OptionalDevices); + + if (form.ShowDialog() == DialogResult.OK && form.PIN != 0) + { + Add(form.PIN); + } + + ActiveControl = txtPIN; + } + } +} diff --git a/src_vs2012/Package/Dialogs/PinListForm.resx b/src_vs2012/Package/Dialogs/PinListForm.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Dialogs/PinListForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/RegistrationForm.Designer.cs b/src_vs2012/Package/Dialogs/RegistrationForm.Designer.cs new file mode 100644 index 00000000..90c1b47b --- /dev/null +++ b/src_vs2012/Package/Dialogs/RegistrationForm.Designer.cs @@ -0,0 +1,559 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class RegistrationForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RegistrationForm)); + this.label1 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.txtPassword = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.txtName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.bttOK = new System.Windows.Forms.Button(); + this.txtConfirmPassword = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.bttCreateToken = new System.Windows.Forms.Button(); + this.bttCreateCertificate = new System.Windows.Forms.Button(); + this.groupBlackBerry10 = new System.Windows.Forms.GroupBox(); + this.lblTokenExpiration = new System.Windows.Forms.Label(); + this.lblRegistration = new System.Windows.Forms.Label(); + this.bttRefresh = new System.Windows.Forms.Button(); + this.txtCertName = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.bttImportCertificate = new System.Windows.Forms.Button(); + this.cmbSections = new System.Windows.Forms.ComboBox(); + this.txtLog = new System.Windows.Forms.TextBox(); + this.groupTablet = new System.Windows.Forms.GroupBox(); + this.lblTabletRegistration = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.lnkMoreInfo = new System.Windows.Forms.LinkLabel(); + this.txtCskConfirmPassword = new System.Windows.Forms.TextBox(); + this.txtCskPassword = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.txtCsjPin = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.txtPbdtPath = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.bttPbdtNavigate = new System.Windows.Forms.Button(); + this.bttRdkNavigate = new System.Windows.Forms.Button(); + this.bttCreateSigner = new System.Windows.Forms.Button(); + this.txtRdkPath = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.bttNavigate = new System.Windows.Forms.Button(); + this.groupBlackBerry10.SuspendLayout(); + this.groupTablet.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Location = new System.Drawing.Point(12, 73); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(519, 33); + this.label1.TabIndex = 1; + this.label1.Text = resources.GetString("label1.Text"); + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label4.Location = new System.Drawing.Point(12, 26); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(519, 47); + this.label4.TabIndex = 0; + this.label4.Text = resources.GetString("label4.Text"); + // + // txtPassword + // + this.txtPassword.Location = new System.Drawing.Point(131, 144); + this.txtPassword.Name = "txtPassword"; + this.txtPassword.PasswordChar = '*'; + this.txtPassword.Size = new System.Drawing.Size(113, 20); + this.txtPassword.TabIndex = 5; + this.txtPassword.TextChanged += new System.EventHandler(this.txtPassword_TextChanged); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(12, 147); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(56, 13); + this.label3.TabIndex = 4; + this.label3.Text = "Password:"; + // + // txtName + // + this.txtName.Location = new System.Drawing.Point(131, 118); + this.txtName.Name = "txtName"; + this.txtName.Size = new System.Drawing.Size(184, 20); + this.txtName.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 121); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(72, 13); + this.label2.TabIndex = 2; + this.label2.Text = "Author Name:"; + // + // bttOK + // + this.bttOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttOK.Location = new System.Drawing.Point(474, 433); + this.bttOK.Name = "bttOK"; + this.bttOK.Size = new System.Drawing.Size(75, 23); + this.bttOK.TabIndex = 3; + this.bttOK.Text = "&Close"; + this.bttOK.UseVisualStyleBackColor = true; + // + // txtConfirmPassword + // + this.txtConfirmPassword.Location = new System.Drawing.Point(131, 170); + this.txtConfirmPassword.Name = "txtConfirmPassword"; + this.txtConfirmPassword.PasswordChar = '*'; + this.txtConfirmPassword.Size = new System.Drawing.Size(113, 20); + this.txtConfirmPassword.TabIndex = 7; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(12, 173); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(94, 13); + this.label5.TabIndex = 6; + this.label5.Text = "Confirm Password:"; + // + // bttCreateToken + // + this.bttCreateToken.Location = new System.Drawing.Point(15, 230); + this.bttCreateToken.Name = "bttCreateToken"; + this.bttCreateToken.Size = new System.Drawing.Size(110, 23); + this.bttCreateToken.TabIndex = 11; + this.bttCreateToken.Text = "Create &Token..."; + this.bttCreateToken.UseVisualStyleBackColor = true; + this.bttCreateToken.Click += new System.EventHandler(this.bttCreateToken_Click); + // + // bttCreateCertificate + // + this.bttCreateCertificate.Location = new System.Drawing.Point(131, 230); + this.bttCreateCertificate.Name = "bttCreateCertificate"; + this.bttCreateCertificate.Size = new System.Drawing.Size(113, 23); + this.bttCreateCertificate.TabIndex = 12; + this.bttCreateCertificate.Text = "Create C&ertificate..."; + this.bttCreateCertificate.UseVisualStyleBackColor = true; + this.bttCreateCertificate.Click += new System.EventHandler(this.bttCreateCertificate_Click); + // + // groupBlackBerry10 + // + this.groupBlackBerry10.Controls.Add(this.lblTokenExpiration); + this.groupBlackBerry10.Controls.Add(this.lblRegistration); + this.groupBlackBerry10.Controls.Add(this.bttRefresh); + this.groupBlackBerry10.Controls.Add(this.label4); + this.groupBlackBerry10.Controls.Add(this.txtCertName); + this.groupBlackBerry10.Controls.Add(this.label6); + this.groupBlackBerry10.Controls.Add(this.bttImportCertificate); + this.groupBlackBerry10.Controls.Add(this.bttCreateCertificate); + this.groupBlackBerry10.Controls.Add(this.label2); + this.groupBlackBerry10.Controls.Add(this.bttCreateToken); + this.groupBlackBerry10.Controls.Add(this.txtName); + this.groupBlackBerry10.Controls.Add(this.label3); + this.groupBlackBerry10.Controls.Add(this.label5); + this.groupBlackBerry10.Controls.Add(this.txtConfirmPassword); + this.groupBlackBerry10.Controls.Add(this.txtPassword); + this.groupBlackBerry10.Controls.Add(this.label1); + this.groupBlackBerry10.Location = new System.Drawing.Point(12, 12); + this.groupBlackBerry10.Name = "groupBlackBerry10"; + this.groupBlackBerry10.Size = new System.Drawing.Size(537, 288); + this.groupBlackBerry10.TabIndex = 0; + this.groupBlackBerry10.TabStop = false; + this.groupBlackBerry10.Text = "BlackBerry 10 Devices"; + this.groupBlackBerry10.Visible = false; + // + // lblTokenExpiration + // + this.lblTokenExpiration.AutoSize = true; + this.lblTokenExpiration.Location = new System.Drawing.Point(247, 264); + this.lblTokenExpiration.Name = "lblTokenExpiration"; + this.lblTokenExpiration.Size = new System.Drawing.Size(101, 13); + this.lblTokenExpiration.TabIndex = 14; + this.lblTokenExpiration.Text = "Token expires at: ---"; + // + // lblRegistration + // + this.lblRegistration.AutoSize = true; + this.lblRegistration.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.lblRegistration.ForeColor = System.Drawing.Color.Navy; + this.lblRegistration.Location = new System.Drawing.Point(247, 235); + this.lblRegistration.Name = "lblRegistration"; + this.lblRegistration.Size = new System.Drawing.Size(197, 13); + this.lblRegistration.TabIndex = 13; + this.lblRegistration.Text = "Registration has been completed."; + // + // bttRefresh + // + this.bttRefresh.Location = new System.Drawing.Point(321, 196); + this.bttRefresh.Name = "bttRefresh"; + this.bttRefresh.Size = new System.Drawing.Size(75, 23); + this.bttRefresh.TabIndex = 10; + this.bttRefresh.Text = "&Refresh"; + this.bttRefresh.UseVisualStyleBackColor = true; + this.bttRefresh.Click += new System.EventHandler(this.bttRefresh_Click); + // + // txtCertName + // + this.txtCertName.Location = new System.Drawing.Point(131, 196); + this.txtCertName.Name = "txtCertName"; + this.txtCertName.ReadOnly = true; + this.txtCertName.Size = new System.Drawing.Size(184, 20); + this.txtCertName.TabIndex = 9; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(12, 199); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(57, 13); + this.label6.TabIndex = 8; + this.label6.Text = "Certificate:"; + // + // bttImportCertificate + // + this.bttImportCertificate.Location = new System.Drawing.Point(131, 259); + this.bttImportCertificate.Name = "bttImportCertificate"; + this.bttImportCertificate.Size = new System.Drawing.Size(113, 23); + this.bttImportCertificate.TabIndex = 12; + this.bttImportCertificate.Text = "I&mport Certificate..."; + this.bttImportCertificate.UseVisualStyleBackColor = true; + this.bttImportCertificate.Click += new System.EventHandler(this.bttImportCertificate_Click); + // + // cmbSections + // + this.cmbSections.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbSections.FormattingEnabled = true; + this.cmbSections.Items.AddRange(new object[] { + "BlackBerry 10 Devices", + "BlackBerry PlayBook Tablet"}); + this.cmbSections.Location = new System.Drawing.Point(20, 8); + this.cmbSections.Name = "cmbSections"; + this.cmbSections.Size = new System.Drawing.Size(238, 21); + this.cmbSections.TabIndex = 16; + this.cmbSections.SelectedIndexChanged += new System.EventHandler(this.cmbSections_SelectedIndexChanged); + // + // txtLog + // + this.txtLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtLog.Location = new System.Drawing.Point(12, 306); + this.txtLog.Multiline = true; + this.txtLog.Name = "txtLog"; + this.txtLog.ReadOnly = true; + this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtLog.Size = new System.Drawing.Size(537, 121); + this.txtLog.TabIndex = 2; + // + // groupTablet + // + this.groupTablet.Controls.Add(this.lblTabletRegistration); + this.groupTablet.Controls.Add(this.label13); + this.groupTablet.Controls.Add(this.lnkMoreInfo); + this.groupTablet.Controls.Add(this.txtCskConfirmPassword); + this.groupTablet.Controls.Add(this.txtCskPassword); + this.groupTablet.Controls.Add(this.label11); + this.groupTablet.Controls.Add(this.txtCsjPin); + this.groupTablet.Controls.Add(this.label10); + this.groupTablet.Controls.Add(this.txtPbdtPath); + this.groupTablet.Controls.Add(this.label9); + this.groupTablet.Controls.Add(this.bttPbdtNavigate); + this.groupTablet.Controls.Add(this.bttRdkNavigate); + this.groupTablet.Controls.Add(this.bttCreateSigner); + this.groupTablet.Controls.Add(this.txtRdkPath); + this.groupTablet.Controls.Add(this.label8); + this.groupTablet.Controls.Add(this.label7); + this.groupTablet.Controls.Add(this.label12); + this.groupTablet.Location = new System.Drawing.Point(12, 12); + this.groupTablet.Name = "groupTablet"; + this.groupTablet.Size = new System.Drawing.Size(537, 288); + this.groupTablet.TabIndex = 1; + this.groupTablet.TabStop = false; + this.groupTablet.Text = "BlackBerry Tablet"; + this.groupTablet.Visible = false; + // + // lblTabletRegistration + // + this.lblTabletRegistration.AutoSize = true; + this.lblTabletRegistration.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.lblTabletRegistration.ForeColor = System.Drawing.Color.Navy; + this.lblTabletRegistration.Location = new System.Drawing.Point(134, 264); + this.lblTabletRegistration.Name = "lblTabletRegistration"; + this.lblTabletRegistration.Size = new System.Drawing.Size(197, 13); + this.lblTabletRegistration.TabIndex = 16; + this.lblTabletRegistration.Text = "Registration has been completed."; + // + // label13 + // + this.label13.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label13.Location = new System.Drawing.Point(12, 73); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(520, 36); + this.label13.TabIndex = 2; + this.label13.Text = "To complete the registration both - BlackBerry Signer and developer certificate -" + + " are required. Certificate will be created automatically here or at BlackBerry 1" + + "0 devices section on left."; + // + // lnkMoreInfo + // + this.lnkMoreInfo.AutoSize = true; + this.lnkMoreInfo.Location = new System.Drawing.Point(12, 54); + this.lnkMoreInfo.Name = "lnkMoreInfo"; + this.lnkMoreInfo.Size = new System.Drawing.Size(60, 13); + this.lnkMoreInfo.TabIndex = 1; + this.lnkMoreInfo.TabStop = true; + this.lnkMoreInfo.Text = "More info..."; + this.lnkMoreInfo.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkMoreInfo_LinkClicked); + // + // txtCskConfirmPassword + // + this.txtCskConfirmPassword.Location = new System.Drawing.Point(134, 222); + this.txtCskConfirmPassword.Name = "txtCskConfirmPassword"; + this.txtCskConfirmPassword.PasswordChar = '*'; + this.txtCskConfirmPassword.Size = new System.Drawing.Size(113, 20); + this.txtCskConfirmPassword.TabIndex = 14; + // + // txtCskPassword + // + this.txtCskPassword.Location = new System.Drawing.Point(134, 196); + this.txtCskPassword.Name = "txtCskPassword"; + this.txtCskPassword.PasswordChar = '*'; + this.txtCskPassword.Size = new System.Drawing.Size(113, 20); + this.txtCskPassword.TabIndex = 12; + this.txtCskPassword.TextChanged += new System.EventHandler(this.txtCskPassword_TextChanged); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(12, 199); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(80, 13); + this.label11.TabIndex = 11; + this.label11.Text = "CSK Password:"; + // + // txtCsjPin + // + this.txtCsjPin.Location = new System.Drawing.Point(134, 170); + this.txtCsjPin.Name = "txtCsjPin"; + this.txtCsjPin.PasswordChar = '*'; + this.txtCsjPin.Size = new System.Drawing.Size(113, 20); + this.txtCsjPin.TabIndex = 10; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(12, 173); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(50, 13); + this.label10.TabIndex = 9; + this.label10.Text = "CSJ PIN:"; + // + // txtPbdtPath + // + this.txtPbdtPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPbdtPath.Location = new System.Drawing.Point(134, 144); + this.txtPbdtPath.Name = "txtPbdtPath"; + this.txtPbdtPath.Size = new System.Drawing.Size(344, 20); + this.txtPbdtPath.TabIndex = 7; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(12, 147); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(86, 13); + this.label9.TabIndex = 6; + this.label9.Text = "PBDT CSJ Path:"; + // + // bttPbdtNavigate + // + this.bttPbdtNavigate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttPbdtNavigate.Location = new System.Drawing.Point(484, 144); + this.bttPbdtNavigate.Name = "bttPbdtNavigate"; + this.bttPbdtNavigate.Size = new System.Drawing.Size(38, 23); + this.bttPbdtNavigate.TabIndex = 8; + this.bttPbdtNavigate.Text = "..."; + this.bttPbdtNavigate.UseVisualStyleBackColor = true; + this.bttPbdtNavigate.Click += new System.EventHandler(this.bttPbdtNavigate_Click); + // + // bttRdkNavigate + // + this.bttRdkNavigate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttRdkNavigate.Location = new System.Drawing.Point(484, 118); + this.bttRdkNavigate.Name = "bttRdkNavigate"; + this.bttRdkNavigate.Size = new System.Drawing.Size(38, 23); + this.bttRdkNavigate.TabIndex = 5; + this.bttRdkNavigate.Text = "..."; + this.bttRdkNavigate.UseVisualStyleBackColor = true; + this.bttRdkNavigate.Click += new System.EventHandler(this.bttRdkNavigate_Click); + // + // bttCreateSigner + // + this.bttCreateSigner.Location = new System.Drawing.Point(15, 259); + this.bttCreateSigner.Name = "bttCreateSigner"; + this.bttCreateSigner.Size = new System.Drawing.Size(110, 23); + this.bttCreateSigner.TabIndex = 15; + this.bttCreateSigner.Text = "Create &Signer..."; + this.bttCreateSigner.UseVisualStyleBackColor = true; + this.bttCreateSigner.Click += new System.EventHandler(this.bttCreateSigner_Click); + // + // txtRdkPath + // + this.txtRdkPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtRdkPath.Location = new System.Drawing.Point(134, 118); + this.txtRdkPath.Name = "txtRdkPath"; + this.txtRdkPath.Size = new System.Drawing.Size(344, 20); + this.txtRdkPath.TabIndex = 4; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(12, 121); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(80, 13); + this.label8.TabIndex = 3; + this.label8.Text = "RDK CSJ Path:"; + // + // label7 + // + this.label7.Location = new System.Drawing.Point(12, 20); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(520, 40); + this.label7.TabIndex = 0; + this.label7.Text = "Specify signing properties, that were submitted at BlackBerry CodeSigning page. Y" + + "ou should receive required RDK and PBDT files via email before."; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(12, 225); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(94, 13); + this.label12.TabIndex = 13; + this.label12.Text = "Confirm Password:"; + // + // bttNavigate + // + this.bttNavigate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttNavigate.Location = new System.Drawing.Point(12, 433); + this.bttNavigate.Name = "bttNavigate"; + this.bttNavigate.Size = new System.Drawing.Size(75, 23); + this.bttNavigate.TabIndex = 4; + this.bttNavigate.Text = "&Navigate..."; + this.bttNavigate.UseVisualStyleBackColor = true; + this.bttNavigate.Click += new System.EventHandler(this.bttNavigate_Click); + // + // RegistrationForm + // + this.AcceptButton = this.bttOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttOK; + this.ClientSize = new System.Drawing.Size(561, 468); + this.Controls.Add(this.cmbSections); + this.Controls.Add(this.bttNavigate); + this.Controls.Add(this.txtLog); + this.Controls.Add(this.bttOK); + this.Controls.Add(this.groupTablet); + this.Controls.Add(this.groupBlackBerry10); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "RegistrationForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Developer Registration"; + this.groupBlackBerry10.ResumeLayout(false); + this.groupBlackBerry10.PerformLayout(); + this.groupTablet.ResumeLayout(false); + this.groupTablet.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button bttOK; + private System.Windows.Forms.TextBox txtPassword; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button bttCreateCertificate; + private System.Windows.Forms.Button bttCreateToken; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox txtConfirmPassword; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.GroupBox groupBlackBerry10; + private System.Windows.Forms.TextBox txtLog; + private System.Windows.Forms.TextBox txtCertName; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.GroupBox groupTablet; + private System.Windows.Forms.LinkLabel lnkMoreInfo; + private System.Windows.Forms.TextBox txtCskConfirmPassword; + private System.Windows.Forms.TextBox txtCskPassword; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox txtCsjPin; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.TextBox txtPbdtPath; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Button bttPbdtNavigate; + private System.Windows.Forms.Button bttRdkNavigate; + private System.Windows.Forms.Button bttCreateSigner; + private System.Windows.Forms.TextBox txtRdkPath; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label lblTabletRegistration; + private System.Windows.Forms.Button bttRefresh; + private System.Windows.Forms.Button bttImportCertificate; + private System.Windows.Forms.Button bttNavigate; + private System.Windows.Forms.Label lblTokenExpiration; + private System.Windows.Forms.Label lblRegistration; + private System.Windows.Forms.ComboBox cmbSections; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/RegistrationForm.cs b/src_vs2012/Package/Dialogs/RegistrationForm.cs new file mode 100644 index 00000000..ebe946ae --- /dev/null +++ b/src_vs2012/Package/Dialogs/RegistrationForm.cs @@ -0,0 +1,413 @@ +using System; +using System.IO; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Model; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class RegistrationForm : Form + { + private const string ValidationCaption = "Validation"; + private readonly DeveloperDefinition _developer; + + public RegistrationForm(DeveloperDefinition developer, int startupSection) + { + if (developer == null) + throw new ArgumentNullException("developer"); + _developer = developer; + + InitializeComponent(); + + AuthorName = _developer.Name; + Password = _developer.CskPassword; + + if (_developer.HasCertificate) + Log(string.Format("Found certificate:\r\n * \"{0}\"", _developer.CertificateFullPath)); + if (_developer.HasToken) + Log(string.Format("Found BlackBerry 10 token:\r\n * \"{0}\"\r\n * version: {1}\r\n * created at: {2}", _developer.CskTokenFullPath, _developer.Token.Version, _developer.Token.CreatedAtString)); + if (_developer.HasTabletToken) + Log(string.Format("Found Tablet token:\r\n * \"{0}\"\r\n * version: {1}\r\n * created at: {2}", _developer.TabletCskTokenFullPath, _developer.TabletToken.Version, _developer.TabletToken.CreatedAtString)); + + UpdateUI(); + ActivateSection(startupSection); + } + + #region Properties + + public string AuthorName + { + get { return txtName.Text; } + set { txtName.Text = value; } + } + + public string Password + { + get { return txtPassword.Text; } + set + { + txtPassword.Text = value; + txtConfirmPassword.Text = value; + txtCskPassword.Text = value; + txtCskConfirmPassword.Text = value; + } + } + + #endregion + + #region Logging + + private void ClearLogs() + { + txtLog.Text = string.Empty; + } + + private void Log(string text) + { + if (string.IsNullOrEmpty(text)) + return; + + if (InvokeRequired) + { + Invoke(new Action(Log), text); + return; + } + + txtLog.Text += text + Environment.NewLine; + } + + #endregion + + #region Input Checks + + /// + /// Checks for input password errors. Returns 'true', when all is OK. + /// + private bool CheckPassword(TextBox password, TextBox confirmation, string name) + { + if (string.IsNullOrEmpty(name)) + name = "Password"; + + if (password != null && string.IsNullOrEmpty(password.Text)) + { + MessageBoxHelper.Show(name + " can not be empty", ValidationCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = password; + return false; + } + + if (password != null && confirmation != null + && string.Compare(password.Text, confirmation.Text, StringComparison.CurrentCulture) != 0) + { + MessageBoxHelper.Show(name + "s are not matching.", ValidationCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = confirmation; + return false; + } + + return true; + } + + /// + /// Checks for input file name errors. Returns 'true', when all is OK. + /// + private bool CheckPath(TextBox path, string name) + { + if (string.IsNullOrEmpty(name)) + name = "file name"; + + if (path != null && string.IsNullOrEmpty(path.Text)) + { + MessageBoxHelper.Show("Specified " + name + " can not be empty", ValidationCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = path; + return false; + } + + if (path != null && !File.Exists(path.Text)) + { + MessageBoxHelper.Show("Specified " + name + " does not exist. Ensure it points to the right file", ValidationCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = path; + return false; + } + + return true; + } + + /// + /// Checks for author name's errors. Returns 'true', when all is OK. + /// + private bool CheckName(TextBox author) + { + if (string.IsNullOrEmpty(author.Text)) + { + MessageBoxHelper.Show("Author Name can not be empty.", ValidationCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = author; + return false; + } + + if (author.Text.Trim().ToUpper().Contains("BLACKBERRY")) + { + MessageBoxHelper.Show("\"BlackBerry\" is a reserved word and cannot be used as \"Author Name\"", ValidationCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); + ActiveControl = author; + return false; + } + + return true; + } + + #endregion + + private void UpdateUI() + { + // tablet section: + bool tabletRegistered = _developer.IsTabletRegistered; + + lblTabletRegistration.Visible = tabletRegistered; + + bttCreateSigner.Enabled = !tabletRegistered; + txtRdkPath.Enabled = bttRdkNavigate.Enabled = !tabletRegistered; + txtPbdtPath.Enabled = bttPbdtNavigate.Enabled = !tabletRegistered; + txtCsjPin.Enabled = txtCskPassword.Enabled = txtCskConfirmPassword.Enabled = !tabletRegistered; + + // BB10 devices section: + bool registered = _developer.IsBB10Registered; + + lblRegistration.Visible = registered; + lblTokenExpiration.Visible = _developer.HasToken; + lblTokenExpiration.Text = _developer.HasToken ? "Token expires at: " + _developer.Token.ValidDateString : string.Empty; + + txtCertName.Text = _developer.CertificateFileName; + bttCreateToken.Enabled = true; + bttImportCertificate.Enabled = true; + bttCreateCertificate.Enabled = !_developer.HasCertificate; + } + + private void UpdateActionButtons(bool enabled) + { + bttCreateCertificate.Enabled = enabled; + bttCreateSigner.Enabled = enabled; + bttCreateToken.Enabled = enabled; + } + + private void ActivateSection(int index) + { + cmbSections.SelectedIndex = index; + } + + private void txtPassword_TextChanged(object sender, EventArgs e) + { + txtConfirmPassword.Text = string.Empty; + txtCskPassword.Text = txtPassword.Text; + } + + private void txtCskPassword_TextChanged(object sender, EventArgs e) + { + txtCskConfirmPassword.Text = string.Empty; + txtPassword.Text = txtCskPassword.Text; + } + + private void bttCreateToken_Click(object sender, EventArgs e) + { + if (!CheckPassword(txtPassword, txtConfirmPassword, null)) + return; + + if (File.Exists(_developer.CskTokenFullPath)) + { + // confirm overwrite operation: + if (MessageBoxHelper.Show("Overwrite existing BlackBerry ID token?", null, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) + return; + } + + // show token request form: + var form = new CskRequestForm(null); + form.StartRequest(txtPassword.Text); + + if (form.ShowDialog() == DialogResult.OK) + { + // got the token, so save it in respective location: + _developer.SaveCskToken(form.Token); + + // log it: + Log("Created BlackBerry ID token - valid until " + form.Token.ValidDateString); + } + else + { + if (form.StatusCode != 0) + { + MessageBoxHelper.Show("Failed to obtain the BlackBerry ID token.\r\nCheck your Internet connection", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + UpdateUI(); + } + + private void lnkMoreInfo_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL("http://www.blackberry.com/go/codesigning/"); + } + + private void bttRdkNavigate_Click(object sender, EventArgs e) + { + var form = DialogHelper.OpenCsjFile(_developer.DataPath, "Opening RDK file"); + + if (form.ShowDialog() == DialogResult.OK) + { + txtRdkPath.Text = form.FileName; + } + } + + private void bttPbdtNavigate_Click(object sender, EventArgs e) + { + var form = DialogHelper.OpenCsjFile(_developer.DataPath, "Opening PBDT file"); + + if (form.ShowDialog() == DialogResult.OK) + { + txtPbdtPath.Text = form.FileName; + } + } + + private void bttCreateSigner_Click(object sender, EventArgs e) + { + if (!CheckPassword(txtCskPassword, txtCskConfirmPassword, null)) + return; + if (!CheckPassword(txtCsjPin, null, "PIN")) + return; + + // check paths: + if (!CheckPath(txtRdkPath, "RDK path")) + return; + if (!CheckPath(txtPbdtPath, "PBDT path")) + return; + + UpdateActionButtons(false); + Log("Starting registration..." + Environment.NewLine); + + // create CSK file: + bool successful; + string certificateFileName; + using (var runner = new KeyToolRegisterRunner(txtCsjPin.Text, txtCskPassword.Text, txtRdkPath.Text, txtPbdtPath.Text)) + { + successful = runner.Execute(); + certificateFileName = runner.CertificateFileName; + + // print results: + if (!string.IsNullOrEmpty(runner.LastOutput)) + Log(runner.LastOutput); + } + + // refresh the UI: + Log("Registration finished."); + _developer.InvalidateTokens(); + UpdateUI(); + + // and save the password: + if (successful) + { + _developer.UpdateCertificate(certificateFileName, txtCskPassword.Text, true); + + if (_developer.IsTabletRegistered) + { + // update the name of the developer (publisher): + txtName.Text = _developer.UpdateName(null); + MessageBoxHelper.Show("You have successfully registered your BlackBerry Tablet Signer", null, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBoxHelper.Show("Sorry, something unexpected has happened. Verify logs, unregister and try again.", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + else + { + MessageBoxHelper.Show("Failed to create BlackBerry Tablet Signer. Examine logs for more details.", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void bttImportCertificate_Click(object sender, EventArgs e) + { + if (CertHelper.Import(_developer)) + { + AuthorName = _developer.Name; + Password = _developer.CskPassword; + + UpdateUI(); + } + } + + private void bttNavigate_Click(object sender, EventArgs e) + { + // open the folder, where all the certificates are placed: + DialogHelper.StartExplorer(_developer.DataPath); + } + + private void bttRefresh_Click(object sender, EventArgs e) + { + if (CertHelper.ReloadAuthor(_developer)) + { + AuthorName = _developer.Name; + Password = _developer.CskPassword; + } + } + + private void bttCreateCertificate_Click(object sender, EventArgs e) + { + if (!CheckPassword(txtPassword, txtConfirmPassword, null)) + return; + if (!CheckName(txtName)) + return; + + UpdateActionButtons(false); + + using (var runner = new KeyToolGenRunner(AuthorName, Password, null)) + { + Log("Started certificate generation..." + Environment.NewLine); + var success = runner.Execute(); + + // print results: + if (runner.ExitCode != 0) + Log("Exit code: " + runner.ExitCode); + if (!string.IsNullOrEmpty(runner.LastError)) + Log(runner.LastError); + if (!string.IsNullOrEmpty(runner.LastOutput)) + Log(runner.LastOutput); + + Log("Certificate creation finished"); + + // show result message: + if (success && string.IsNullOrEmpty(runner.LastError)) + { + _developer.UpdateCertificate(runner.CertificateFileName, txtCskPassword.Text, true); + + MessageBoxHelper.Show("Keystore certificate has been successfully created", null, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + if (!string.IsNullOrEmpty(runner.LastError)) + { + MessageBoxHelper.Show("Failed to create developer certificate", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + UpdateUI(); + } + + private void cmbSections_SelectedIndexChanged(object sender, EventArgs e) + { + switch (cmbSections.SelectedIndex) + { + case 0: + groupBlackBerry10.Visible = true; + groupTablet.Visible = false; + ActiveControl = txtName; + break; + case 1: + groupBlackBerry10.Visible = false; + groupTablet.Visible = true; + ActiveControl = txtRdkPath; + break; + default: + throw new InvalidOperationException("Unsupported index to select"); + } + } + } +} diff --git a/src_vs2012/Package/Dialogs/RegistrationForm.resx b/src_vs2012/Package/Dialogs/RegistrationForm.resx new file mode 100644 index 00000000..0923d4e0 --- /dev/null +++ b/src_vs2012/Package/Dialogs/RegistrationForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + To complete the registration both - BlackBerry ID token and developer certificate - are required. However if you created BlackBerry Signer at tablet's section, it can be also used to deploy and debug applications here. + + + Type the password to use with the BlackBerry token. The browser will open and you will be asked to login to your BlackBerry ID or create a new account. The BlackBerry token can be used to create debug-tokens, sign applications and publish to the BlackBerry World storefront. + + \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.Designer.cs b/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.Designer.cs new file mode 100644 index 00000000..335108ed --- /dev/null +++ b/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.Designer.cs @@ -0,0 +1,190 @@ +namespace BlackBerry.Package.Dialogs +{ + internal partial class UpdateManagerStatusForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.bttClose = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttAbort = new System.Windows.Forms.Button(); + this.progressBar = new System.Windows.Forms.ProgressBar(); + this.lblActionLog2 = new System.Windows.Forms.Label(); + this.lblActionLog1 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.bttDelete = new System.Windows.Forms.Button(); + this.listActions = new System.Windows.Forms.ListBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // bttClose + // + this.bttClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttClose.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bttClose.Location = new System.Drawing.Point(504, 316); + this.bttClose.Name = "bttClose"; + this.bttClose.Size = new System.Drawing.Size(75, 23); + this.bttClose.TabIndex = 0; + this.bttClose.Text = "&Close"; + this.bttClose.UseVisualStyleBackColor = true; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttAbort); + this.groupBox1.Controls.Add(this.progressBar); + this.groupBox1.Controls.Add(this.lblActionLog2); + this.groupBox1.Controls.Add(this.lblActionLog1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(567, 122); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Current"; + // + // bttAbort + // + this.bttAbort.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttAbort.Enabled = false; + this.bttAbort.Location = new System.Drawing.Point(486, 78); + this.bttAbort.Name = "bttAbort"; + this.bttAbort.Size = new System.Drawing.Size(75, 23); + this.bttAbort.TabIndex = 3; + this.bttAbort.Text = "&Abort"; + this.bttAbort.UseVisualStyleBackColor = true; + this.bttAbort.Click += new System.EventHandler(this.bttAbort_Click); + // + // progressBar + // + this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.progressBar.Location = new System.Drawing.Point(12, 78); + this.progressBar.Name = "progressBar"; + this.progressBar.Size = new System.Drawing.Size(468, 23); + this.progressBar.TabIndex = 2; + // + // lblActionLog2 + // + this.lblActionLog2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lblActionLog2.AutoEllipsis = true; + this.lblActionLog2.Location = new System.Drawing.Point(9, 49); + this.lblActionLog2.Name = "lblActionLog2"; + this.lblActionLog2.Size = new System.Drawing.Size(552, 13); + this.lblActionLog2.TabIndex = 1; + this.lblActionLog2.Text = "-"; + // + // lblActionLog1 + // + this.lblActionLog1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lblActionLog1.AutoEllipsis = true; + this.lblActionLog1.Location = new System.Drawing.Point(9, 25); + this.lblActionLog1.Name = "lblActionLog1"; + this.lblActionLog1.Size = new System.Drawing.Size(552, 13); + this.lblActionLog1.TabIndex = 0; + this.lblActionLog1.Text = "-"; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.bttDelete); + this.groupBox2.Controls.Add(this.listActions); + this.groupBox2.Location = new System.Drawing.Point(12, 140); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(567, 170); + this.groupBox2.TabIndex = 2; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Pending"; + // + // bttDelete + // + this.bttDelete.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttDelete.Enabled = false; + this.bttDelete.Location = new System.Drawing.Point(486, 25); + this.bttDelete.Name = "bttDelete"; + this.bttDelete.Size = new System.Drawing.Size(75, 23); + this.bttDelete.TabIndex = 1; + this.bttDelete.Text = "&Delete"; + this.bttDelete.UseVisualStyleBackColor = true; + this.bttDelete.Click += new System.EventHandler(this.bttDelete_Click); + // + // listActions + // + this.listActions.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listActions.FormattingEnabled = true; + this.listActions.Location = new System.Drawing.Point(12, 25); + this.listActions.Name = "listActions"; + this.listActions.Size = new System.Drawing.Size(468, 134); + this.listActions.TabIndex = 0; + this.listActions.SelectedIndexChanged += new System.EventHandler(this.listActions_SelectedIndexChanged); + // + // UpdateManagerStatusForm + // + this.AcceptButton = this.bttClose; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bttClose; + this.ClientSize = new System.Drawing.Size(591, 351); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.bttClose); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UpdateManagerStatusForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Installation Status"; + this.groupBox1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button bttClose; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttAbort; + private System.Windows.Forms.ProgressBar progressBar; + private System.Windows.Forms.Label lblActionLog2; + private System.Windows.Forms.Label lblActionLog1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.ListBox listActions; + private System.Windows.Forms.Button bttDelete; + private System.Windows.Forms.ToolTip toolTip; + } +} \ No newline at end of file diff --git a/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.cs b/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.cs new file mode 100644 index 00000000..56f05831 --- /dev/null +++ b/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.cs @@ -0,0 +1,120 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Dialogs +{ + internal partial class UpdateManagerStatusForm : Form + { + private readonly ApiLevelOptionViewModel _vm; + private readonly IEventDispatcher _dispatcher; + + public UpdateManagerStatusForm(ApiLevelOptionViewModel vm) + { + if (vm == null) + throw new ArgumentNullException("vm"); + InitializeComponent(); + + _vm = vm; + UpdateUI(); + + _dispatcher = _vm.Dispatcher ?? EventDispatcher.From(this); + _vm.UpdateManager.Started += OnActionChanged; + _vm.UpdateManager.Completed += OnActionChanged; + _vm.UpdateManager.Log += OnLog; // this will cause the last message to be sent again... + } + + protected override void OnClosed(EventArgs e) + { + _vm.UpdateManager.Started -= OnActionChanged; + _vm.UpdateManager.Completed -= OnActionChanged; + _vm.UpdateManager.Log -= OnLog; + base.OnClosed(e); + } + + private void OnActionChanged(object sender, EventArgs e) + { + _dispatcher.Invoke(UpdateUI); + } + + private void OnLog(object sender, ApiLevelUpdateLogEventArgs e) + { + _dispatcher.Invoke(UpdateLog, e); + } + + private void UpdateUI() + { + UpdateList(); + UpdateLog(_vm.UpdateManager.CurrentAction); + } + + private void UpdateList() + { + listActions.Items.Clear(); + foreach (var item in _vm.UpdateManager.Actions) + { + listActions.Items.Add(item); + } + + listActions_SelectedIndexChanged(null, EventArgs.Empty); + } + + private void UpdateLog(UpdateManager.ActionData action) + { + lblActionLog1.Text = action != null ? string.Concat("Processing ", action.Name, "...") : "Nothing is currently executing"; + lblActionLog2.Text = "-"; + progressBar.Value = 0; + toolTip.SetToolTip(progressBar, null); + bttAbort.Enabled = action != null && action.CanAbort; + } + + private void UpdateLog(ApiLevelUpdateLogEventArgs e) + { + if (e != null && !string.IsNullOrEmpty(e.Message)) + { + lblActionLog2.Text = e.Message; + } + if (e != null && e.Progress >= 0) + { + progressBar.Value = e.Progress; + toolTip.SetToolTip(progressBar, progressBar.Value + "%"); + } + bttAbort.Enabled = e != null && e.CanAbort; + } + + private void listActions_SelectedIndexChanged(object sender, EventArgs e) + { + bttDelete.Enabled = listActions.SelectedIndex >= 0; + } + + private void bttAbort_Click(object sender, EventArgs e) + { + var action = _vm.UpdateManager.CurrentAction; + if (action != null) + { + if (MessageBoxHelper.Show(action.ToString(), "Do you want to abort currently running action?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + action.Abort(); + UpdateUI(); + } + } + } + + private void bttDelete_Click(object sender, EventArgs e) + { + var action = listActions.SelectedItem as UpdateManager.ActionData; + + if (action != null) + { + if (MessageBoxHelper.Show(action.ToString(), "Do you want to delete this step?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + action.Delete(); + UpdateList(); + } + } + } + } +} diff --git a/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.resx b/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.resx new file mode 100644 index 00000000..1ca1e9b0 --- /dev/null +++ b/src_vs2012/Package/Dialogs/UpdateManagerStatusForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/src_vs2012/Package/Editors/BarDescriptorEditorControl.xaml b/src_vs2012/Package/Editors/BarDescriptorEditorControl.xaml new file mode 100644 index 00000000..b00cfabb --- /dev/null +++ b/src_vs2012/Package/Editors/BarDescriptorEditorControl.xaml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2012/Package/Editors/BarDescriptorEditorControl.xaml.cs b/src_vs2012/Package/Editors/BarDescriptorEditorControl.xaml.cs new file mode 100644 index 00000000..56df74e6 --- /dev/null +++ b/src_vs2012/Package/Editors/BarDescriptorEditorControl.xaml.cs @@ -0,0 +1,341 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.IO; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Forms; +using System.Windows.Input; +using BlackBerry.BarDescriptor.Model; +using BlackBerry.NativeCore; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.ViewModels; +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using CheckBox = System.Windows.Controls.CheckBox; +using ComboBox = System.Windows.Controls.ComboBox; +using UserControl = System.Windows.Controls.UserControl; + +namespace BlackBerry.Package.Editors +{ + /// + /// Interaction logic for BarDescription editor control. + /// + public partial class BarDescriptorEditorControl : UserControl + { + private readonly ServiceProvider _serviceProvider; + /// + /// Primary Constructor + /// + public BarDescriptorEditorControl() + { + InitializeComponent(); + } + + /// + /// Overloaded Constructor + /// + /// + public BarDescriptorEditorControl(ServiceProvider serviceProvider, BarEditorViewModel viewModel) + { + _serviceProvider = serviceProvider; + DataContext = viewModel; + InitializeComponent(); + + // wait until we're initialized to handle events + viewModel.ViewModelChanged += ViewModelChanged; + } + + public BarEditorViewModel ViewModel + { + get { return DataContext as BarEditorViewModel; } + } + + internal void DoIdle() + { + // only call the view model DoIdle if this control has focus + // otherwise, we should skip and this will be called again + // once focus is regained + var viewModel = ViewModel; + if (viewModel != null && IsKeyboardFocusWithin) + { + viewModel.DoIdle(); + } + } + + /// + /// ViewModel Changerd Event + /// + /// + /// + private void ViewModelChanged(object sender, EventArgs e) + { + // this gets called when the view model is updated because the Xml Document was updated + // since we don't get individual PropertyChanged events, just re-set the DataContext + var viewModel = ViewModel; + DataContext = null; // first, set to null so that we see the change and rebind + DataContext = viewModel; + } + + /// + /// Check to see if the inputed text is allowed + /// + /// + /// + private Boolean IsTextAllowed(String text) + { + for (int i = 0; i < text.Length; i++) + { + if (!char.IsDigit(text[i]) && !char.IsControl(text[i])) + return false; + } + + return true; + } + + /// + /// Use the PreviewTextInputHandler to respond to key presses + /// + /// + /// + + private void PreviewTextInputHandler(object sender, TextCompositionEventArgs e) + { + e.Handled = !IsTextAllowed(e.Text); + } + + /// + /// Use the DataObject.Pasting Handler + /// + /// + /// + private void PastingHandler(object sender, DataObjectPastingEventArgs e) + { + if (e.DataObject.GetDataPresent(typeof(String))) + { + String text = (String)e.DataObject.GetData(typeof(String)); + if (!IsTextAllowed(text)) e.CancelCommand(); + } + else e.CancelCommand(); + } + + /// + /// GetAuthor Button Click Event + /// + /// + /// + private void btGetAuthor_Click(object sender, RoutedEventArgs e) + { + var viewModel = ViewModel; + + if (viewModel != null) + { + var form = DialogHelper.OpenBarFile("Select debug token", ConfigDefaults.DataDirectory); + if (form.ShowDialog() == DialogResult.OK) + { + viewModel.SetAuthorInfoFrom(form.FileName, EventDispatcher.From(this), OnLoadingDebugInfoFailed); + } + } + } + + private void OnLoadingDebugInfoFailed(object sender, EventArgs eventArgs) + { + MessageBoxHelper.Show("Unable to load info about the Author from given debug token. ", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + private void btnAddIC_Click(object sender, RoutedEventArgs e) + { + string filename = string.Empty; + Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); + dlg.DefaultExt = ".png"; // Default file extension + dlg.Filter = "Image Files (*.png, *.jpg, *.gif)|*.png;*.jpg;*.gif"; + bool? result = dlg.ShowDialog(); + if (result == true) + { + filename = dlg.FileName; + + AddIconToProject(filename); + + var viewModel = ViewModel; + if (viewModel != null) + { + FileInfo fileInfo = new FileInfo(filename); + viewModel.AddIcon(fileInfo); + } + } + } + + private void AddIconToProject(string path) + { + try + { + DTE dte = (DTE)_serviceProvider.GetService(typeof(DTE)); + string solutionDir = Path.GetDirectoryName(dte.Solution.FullName); + + + Projects projs = dte.Solution.Projects; + foreach (Project proj in projs) + { + var viewModel = ViewModel; + if (viewModel != null) + { + + FileInfo fileInfo1 = new FileInfo(proj.FullName); + FileInfo fileInfo2 = new FileInfo(viewModel.Model.Name); + FileInfo fileInfo3 = new FileInfo(path); + + if (viewModel.AppName == proj.Name) + { + proj.ProjectItems.AddFromFile(path); + viewModel.AddLocalAsset(path); + } + } + } + } + catch (Exception) + { + + } + } + + private void btnRemoveIC_Click(object sender, RoutedEventArgs e) + { + if (grdIcon.SelectedItem != null) + { + var viewModel = ViewModel; + if (viewModel != null) + { + viewModel.DeleteIcon(grdIcon.SelectedItem); + } + } + } + + + private void btnAddSS_Click(object sender, RoutedEventArgs e) + { + string filename = string.Empty; + Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); + dlg.DefaultExt = ".png"; // Default file extension + dlg.Filter = "Image Files (*.png, *.jpg, *.gif)|*.png;*.jpg;*.gif"; + bool? result = dlg.ShowDialog(); + if (result == true) + { + filename = dlg.FileName; + + AddIconToProject(filename); + + var viewModel = ViewModel; + if (viewModel != null) + { + FileInfo fileInfo = new FileInfo(filename); + viewModel.AddSplashScreen(fileInfo); + } + } + + } + + private void btnRemoveSS_Click(object sender, RoutedEventArgs e) + { + if (grdSplashScreen.SelectedItem != null) + { + var viewModel = ViewModel; + if (viewModel != null) + { + viewModel.DeleteSplashScreen(grdSplashScreen.SelectedItem); + } + } + } + + private void CheckBox_Click(object sender, RoutedEventArgs e) + { + if ((sender as CheckBox).IsChecked == true) + { + var viewModel = ViewModel; + if (viewModel != null) + { + viewModel.CheckPermission((grdPermissions.SelectedItem as PermissionItemClass).Identifier); + }; + } + else + { + var viewModel = ViewModel; + if (viewModel != null) + { + viewModel.UnCheckPermission((grdPermissions.SelectedItem as PermissionItemClass).Identifier); + } + } + + } + + private void btnAddAsset_Click(object sender, RoutedEventArgs e) + { + string filename = string.Empty; + Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); + + bool? result = dlg.ShowDialog(); + if (result == true) + { + filename = dlg.FileName; + + var viewModel = ViewModel; + if (viewModel != null) + { + viewModel.AddLocalAsset(filename); + } + } + } + + private void btnRemoveAsset_Click(object sender, RoutedEventArgs e) + { + if (grdAssets.SelectedItem != null) + { + var viewModel = ViewModel; + if (viewModel != null) + { + viewModel.DeleteLocalAsset(grdAssets.SelectedItem); + } + } + } + + private void CheckBox_Click_1(object sender, RoutedEventArgs e) + { + var viewModel = ViewModel; + if (viewModel != null) + { + bool isPublic = (sender as CheckBox).IsChecked == true; + viewModel.EditLocalAsset((grdAssets.SelectedItem as AssetType).Value, isPublic, ""); + } + } + + private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + string assetType; + + if (e.RemovedItems.Count != 0) + { + if (grdAssets.SelectedItems.Count != 0) + { + var viewModel = ViewModel; + if (viewModel != null) + { + assetType = (sender as ComboBox).SelectedValue.ToString(); + viewModel.EditLocalAsset((grdAssets.SelectedItem as AssetType).Value, null, assetType); + } + } + } + } + } +} diff --git a/src_vs2012/Package/Editors/BarDescriptorEditorFactory.cs b/src_vs2012/Package/Editors/BarDescriptorEditorFactory.cs new file mode 100644 index 00000000..7c724ecf --- /dev/null +++ b/src_vs2012/Package/Editors/BarDescriptorEditorFactory.cs @@ -0,0 +1,225 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using BlackBerry.DebugEngine; +using BlackBerry.NativeCore.Diagnostics; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.OLE.Interop; + +using IOleIServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; + +namespace BlackBerry.Package.Editors +{ + /// + /// Factory for creating the bar-descriptor editor + /// + [Guid(GuidList.guidVSNDK_PackageEditorFactoryString)] + public sealed class BarDescriptorEditorFactory : IVsEditorFactory, IDisposable + { + /// Declare Constants + public const string DefaultExtension = ".xml"; + + // Private Member Variables + private ServiceProvider _vsServiceProvider; + + ~BarDescriptorEditorFactory() + { + Dispose(false); + } + + /// + /// Close the factory + /// + public int Close() + { + return VSConstants.S_OK; + } + + /// + /// Create an instance of the custom editor + /// + /// Behaviour Flags + /// Document to be opened. + /// Name of the view + /// Pointer to the IVSHierarchy + /// Item ID for this instance + /// This parameter is used to determine if a document buffer (DocData object) has already been created + /// Pointer to the IUnknown interface for the DocView object + /// Pointer to the IUnknown interface for the DocData object + /// Caption mentioned by the editor for the doc window + /// the Command UI Guid. Any UI element that is visible in the editor has to use this GUID. This is specified in the .vsct file + /// Flags for CreateDocumentWindow + /// + public int CreateEditorInstance(uint grfCreateDoc, string pszMkDocument, string pszPhysicalView, IVsHierarchy pvHier, uint itemid, IntPtr punkDocDataExisting, out IntPtr ppunkDocView, out IntPtr ppunkDocData, out string pbstrEditorCaption, out Guid pguidCmdUI, out int pgrfCDW) + { + // Initialize variables. + ppunkDocView = IntPtr.Zero; + ppunkDocData = IntPtr.Zero; + pguidCmdUI = GuidList.guidVSNDK_PackageEditorFactory; + pgrfCDW = 0; + pbstrEditorCaption = null; + IVsTextLines textBuffer = null; + + // Validate Inputs + if ((grfCreateDoc & (VSConstants.CEF_OPENFILE | VSConstants.CEF_SILENT)) == 0) + { + return VSConstants.E_INVALIDARG; + } + + if (punkDocDataExisting == IntPtr.Zero) + { + // File is not open yet. Create a new text buffer object. + + // get the ILocalRegistry interface so we can use it to + // create the text buffer from the shell's local registry + try + { + ILocalRegistry localRegistry = (ILocalRegistry)GetService(typeof(SLocalRegistry)); + if (localRegistry != null) + { + // Successfully created + + IntPtr ptr; + Guid iid = typeof(IVsTextLines).GUID; + Guid CLSID_VsTextBuffer = typeof(VsTextBufferClass).GUID; + localRegistry.CreateInstance(CLSID_VsTextBuffer, null, ref iid, 1 /*CLSCTX_INPROC_SERVER*/, out ptr); + try + { + textBuffer = Marshal.GetObjectForIUnknown(ptr) as IVsTextLines; + } + finally + { + Marshal.Release(ptr); // Release RefCount from CreateInstance call + } + + // It is important to site the TextBuffer object + IObjectWithSite objWSite = (IObjectWithSite)textBuffer; + if (objWSite != null) + { + var oleServiceProvider = (IOleIServiceProvider)GetService(typeof(IOleIServiceProvider)); + objWSite.SetSite(oleServiceProvider); + } + } + } + catch (Exception ex) + { + Debug.WriteLine("Can not get IVsCfgProviderEventsHelper" + ex.Message); + throw; + } + } + else + { + // File is already open. Verify open document is a Text Buffer + + + // QI existing buffer for text lines + textBuffer = Marshal.GetObjectForIUnknown(punkDocDataExisting) as IVsTextLines; + if (textBuffer == null) + { + return VSConstants.VS_E_INCOMPATIBLEDOCDATA; + } + } + + try + { + // Create the Document (editor) + var newEditor = new BarDescriptorEditorPane(_vsServiceProvider, pszMkDocument, textBuffer); + ppunkDocView = Marshal.GetIUnknownForObject(newEditor); + ppunkDocData = Marshal.GetIUnknownForObject(textBuffer); + pbstrEditorCaption = ""; + return VSConstants.S_OK; + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to open XML file: \"{0}\"", pszMkDocument); + return VSConstants.VS_E_INCOMPATIBLEDOCDATA; + } + } + + /// + /// Private function to return the required service. + /// + /// Service Type + public object GetService(Type serviceType) + { + return _vsServiceProvider.GetService(serviceType); + } + + /// + /// This method is called by the Environment (inside IVsUIShellOpenDocument:: + /// OpenStandardEditor and OpenSpecificEditor) to map a LOGICAL view to a + /// PHYSICAL view. + /// + /// + /// + /// + public int MapLogicalView(ref Guid rguidLogicalView, out string pbstrPhysicalView) + { + // Initialize our parameter + pbstrPhysicalView = null; + + // we support only a single physical view + if (VSConstants.LOGVIEWID_Primary == rguidLogicalView) + { + // primary view uses NULL as pbstrPhysicalView + return VSConstants.S_OK; + } + + // must return E_NOTIMPL for any unrecognized rguidLogicalView values + return VSConstants.E_NOTIMPL; + } + + /// + /// Used for initialization of the editor in the environment + /// + /// pointer to the service provider. Can be used to obtain instances of other interfaces + public int SetSite(IOleIServiceProvider psp) + { + _vsServiceProvider = new ServiceProvider(psp); + return VSConstants.S_OK; + } + + /// + /// IDisposable Constructor + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// IDisposable Constructor Override + /// + /// + private void Dispose(bool disposing) + { + if (disposing) + { + // dispose all managed and unmanaged resources + if (_vsServiceProvider != null) + { + _vsServiceProvider.Dispose(); + _vsServiceProvider = null; + } + } + } + } +} diff --git a/src_vs2012/Package/Editors/BarDescriptorEditorPane.cs b/src_vs2012/Package/Editors/BarDescriptorEditorPane.cs new file mode 100644 index 00000000..cc16dd13 --- /dev/null +++ b/src_vs2012/Package/Editors/BarDescriptorEditorPane.cs @@ -0,0 +1,473 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.Package.ViewModels; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.TextManager.Interop; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.XmlEditor; +using Microsoft.VisualStudio; +using System.ComponentModel.Design; +using Microsoft.VisualStudio.Shell; +using System.Security.Permissions; + +namespace BlackBerry.Package.Editors +{ + /// + /// This control hosts the editor and is responsible for + /// handling the commands targeted to the editor + /// + [ComVisible(true)] + public sealed class BarDescriptorEditorPane : WindowPane, IOleComponent, IVsDeferredDocView, IVsLinkedUndoClient + { + #region Fields + private readonly ServiceProvider _service; + private readonly string _fileName; + private BarDescriptorEditorControl _vsDesignerControl; + private readonly IVsTextLines _textBuffer; + private uint _componentId; + private IOleUndoManager _undoManager; + private XmlStore _store; + private XmlModel _model; + #endregion + + #region "Window.Pane Overrides" + + /// + /// Constructor that calls the Microsoft.VisualStudio.Shell.WindowPane constructor then + /// our initialization functions. + /// + public BarDescriptorEditorPane(ServiceProvider service, string fileName, IVsTextLines textBuffer) + : base(null) + { + _fileName = fileName; + _textBuffer = textBuffer; + _service = service; + } + + /// + /// Event on close of the editor pane + /// + protected override void OnClose() + { + // unhook from Undo related services + if (_undoManager != null) + { + IVsLinkCapableUndoManager linkCapableUndoMgr = (IVsLinkCapableUndoManager)_undoManager; + if (linkCapableUndoMgr != null) + { + linkCapableUndoMgr.UnadviseLinkedUndoClient(); + } + + // Throw away the undo stack etc. + // It is important to “zombify” the undo manager when the owning object is shutting down. + // This is done by calling IVsLifetimeControlledObject.SeverReferencesToOwner on the undoManager. + // This call will clear the undo and redo stacks. This is particularly important to do if + // your undo units hold references back to your object. It is also important if you use + // "mdtStrict" linked undo transactions as this sample does (see IVsLinkedUndoTransactionManager). + // When one object involved in linked undo transactions clears its undo/redo stacks, then + // the stacks of the other documents involved in the linked transaction will also be cleared. + IVsLifetimeControlledObject lco = (IVsLifetimeControlledObject)_undoManager; + lco.SeverReferencesToOwner(); + _undoManager = null; + } + + IOleComponentManager mgr = GetService(typeof(SOleComponentManager)) as IOleComponentManager; + mgr.FRevokeComponent(_componentId); + + this.Dispose(true); + + base.OnClose(); + } + #endregion + + /// + /// Called after the WindowPane has been sited with an IServiceProvider from the environment + /// + protected override void Initialize() + { + base.Initialize(); + + // Create and initialize the editor + #region Register with IOleComponentManager + IOleComponentManager componentManager = (IOleComponentManager)GetService(typeof(SOleComponentManager)); + if (this._componentId == 0 && componentManager != null) + { + OLECRINFO[] crinfo = new OLECRINFO[1]; + crinfo[0].cbSize = (uint)Marshal.SizeOf(typeof(OLECRINFO)); + crinfo[0].grfcrf = (uint)_OLECRF.olecrfNeedIdleTime | (uint)_OLECRF.olecrfNeedPeriodicIdleTime; + crinfo[0].grfcadvf = (uint)_OLECADVF.olecadvfModal | (uint)_OLECADVF.olecadvfRedrawOff | (uint)_OLECADVF.olecadvfWarningsOff; + crinfo[0].uIdleTimeInterval = 100; + int hr = componentManager.FRegisterComponent(this, crinfo, out this._componentId); + ErrorHandler.Succeeded(hr); + } + #endregion + + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BarDescriptorEditorPane)); + + #region Hook Undo Manager + // Attach an IOleUndoManager to our WindowFrame. Merely calling QueryService + // for the IOleUndoManager on the site of our IVsWindowPane causes an IOleUndoManager + // to be created and attached to the IVsWindowFrame. The WindowFrame automaticall + // manages to route the undo related commands to the IOleUndoManager object. + // Thus, our only responsibilty after this point is to add IOleUndoUnits to the + // IOleUndoManager (aka undo stack). + _undoManager = (IOleUndoManager)GetService(typeof(SOleUndoManager)); + + // In order to use the IVsLinkedUndoTransactionManager, it is required that you + // advise for IVsLinkedUndoClient notifications. This gives you a callback at + // a point when there are intervening undos that are blocking a linked undo. + // You are expected to activate your document window that has the intervening undos. + if (_undoManager != null) + { + IVsLinkCapableUndoManager linkCapableUndoMgr = (IVsLinkCapableUndoManager)_undoManager; + if (linkCapableUndoMgr != null) + { + linkCapableUndoMgr.AdviseLinkedUndoClient(this); + } + } + #endregion + + // hook up our + XmlEditorService es = GetService(typeof(XmlEditorService)) as XmlEditorService; + _store = es.CreateXmlStore(); + _store.UndoManager = _undoManager; + + _model = _store.OpenXmlModel(new Uri(_fileName)); + + // This is the user control hosted by the tool window; Note that, even if this class implements IDisposable, + // we are not calling Dispose on this object. This is because ToolWindowPane calls Dispose on + // the object returned by the Content property. + _vsDesignerControl = new BarDescriptorEditorControl(_service, new BarEditorViewModel(_store, _model, this, _textBuffer)); + base.Content = _vsDesignerControl; + + RegisterIndependentView(true); + + IMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as IMenuCommandService; + if (null != mcs) + { + // Now create one object derived from MenuCommnad for each command defined in + // the CTC file and add it to the command service. + + // For each command we have to define its id that is a unique Guid/integer pair, then + // create the OleMenuCommand object for this command. The EventHandler object is the + // function that will be called when the user will select the command. Then we add the + // OleMenuCommand to the menu service. The addCommand helper function does all this for us. + AddCommand(mcs, VSConstants.GUID_VSStandardCommandSet97, (int)VSConstants.VSStd97CmdID.NewWindow, + new EventHandler(OnNewWindow), new EventHandler(OnQueryNewWindow)); + AddCommand(mcs, VSConstants.GUID_VSStandardCommandSet97, (int)VSConstants.VSStd97CmdID.ViewCode, + new EventHandler(OnViewCode), new EventHandler(OnQueryViewCode)); + } + } + + /// + /// returns the name of the file currently loaded + /// + public string FileName + { + get { return _fileName; } + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + RegisterIndependentView(false); + + using (_model) + { + _model = null; + } + using (_store) + { + _store = null; + } + } + base.Dispose(disposing); + } + + /// + /// Gets an instance of the RunningDocumentTable (RDT) service which manages the set of currently open + /// documents in the environment and then notifies the client that an open document has changed + /// + private void NotifyDocChanged() + { + // Make sure that we have a file name + if (_fileName.Length == 0) + return; + + // Get a reference to the Running Document Table + IVsRunningDocumentTable runningDocTable = (IVsRunningDocumentTable)GetService(typeof(SVsRunningDocumentTable)); + + // Lock the document + uint docCookie; + IVsHierarchy hierarchy; + uint itemID; + IntPtr docData; + int hr = runningDocTable.FindAndLockDocument( + (uint)_VSRDTFLAGS.RDT_ReadLock, + _fileName, + out hierarchy, + out itemID, + out docData, + out docCookie + ); + ErrorHandler.ThrowOnFailure(hr); + + // Send the notification + hr = runningDocTable.NotifyDocumentChanged(docCookie, (uint)__VSRDTATTRIB.RDTA_DocDataReloaded); + + // Unlock the document. + // Note that we have to unlock the document even if the previous call failed. + ErrorHandler.ThrowOnFailure(runningDocTable.UnlockDocument((uint)_VSRDTFLAGS.RDT_ReadLock, docCookie)); + + // Check ff the call to NotifyDocChanged failed. + ErrorHandler.ThrowOnFailure(hr); + } + + /// + /// Helper function used to add commands using IMenuCommandService + /// + /// The IMenuCommandService interface. + /// This guid represents the menu group of the command. + /// The command ID of the command. + /// An EventHandler which will be called whenever the command is invoked. + /// An EventHandler which will be called whenever we want to query the status of + /// the command. If null is passed in here then no EventHandler will be added. + private static void AddCommand(IMenuCommandService mcs, Guid menuGroup, int cmdID, + EventHandler commandEvent, EventHandler queryEvent) + { + // Create the OleMenuCommand from the menu group, command ID, and command event + CommandID menuCommandID = new CommandID(menuGroup, cmdID); + OleMenuCommand command = new OleMenuCommand(commandEvent, menuCommandID); + + // Add an event handler to BeforeQueryStatus if one was passed in + if (null != queryEvent) + { + command.BeforeQueryStatus += queryEvent; + } + + // Add the command using our IMenuCommandService instance + mcs.AddCommand(command); + } + + /// + /// Registers an independent view with the IVsTextManager so that it knows + /// the user is working with a view over the text buffer. This will trigger + /// the text buffer to prompt the user whether to reload the file if it is + /// edited outside of the environment. + /// + /// True to subscribe, false to unsubscribe + void RegisterIndependentView(bool subscribe) + { + IVsTextManager textManager = (IVsTextManager)GetService(typeof(SVsTextManager)); + + if (textManager != null) + { + if (subscribe) + { + textManager.RegisterIndependentView((IVsWindowPane)this, this._textBuffer); + } + else + { + textManager.UnregisterIndependentView((IVsWindowPane)this, this._textBuffer); + } + } + } + + /// + /// This method loads a localized string based on the specified resource. + /// + /// Resource to load + /// String loaded for the specified resource + internal string GetResourceString(string resourceName) + { + string resourceValue; + IVsResourceManager resourceManager = (IVsResourceManager)GetService(typeof(SVsResourceManager)); + if (resourceManager == null) + { + throw new InvalidOperationException("Could not get SVsResourceManager service. Make sure the package is Sited before calling this method"); + } + Guid packageGuid = new Guid(GuidList.guidVSNDK_PackageString); + int hr = resourceManager.LoadResourceString(ref packageGuid, -1, resourceName, out resourceValue); + ErrorHandler.ThrowOnFailure(hr); + return resourceValue; + } + + #region Commands + + /// + /// On create of new window + /// + /// + /// + private void OnQueryNewWindow(object sender, EventArgs e) + { + OleMenuCommand command = (OleMenuCommand)sender; + command.Enabled = true; + } + + /// + /// Create a new window + /// + /// + /// + private void OnNewWindow(object sender, EventArgs e) + { + NewWindow(); + } + + private void OnQueryViewCode(object sender, EventArgs e) + { + OleMenuCommand command = (OleMenuCommand)sender; + command.Enabled = true; + } + + /// + /// Event that fires on view of code + /// + /// + /// + private void OnViewCode(object sender, EventArgs e) + { + ViewCode(); + } + + /// + /// Method to create a new windows + /// + private void NewWindow() + { + int hr = VSConstants.S_OK; + + IVsUIShellOpenDocument uishellOpenDocument = (IVsUIShellOpenDocument)GetService(typeof(SVsUIShellOpenDocument)); + if (uishellOpenDocument != null) + { + IVsWindowFrame windowFrameOrig = (IVsWindowFrame)GetService(typeof(SVsWindowFrame)); + if (windowFrameOrig != null) + { + IVsWindowFrame windowFrameNew; + Guid LOGVIEWID_Primary = Guid.Empty; + hr = uishellOpenDocument.OpenCopyOfStandardEditor(windowFrameOrig, ref LOGVIEWID_Primary, out windowFrameNew); + if (windowFrameNew != null) + hr = windowFrameNew.Show(); + ErrorHandler.ThrowOnFailure(hr); + } + } + } + + /// + /// Method to viewcode + /// + private void ViewCode() + { + Guid XmlTextEditorGuid = new Guid("FA3CD31E-987B-443A-9B81-186104E8DAC1"); + + // Open the referenced document using our editor. + IVsWindowFrame frame; + IVsUIHierarchy hierarchy; + uint itemid; + VsShellUtilities.OpenDocumentWithSpecificEditor(this, _model.Name, + XmlTextEditorGuid, VSConstants.LOGVIEWID_Primary, out hierarchy, out itemid, out frame); + ErrorHandler.ThrowOnFailure(frame.Show()); + } + + #endregion + + #region IVsLinkedUndoClient + + public int OnInterveningUnitBlockingLinkedUndo() + { + return VSConstants.E_FAIL; + } + + #endregion + + #region IVsDeferredDocView + + /// + /// Assigns out parameter with the Guid of the EditorFactory. + /// + /// The output parameter that receives a value of the Guid of the EditorFactory. + /// S_OK if Marshal operations completed successfully. + int IVsDeferredDocView.get_CmdUIGuid(out Guid pGuidCmdId) + { + pGuidCmdId = GuidList.guidVSNDK_PackageEditorFactory; + return VSConstants.S_OK; + } + + /// + /// Assigns out parameter with the document view being implemented. + /// + /// The parameter that receives a reference to current view. + /// S_OK if Marshal operations completed successfully. + [EnvironmentPermission(SecurityAction.Demand)] + int IVsDeferredDocView.get_DocView(out IntPtr ppUnkDocView) + { + ppUnkDocView = Marshal.GetIUnknownForObject(this); + return VSConstants.S_OK; + } + + #endregion + + #region IOleComponent + + int IOleComponent.FContinueMessageLoop(uint uReason, IntPtr pvLoopData, MSG[] pMsgPeeked) + { + return VSConstants.S_OK; + } + + int IOleComponent.FDoIdle(uint grfidlef) + { + if (_vsDesignerControl != null) + { + _vsDesignerControl.DoIdle(); + } + return VSConstants.S_OK; + } + + int IOleComponent.FPreTranslateMessage(MSG[] pMsg) + { + return VSConstants.S_OK; + } + + int IOleComponent.FQueryTerminate(int fPromptUser) + { + return 1; //true + } + + int IOleComponent.FReserved1(uint dwReserved, uint message, IntPtr wParam, IntPtr lParam) + { + return VSConstants.S_OK; + } + + IntPtr IOleComponent.HwndGetWindow(uint dwWhich, uint dwReserved) + { + return IntPtr.Zero; + } + + void IOleComponent.OnActivationChange(IOleComponent pic, int fSameComponent, OLECRINFO[] pcrinfo, int fHostIsActivating, OLECHOSTINFO[] pchostinfo, uint dwReserved) { } + void IOleComponent.OnAppActivate(int fActive, uint dwOtherThreadID) { } + void IOleComponent.OnEnterState(uint uStateID, int fEnter) { } + void IOleComponent.OnLoseActivation() { } + void IOleComponent.Terminate() { } + + #endregion + } +} diff --git a/src_vs2012/Package/GuidList.cs b/src_vs2012/Package/GuidList.cs new file mode 100644 index 00000000..1921e691 --- /dev/null +++ b/src_vs2012/Package/GuidList.cs @@ -0,0 +1,42 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; + +namespace BlackBerry.Package +{ + static class GuidList + { + public const string guidVSNDK_PackageString = "db9f9c5f-fb27-4297-ab44-fa8774e962ca"; + public const string guidVSNDK_PackageCmdSetString = "d531fe01-f48e-443d-8ea1-1530a352525f"; + public const string guidToolWindowPersistanceString = "87346a4d-fbf2-46ff-8f59-31915e39cfb9"; + public const string guidVSNDK_PackageEditorFactoryString = "1daf1ab7-917a-4fdf-9b2f-0cd801301a70"; + public const string guidVsTemplateDesignerEditorFactoryString = "5f591054-0a88-4a07-8979-44dfb1b28fd8"; + + public const string guidVSStd97String = "{5efc7975-14bc-11cf-9b2b-00aa00573819}"; + public const string guidVSStd2KString = "{1496A755-94DE-11D0-8C3F-00C04FC2AAE2}"; + public const string guidVSDebugGroup = "{C9DD4A59-47FB-11D2-83E7-00C04F9902C1}"; + + public static readonly Guid guidVSNDK_PackageCmdSet = new Guid(guidVSNDK_PackageCmdSetString); + public static readonly Guid guidVSNDK_PackageEditorFactory = new Guid(guidVsTemplateDesignerEditorFactoryString); + + // Guid of the new pane with output messages + public const string guidTraceMainOutputWindowPaneString = "09963E4F-18EA-40E5-BA9E-1BC375AD68D1"; + public static readonly Guid GUID_TraceMainOutputWindowPane = new Guid(guidTraceMainOutputWindowPaneString); + public const string guidTraceGdbOutputWindowPaneString = "796156CD-B6AD-4574-9418-936BC258D38C"; + public static readonly Guid GUID_TraceGdbOutputWindowPane = new Guid(guidTraceGdbOutputWindowPaneString); + public const string guidTraceQConnOutputWindowPaneString = "56D1A17F-2632-49A5-B678-A18B306C07AA"; + public static readonly Guid GUID_TraceQConnOutputWindowPane = new Guid(guidTraceQConnOutputWindowPaneString); + }; +} diff --git a/src_vs2012/Package/Helpers/AttributeHelper.cs b/src_vs2012/Package/Helpers/AttributeHelper.cs new file mode 100644 index 00000000..522b5310 --- /dev/null +++ b/src_vs2012/Package/Helpers/AttributeHelper.cs @@ -0,0 +1,121 @@ +using System; + +namespace BlackBerry.Package.Helpers +{ + /// + /// Helper class for custom attributes. + /// + internal static class AttributeHelper + { + /// + /// Returns the GUID from an object. + /// + public static Guid GetGuidFrom(object guidObject) + { + // figure out what type of object they passed in and get the GUID from it + var strObject = guidObject as string; + if (strObject != null) + return new Guid(strObject); + + var typeObject = guidObject as Type; + if (typeObject != null) + return typeObject.GUID; + + var byteObject = guidObject as byte[]; + if (byteObject != null && byteObject.Length == 16) + return new Guid(byteObject); + + if (guidObject is Guid) + return (Guid)guidObject; + + throw new ArgumentException("Could not determine Guid from supplied object.", "guidObject"); + } + + /// + /// Gets the string representation of the GUID valid for registry settings. + /// + public static string Format(Guid guid) + { + return guid.ToString("B").ToUpperInvariant(); + } + + /// + /// Gets the string representation of the GUID valid for registry settings. + /// GUID is passed anyhow (string, type or GUID itself). + /// + public static string Format(object guidObject) + { + return Format(GetGuidFrom(guidObject)); + } + + /// + /// Gets the array of GUIDs from specified argument. + /// Argument can be any type (string, type or GUID itself). + /// + public static Guid[] GetArrayFrom(object guidArray) + { + var strObject = guidArray as string; + if (strObject != null) + { + return Convert(strObject.Split(',', ';', '|')); + } + + var strArrayObject = guidArray as string[]; + if (strArrayObject != null) + { + return Convert(strArrayObject); + } + + if (guidArray is Guid) + return new[] { (Guid) guidArray }; + + var guidArrayObject = guidArray as Guid[]; + if (guidArrayObject != null) + return guidArrayObject; + + var typeObject = guidArray as Type; + if (typeObject != null) + return new[] { typeObject.GUID }; + + var typeArrayObject = guidArray as Type[]; + if (typeArrayObject != null) + { + return Convert(typeArrayObject); + } + + var byteObject = guidArray as byte[]; + if (byteObject != null && byteObject.Length == 16) + return new[] { new Guid(byteObject) }; + + throw new ArgumentException("Invalid GUID array", "guidArray"); + } + + private static Guid[] Convert(string[] stringArray) + { + if (stringArray == null || stringArray.Length == 0) + return null; + + var result = new Guid[stringArray.Length]; + for (int i = 0; i < result.Length; i++) + { + result[i] = new Guid(stringArray[i]); + } + + return result; + } + + private static Guid[] Convert(Type[] typeArray) + { + if (typeArray == null || typeArray.Length == 0) + return null; + + var result = new Guid[typeArray.Length]; + for (int i = 0; i < result.Length; i++) + { + result[i] = typeArray[i].GUID; + } + + return result; + } + } +} diff --git a/src_vs2012/Package/Helpers/CertHelper.cs b/src_vs2012/Package/Helpers/CertHelper.cs new file mode 100644 index 00000000..35626951 --- /dev/null +++ b/src_vs2012/Package/Helpers/CertHelper.cs @@ -0,0 +1,147 @@ +using System; +using System.IO; +using System.Windows.Forms; +using BlackBerry.NativeCore.Diagnostics; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Dialogs; + +namespace BlackBerry.Package.Helpers +{ + internal static class CertHelper + { + /// + /// Helper method to let reload author. Returns 'true', when new data has been loaded and UI needs to be updated. + /// + public static bool ReloadAuthor(DeveloperDefinition developer) + { + if (developer == null) + throw new ArgumentNullException("developer"); + + string author; + + // verify if at least tried to register: + if (!developer.HasCertificate) + { + MessageBoxHelper.Show("Sorry, but certificate does not exist. You must register first", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + + // try to reload info with cached password: + if (developer.HasPassword) + { + author = developer.UpdateName(null); + + if (!string.IsNullOrEmpty(author)) + return true; + } + + // if it failed, ask for new password: + var form = new PasswordForm(); + if (form.ShowDialog() != DialogResult.OK) + return false; + + developer.UpdatePassword(form.Password, form.ShouldRemember); + + // try again to reload data from certificate: + author = developer.UpdateName(null); + VerifyAuthor(author); + + return !string.IsNullOrEmpty(author); + } + + /// + /// Helper class to import certificate into the DataPath location. + /// It also triggers asking for password. Returns 'true', when all was done correctly and UI needs to be updated. + /// + public static bool Import(DeveloperDefinition developer) + { + if (developer == null) + throw new ArgumentNullException("developer"); + if (string.IsNullOrEmpty(developer.DataPath)) + throw new ArgumentOutOfRangeException("developer"); + + // navigate for new certificate: + var form = DialogHelper.OpenCertFile(developer.DataPath); + + if (form.ShowDialog() == DialogResult.OK && File.Exists(form.FileName)) + { + // will need to move the file? - ask for confirmation, if one with the same name exists: + var srcPath = form.FileName; + var fileName = Path.GetFileName(srcPath); + var folderName = Path.GetDirectoryName(srcPath); + + if (string.IsNullOrEmpty(fileName) || string.IsNullOrEmpty(folderName)) + return false; + + // copy the file: + if (string.Compare(developer.DataPath, folderName, StringComparison.InvariantCultureIgnoreCase) != 0) + { + var destPath = Path.Combine(developer.DataPath, fileName); + if (File.Exists(destPath)) + { + var result = MessageBoxHelper.Show("File \"" + fileName + "\" already exists in certificate storage folder.\r\nDo you want to overwrite it?", + null, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation); + + if (result == DialogResult.Cancel) + return false; + if (result == DialogResult.No) + { + // generate new name: + fileName = "author-" + DateTime.Now.ToString("yyyy-MM-dd") + ".p12"; + destPath = Path.Combine(developer.DataPath, fileName); + } + } + + try + { + File.Copy(srcPath, destPath, true); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to copy certificate file \"{0}\"", srcPath); + MessageBoxHelper.Show(ex.Message, "Certificate file error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + } + + developer.UpdateCertificate(fileName); + + // ask for password several times: + while (true) + { + var passForm = new PasswordForm(); + + if (passForm.ShowDialog() == DialogResult.OK) + { + // load info from new certificate: + developer.UpdateName(passForm.Password); + + // succeeded - yes? + if (developer.HasName) + { + developer.UpdatePassword(passForm.Password, passForm.ShouldRemember); + return true; + } + + // no - display error and ask again: + VerifyAuthor(developer.Name); + } + else + { + break; + } + } + } + + return false; + } + + private static void VerifyAuthor(string author) + { + if (string.IsNullOrEmpty(author)) + { + MessageBoxHelper.Show("Unable to load info about author", "Invalid password or certificate file", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + } +} diff --git a/src_vs2012/Package/Helpers/CommandHelper.cs b/src_vs2012/Package/Helpers/CommandHelper.cs new file mode 100644 index 00000000..64ddb1a6 --- /dev/null +++ b/src_vs2012/Package/Helpers/CommandHelper.cs @@ -0,0 +1,58 @@ +using System; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio; + +namespace BlackBerry.Package.Helpers +{ + internal static class CommandHelper + { + /// + /// Registers specified handlers for a command given by guid:id anywhere inside Visual Studio. + /// + public static CommandEvents Register(DTE2 dte, Guid commandGuid, VSConstants.VSStd97CmdID commandId, _dispCommandEvents_BeforeExecuteEventHandler beforeHandler, + _dispCommandEvents_AfterExecuteEventHandler afterHandler) + { + return Register(dte, commandGuid, (int)commandId, beforeHandler, afterHandler); + } + + /// + /// Registers specified handlers for a command given by guid:id anywhere inside Visual Studio. + /// + public static CommandEvents Register(DTE2 dte, Guid commandGuid, VSConstants.VSStd2KCmdID commandId, _dispCommandEvents_BeforeExecuteEventHandler beforeHandler, + _dispCommandEvents_AfterExecuteEventHandler afterHandler) + { + return Register(dte, commandGuid, (int)commandId, beforeHandler, afterHandler); + } + + /// + /// Registers specified handlers for a command given by guid:id anywhere inside Visual Studio. + /// + public static CommandEvents Register(DTE2 dte, Guid commandGuid, int commandId, _dispCommandEvents_BeforeExecuteEventHandler beforeHandler, + _dispCommandEvents_AfterExecuteEventHandler afterHandler) + { + if (dte == null) + throw new ArgumentNullException("dte"); + if (dte.Events == null) + throw new ArgumentOutOfRangeException("dte"); + + if (beforeHandler == null && afterHandler == null) + return null; + + var commandEvents = dte.Events.CommandEvents[commandGuid.ToString("B"), commandId]; + if (commandEvents != null) + { + if (beforeHandler != null) + { + commandEvents.BeforeExecute += beforeHandler; + } + if (afterHandler != null) + { + commandEvents.AfterExecute += afterHandler; + } + } + + return commandEvents; + } + } +} diff --git a/src_vs2012/Package/Helpers/DialogHelper.cs b/src_vs2012/Package/Helpers/DialogHelper.cs new file mode 100644 index 00000000..e556eb56 --- /dev/null +++ b/src_vs2012/Package/Helpers/DialogHelper.cs @@ -0,0 +1,230 @@ +using System.Diagnostics; +using System.IO; +using System.Windows.Forms; + +namespace BlackBerry.Package.Helpers +{ + internal static class DialogHelper + { + /// + /// Shows 'browse-for-folder' dialog. + /// + public static string BrowseForFolder(string startupPath, string description) + { + var browser = new FolderBrowserDialog(); + browser.ShowNewFolderButton = true; + browser.SelectedPath = startupPath; + browser.Description = description; + + if (browser.ShowDialog() == DialogResult.OK) + return browser.SelectedPath; + + return startupPath; + } + + /// + /// Returns preconfigured window for opening .cproject files. + /// + public static OpenFileDialog OpenNativeCoreProject(string title, string startupPath) + { + var openFile = new OpenFileDialog(); + openFile.Title = title; + openFile.InitialDirectory = startupPath; + openFile.DefaultExt = ".cproject"; + openFile.Filter = "Project|*.cproject;*.project;*.properties|All files|*.*"; + + openFile.FilterIndex = 0; + openFile.CheckFileExists = true; + openFile.CheckPathExists = true; + + return openFile; + } + + /// + /// Returns preconfigured window for opening BAR files. + /// + public static OpenFileDialog OpenBarFile(string title, string startupPath) + { + var openFile = new OpenFileDialog(); + openFile.Title = title; + openFile.InitialDirectory = startupPath; + openFile.DefaultExt = ".bar"; + openFile.Filter = "Bar files|*.bar|All files|*.*"; + openFile.FilterIndex = 0; + openFile.CheckFileExists = true; + openFile.CheckPathExists = true; + + return openFile; + } + + /// + /// Returns preconfigured window for opening certificate files. + /// + public static OpenFileDialog OpenCertFile(string startupPath) + { + var openFile = new OpenFileDialog(); + openFile.Title = "Opening certificate file"; + openFile.InitialDirectory = startupPath; + openFile.DefaultExt = ".p12"; + openFile.Filter = "Certificate files|*.p12|All files|*.*"; + openFile.FilterIndex = 0; + openFile.CheckFileExists = true; + openFile.CheckPathExists = true; + + return openFile; + } + + /// + /// Returns preconfigured window for opening CSJ files. + /// + public static OpenFileDialog OpenCsjFile(string startupPath, string title) + { + var openFile = new OpenFileDialog(); + openFile.Title = title ?? "Opening CSJ file"; + openFile.InitialDirectory = startupPath; + openFile.DefaultExt = ".csj"; + openFile.Filter = "Code Signing files|*.csj;*.csk|Certificate files|*.p12|All files|*.*"; + openFile.FilterIndex = 0; + openFile.CheckFileExists = true; + openFile.CheckPathExists = true; + + return openFile; + } + + /// + /// Returns preconfigured window for saving BAR file. + /// + public static SaveFileDialog SaveBarFile(string title, string startupPath, string fileName) + { + var saveFile = new SaveFileDialog(); + saveFile.Title = title; + saveFile.InitialDirectory = startupPath; + saveFile.FileName = fileName; + saveFile.DefaultExt = ".bar"; + saveFile.Filter = "Bar files|*.bar|All files|*.*"; + saveFile.FilterIndex = 0; + saveFile.CreatePrompt = false; + saveFile.OverwritePrompt = true; + + return saveFile; + } + + /// + /// Returns preconfigured window for opening ZIP files. + /// + public static OpenFileDialog OpenZipFile(string title) + { + var openFile = new OpenFileDialog(); + openFile.Title = title; + openFile.DefaultExt = ".bar"; + openFile.Filter = "Zip files|*.zip|All files|*.*"; + openFile.FilterIndex = 0; + openFile.CheckFileExists = true; + openFile.CheckPathExists = true; + + return openFile; + } + + /// + /// Returns preconfigured window for saving ZIP file. + /// + public static SaveFileDialog SaveZipFile(string title, string fileName) + { + var saveFile = new SaveFileDialog(); + saveFile.Title = title; + saveFile.FileName = string.IsNullOrEmpty(fileName) ? string.Empty : Path.ChangeExtension(fileName, ".zip"); + saveFile.DefaultExt = ".zip"; + saveFile.Filter = "Zip files|*.zip|All files|*.*"; + saveFile.FilterIndex = 0; + saveFile.CreatePrompt = false; + saveFile.OverwritePrompt = true; + + return saveFile; + } + + /// + /// Returns preconfigured window for opening ANY files. + /// + public static OpenFileDialog OpenAnyFile(string title) + { + var openFile = new OpenFileDialog(); + openFile.Title = title; + openFile.DefaultExt = string.Empty; + openFile.Filter = "All files|*.*"; + openFile.FilterIndex = 1; + openFile.CheckFileExists = true; + openFile.CheckPathExists = true; + + return openFile; + } + + /// + /// Returns preconfigured window for saving ANY file. + /// + public static SaveFileDialog SaveAnyFile(string title, string fileName) + { + var saveFile = new SaveFileDialog(); + saveFile.Title = title; + saveFile.FileName = fileName; + saveFile.DefaultExt = string.Empty; + saveFile.Filter = "All files|*.*"; + saveFile.FilterIndex = 1; + saveFile.CreatePrompt = false; + saveFile.OverwritePrompt = true; + + return saveFile; + } + + /// + /// Opens Windows Explorer window with specified path. + /// + public static void StartExplorer(string path) + { + if (string.IsNullOrEmpty(path)) + return; + + // if specified directory doesn't exist, create it: + try + { + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + } + catch + { + } + + // open Explorer window with this folder: + Process.Start("Explorer.exe", "/e,\"" + path + "\""); + } + + /// + /// Opens Windows Explorer window with specified file selected. + /// + public static void StartExplorerForFile(string path) + { + if (string.IsNullOrEmpty(path)) + return; + + // if file doesn't exits, try to open its parent folder: + if (!File.Exists(path)) + { + StartExplorer(Path.GetDirectoryName(path)); + return; + } + + // open Explorer window with specified file selected: + Process.Start("Explorer.exe", "/select,\"" + path + "\""); + } + + /// + /// Opens a default web-browser with specified URL. + /// + public static void StartURL(string url) + { + if (string.IsNullOrEmpty(url) || !(url.StartsWith("http://") || url.StartsWith("https://"))) + return; + + Process.Start(url); + } + } +} diff --git a/src_vs2012/Package/Helpers/DteHelper.cs b/src_vs2012/Package/Helpers/DteHelper.cs new file mode 100644 index 00000000..cb1c12ee --- /dev/null +++ b/src_vs2012/Package/Helpers/DteHelper.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.VCProjectEngine; + +namespace BlackBerry.Package.Helpers +{ + /// + /// Helper class providing info from DTE in simple way. + /// + internal static class DteHelper + { + /// + /// Gets the list of VisualC++ projects within the solution. + /// + public static Project[] GetProjects(DTE2 dte) + { + if (dte == null) + throw new ArgumentNullException("dte"); + + var result = new List(); + foreach (Project project in dte.Solution.Projects) + { + var vc = project.Object as VCProject; + if (vc != null) + { + result.Add(project); + } + } + + return result.ToArray(); + } + + /// + /// Gets the output path for specified project. + /// + public static string GetOutputPath(Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + ConfigurationManager config = project.ConfigurationManager; + Configuration active = config.ActiveConfiguration; + + foreach (Property prop in active.Properties) + { + try + { + if (prop.Name == "OutputPath") + { + return prop.Value.ToString(); + } + } + catch + { + } + } + + return null; + } + } +} diff --git a/src_vs2012/Package/Helpers/IconHelper.cs b/src_vs2012/Package/Helpers/IconHelper.cs new file mode 100644 index 00000000..2b54a745 --- /dev/null +++ b/src_vs2012/Package/Helpers/IconHelper.cs @@ -0,0 +1,90 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using BlackBerry.NativeCore.Diagnostics; + +namespace BlackBerry.Package.Helpers +{ + /// + /// Helper class to load system icons for files and folders. + /// Original code from Microsoft sample at: http://support.microsoft.com/kb/319350 + /// + internal static class IconHelper + { + #region P/Invoke + + [DllImport("shell32.dll", CharSet = CharSet.Auto)] + private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFileInfo psfi, uint cbFileInfo, uint uFlags); + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DestroyIcon(IntPtr hIcon); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + struct SHFileInfo + { + public IntPtr hIcon; + public int iIcon; + public uint dwAttributes; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string szDisplayName; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] + public string szTypeName; + } + + public const uint SHGFI_ICON = 0x100; + public const uint SHGFI_SMALLICON = 0x1; + public const uint SHGFI_LARGEICON = 0x0; + public const uint SHGFI_OPENICON = 0x02; + + public const uint SHGFI_USEFILEATTRIBUTES = 0x10; + public const uint FILE_ATTRIBUTE_DIRECTORY = 0x10; + public const uint FILE_ATTRIBUTE_FILE = 0x100; + + #endregion + + /// + /// Creates new instance of an image-source with icon for specified file type or folder. + /// + public static ImageSource GetIcon(string extension, bool isSmall, bool isDirectory, bool isOpen) + { + var flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | (isSmall ? SHGFI_SMALLICON : SHGFI_LARGEICON); + var attribute = (isDirectory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_FILE) | (isOpen ? SHGFI_OPENICON : 0u); + var shfi = new SHFileInfo(); + + var result = SHGetFileInfo(extension, attribute, ref shfi, (uint)Marshal.SizeOf(shfi), flags); + if (result == IntPtr.Zero) + throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); + + try + { + return ConvertToImageSource(shfi.hIcon); + } + catch (Exception ex) + { + TraceLog.WriteException(ex, "Unable to load icon for: " + extension); + throw; + } + finally + { + DestroyIcon(shfi.hIcon); + } + } + + private static ImageSource ConvertToImageSource(IntPtr handle) + { + using (Icon i = Icon.FromHandle(handle)) + { + var img = Imaging.CreateBitmapSourceFromHIcon(i.Handle, new Int32Rect(0, 0, i.Width, i.Height), BitmapSizeOptions.FromEmptyOptions()); + img.Freeze(); + return img; + } + } + } +} diff --git a/src_vs2012/Package/Helpers/MessageBoxHelper.cs b/src_vs2012/Package/Helpers/MessageBoxHelper.cs new file mode 100644 index 00000000..9f0f8369 --- /dev/null +++ b/src_vs2012/Package/Helpers/MessageBoxHelper.cs @@ -0,0 +1,160 @@ +using System; +using System.Windows.Forms; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; + +namespace BlackBerry.Package.Helpers +{ + /// + /// Helper class for displaying native dialog boxes. + /// + static class MessageBoxHelper + { + private const int IDABORT = 3; + private const int IDCANCEL = 2; + private const int IDIGNORE = 5; + private const int IDNO = 7; + private const int IDOK = 1; + private const int IDRETRY = 4; + private const int IDYES = 6; + + private static readonly IVsUIShell _uiShell; + + /// + /// Initialize internal structures. + /// + static MessageBoxHelper() + { + // do we need to initialize it again? + if (_uiShell == null) + { + _uiShell = Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsUIShell)) as IVsUIShell; + if (_uiShell == null) + throw new InvalidOperationException("Unable to initialize UiShell"); + } + } + + /// + /// Shows message box. + /// + public static DialogResult Show(string text, string title, MessageBoxButtons buttons, MessageBoxIcon icon, + MessageBoxDefaultButton defaultButton) + { + var guid = Guid.Empty; + int result; + var xButton = OLEMSGBUTTON.OLEMSGBUTTON_OKCANCEL; + var xIcon = OLEMSGICON.OLEMSGICON_INFO; + var xDefaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST; + + switch (buttons) + { + case MessageBoxButtons.OK: + xButton = OLEMSGBUTTON.OLEMSGBUTTON_OK; + break; + case MessageBoxButtons.OKCancel: + xButton = OLEMSGBUTTON.OLEMSGBUTTON_OKCANCEL; + break; + case MessageBoxButtons.RetryCancel: + xButton = OLEMSGBUTTON.OLEMSGBUTTON_RETRYCANCEL; + break; + case MessageBoxButtons.AbortRetryIgnore: + xButton = OLEMSGBUTTON.OLEMSGBUTTON_ABORTRETRYIGNORE; + break; + case MessageBoxButtons.YesNo: + xButton = OLEMSGBUTTON.OLEMSGBUTTON_OKCANCEL; + break; + case MessageBoxButtons.YesNoCancel: + xButton = OLEMSGBUTTON.OLEMSGBUTTON_YESNOCANCEL; + break; + } + + switch (icon) + { + case MessageBoxIcon.Question: + xIcon = OLEMSGICON.OLEMSGICON_QUERY; + break; + case MessageBoxIcon.Information: + xIcon = OLEMSGICON.OLEMSGICON_INFO; + break; + case MessageBoxIcon.Error: + xIcon = OLEMSGICON.OLEMSGICON_CRITICAL; + break; + case MessageBoxIcon.Exclamation: + xIcon = OLEMSGICON.OLEMSGICON_WARNING; + break; + } + + switch (defaultButton) + { + case MessageBoxDefaultButton.Button1: + xDefaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST; + break; + case MessageBoxDefaultButton.Button2: + xDefaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_SECOND; + break; + case MessageBoxDefaultButton.Button3: + xDefaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_THIRD; + break; + } + + // show proper message box: + ErrorHandler.ThrowOnFailure(_uiShell.ShowMessageBox(0, ref guid, title, text, null, 0, + xButton, + xDefaultButton, + xIcon, 0, out result)); + + // interpret the result: + switch (result) + { + case IDOK: + return buttons == MessageBoxButtons.YesNo ? DialogResult.Yes : DialogResult.OK; + case IDCANCEL: + return buttons == MessageBoxButtons.YesNo ? DialogResult.No : DialogResult.Cancel; + case IDABORT: + return DialogResult.Abort; + case IDIGNORE: + return DialogResult.Ignore; + case IDNO: + return DialogResult.No; + case IDYES: + return DialogResult.Yes; + case IDRETRY: + return DialogResult.Retry; + default: + return DialogResult.None; + } + } + + /// + /// Shows message box. + /// + public static DialogResult Show(string text, string title, MessageBoxButtons buttons, MessageBoxIcon icon) + { + return Show(text, title, buttons, icon, MessageBoxDefaultButton.Button1); + } + + /// + /// Shows message box. + /// + public static DialogResult Show(string text, string title, MessageBoxButtons buttons) + { + return Show(text, title, buttons, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); + } + + /// + /// Shows message box. + /// + public static DialogResult Show(string text, string title, MessageBoxIcon icon) + { + return Show(text, title, MessageBoxButtons.OK, icon, MessageBoxDefaultButton.Button1); + } + + /// + /// Shows message box. + /// + public static DialogResult Show(string text, string title) + { + return Show(text, title, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); + } + } +} diff --git a/src_vs2012/Package/Helpers/ProjectHelper.cs b/src_vs2012/Package/Helpers/ProjectHelper.cs new file mode 100644 index 00000000..3b94e6bc --- /dev/null +++ b/src_vs2012/Package/Helpers/ProjectHelper.cs @@ -0,0 +1,442 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.VCProjectEngine; +using Microsoft.Win32; + +namespace BlackBerry.Package.Helpers +{ + /// + /// Helper class for accessing Visual C++ project properties. + /// + internal static class ProjectHelper + { + /// + /// Gets the project out of any selected item inside Solution Explorer of Visual Studio. + /// + public static Project GetProject(IVsHierarchy hierarchy) + { + if (hierarchy == null) + throw new ArgumentNullException("hierarchy"); + + object obj; + Project project = null; + if (ErrorHandler.Succeeded(hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ExtObject, out obj)) && obj != null) + { + project = obj as Project; + } + return project; + } + + /// + /// Updates specific project settings. It can be used to setup value only for particular platform (or 'null' to overwrite for all of them). + /// + public static void SetValue(VCProject project, string ruleName, string propertyName, string platformName, string configurationName, string value, bool appendValues, char valueSeparator, string inheritDefaults) + { + if (project == null) + throw new ArgumentNullException("project"); + if (string.IsNullOrEmpty(value)) + return; + if (valueSeparator == '\0' && (appendValues || !string.IsNullOrEmpty(inheritDefaults))) + throw new ArgumentNullException("valueSeparator"); + + foreach (VCConfiguration configuration in (IVCCollection) project.Configurations) + { + if (string.IsNullOrEmpty(configurationName) || string.Compare(configuration.ConfigurationName, configurationName, StringComparison.OrdinalIgnoreCase) == 0) + { + var rulePropertyStore = configuration.Rules.Item(ruleName) as IVCRulePropertyStorage; + if (rulePropertyStore != null) + { + var currentPlatformName = ((VCPlatform) configuration.Platform).Name; + if (string.IsNullOrEmpty(platformName) || string.Compare(currentPlatformName, platformName, StringComparison.OrdinalIgnoreCase) == 0) + { + var existingPropertyValue = rulePropertyStore.GetUnevaluatedPropertyValue(propertyName); + var newPropertyValue = appendValues + ? MergePropertyValues(existingPropertyValue, value, valueSeparator, inheritDefaults) + : (string.IsNullOrEmpty(inheritDefaults) ? value : MergePropertyValues(null, value, valueSeparator, inheritDefaults)); + + // set new value, if it's really new: + if (!string.IsNullOrEmpty(newPropertyValue) && newPropertyValue != existingPropertyValue && newPropertyValue != inheritDefaults) + { + rulePropertyStore.SetPropertyValue(propertyName, newPropertyValue); + } + } + } + } + } + } + + /// + /// Merges existing and new values set to the project (MSBuild) property. + /// If 'inheritDefaults' value is specified, it is enforced to be placed at the very end. + /// + public static string MergePropertyValues(string existingValue, string value, char valueSeparator, string inheritDefaults) + { + if (valueSeparator == '\0') + throw new ArgumentNullException("valueSeparator"); + if (string.IsNullOrEmpty(value)) + return existingValue; + + var resultArray = new List(); + bool canAddInheritDefaults = false; + + // first add existing values: + if (!string.IsNullOrEmpty(existingValue)) + { + var existingValueArray = existingValue.Split(new[] { valueSeparator }, StringSplitOptions.RemoveEmptyEntries); + + if (string.IsNullOrEmpty(inheritDefaults)) + { + resultArray.AddRange(existingValueArray); + } + else + { + foreach (var ev in existingValueArray) + { + if (string.CompareOrdinal(ev, inheritDefaults) != 0) + { + resultArray.Add(ev); + } + else + { + canAddInheritDefaults = true; + } + } + } + } + else + { + canAddInheritDefaults = true; + } + + // than append new values: + var valueArray = value.Split(new[] { valueSeparator }, StringSplitOptions.RemoveEmptyEntries); + foreach (var v in valueArray) + { + if (!resultArray.Contains(v)) + { + resultArray.Add(v); + } + } + + // and add inherited marker, if specified: + if (!string.IsNullOrEmpty(inheritDefaults) && resultArray.Count > 0 && canAddInheritDefaults) + { + resultArray.Add(inheritDefaults); + } + + // serialize final value: + var result = new StringBuilder(); + + for (int i = 0; i < resultArray.Count; i++) + { + result.Append(resultArray[i]); + + if (i < resultArray.Count - 1) + { + result.Append(valueSeparator); + } + } + + return result.ToString(); + } + + /// + /// Adds additional set of dependencies (libraries) at the end of existing list in project properties. + /// + public static void AddAdditionalDependencies(VCProject project, string platformName, string configurationName, params string[] values) + { + if (project == null) + throw new ArgumentNullException("project"); + + SetValue(project, "Link", "AdditionalDependencies", platformName, configurationName, string.Join(";", values), true, ';', "%(AdditionalDependencies)"); + } + + /// + /// Adds additional set of dependency-directories (search directories for libraries) at the end of existing list in project properties. + /// + public static void AddAdditionalDependencyDirectories(VCProject project, string platformName, string configurationName, params string[] values) + { + if (project == null) + throw new ArgumentNullException("project"); + + SetValue(project, "Link", "AdditionalLibraryDirectories", platformName, configurationName, string.Join(";", values), true, ';', "%(AdditionalLibraryDirectories)"); + } + + /// + /// Adds additional set of preprocessor definitions at the end of existing list in project properties. + /// + public static void AddPreprocessorDefines(VCProject project, string platformName, string configurationName, params string[] values) + { + if (project == null) + throw new ArgumentNullException("project"); + + SetValue(project, "CL", "PreprocessorDefinitions", platformName, configurationName, string.Join(";", values), true, ';', "%(PreprocessorDefinitions)"); + } + + /// + /// Adds additional set of include-directories (search directories for header files) at the end of existing list in project properties. + /// + public static void AddAdditionalIncludeDirectories(VCProject project, string platformName, string configurationName, params string[] values) + { + if (project == null) + throw new ArgumentNullException("project"); + + SetValue(project, "CL", "AdditionalIncludeDirectories", platformName, configurationName, string.Join(";", values), true, ';', "%(AdditionalIncludeDirectories)"); + } + + /// + /// Updates build-output directories in project properties. + /// + public static void SetBuildOutputDirectory(VCProject project, string platformName, string configurationName, string value) + { + if (project == null) + throw new ArgumentNullException("project"); + + SetValue(project, "ConfigurationGeneral", "OutDir", platformName, configurationName, value, false, '\0', null); + } + + /// + /// Gets the evaluated value of specific Visual C++ project property. + /// + public static string GetValue(Project project, string rule, string propertyName) + { + if (project == null) + throw new ArgumentNullException("project"); + + if (project.ConfigurationManager == null || project.ConfigurationManager.ActiveConfiguration == null) + return null; + + var activeConfiguration = project.ConfigurationManager.ActiveConfiguration; + var currentConfigurationName = activeConfiguration.ConfigurationName; + var currentPlatformName = activeConfiguration.PlatformName; + var cppProject = project.Object as VCProject; + + if (cppProject != null) + { + foreach (VCConfiguration configuration in (IVCCollection) cppProject.Configurations) + { + if (string.Compare(configuration.ConfigurationName, currentConfigurationName, StringComparison.InvariantCulture) == 0) + { + var platformName = ((VCPlatform) configuration.Platform).Name; + if (string.Compare(platformName, currentPlatformName, StringComparison.InvariantCulture) == 0) + { + var rulePropertyStorage = configuration.Rules.Item(rule) as IVCRulePropertyStorage; + if (rulePropertyStorage != null) + { + var value = rulePropertyStorage.GetEvaluatedPropertyValue(propertyName); + return value; + } + } + } + } + } + + return null; + } + + /// + /// Gets the full path to the target outcome of specified Visual C++ project. + /// + public static string GetTargetFullName(Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + var targetName = GetValue(project, "ConfigurationGeneral", "TargetName"); + if (string.IsNullOrEmpty(targetName)) + return null; + + targetName += GetValue(project, "ConfigurationGeneral", "TargetExt"); + + // The output folder can be anything, let's assume it's any of these patterns: + // 1) "\\server\folder" + // 2) "drive:\folder" + // 3) "..\..\folder" + // 4) "folder" + // 5) "" + var outputPath = GetValue(project, "ConfigurationGeneral", "OutDir"); + + if (string.IsNullOrEmpty(outputPath)) + { + // 5) "" + var projectFolder = Path.GetDirectoryName(project.FullName); + if (string.IsNullOrEmpty(projectFolder)) + return targetName; + return Path.Combine(projectFolder, targetName); + } + + if (outputPath.Length >= 2 && outputPath[0] == Path.DirectorySeparatorChar && outputPath[1] == Path.DirectorySeparatorChar) + { + // 1) "\\server\folder" + return Path.Combine(outputPath, targetName); + } + + if (outputPath.Length >= 3 && outputPath[1] == Path.VolumeSeparatorChar && outputPath[2] == Path.DirectorySeparatorChar) + { + // 2) "drive:\folder" + return Path.Combine(outputPath, targetName); + } + + if (outputPath.StartsWith("..\\") || outputPath.StartsWith("../")) + { + // 3) "..\..\folder" + + var projectFolder = Path.GetDirectoryName(project.FullName); + while (outputPath.StartsWith("..\\") || outputPath.StartsWith("../")) + { + outputPath = outputPath.Substring(3); + if (!string.IsNullOrEmpty(projectFolder)) + { + projectFolder = Path.GetDirectoryName(projectFolder); + } + } + + if (string.IsNullOrEmpty(projectFolder)) + return Path.Combine(outputPath, targetName); + return Path.Combine(projectFolder, outputPath, targetName); + } + + // 4) "folder" + var folder = Path.GetDirectoryName(project.FullName); + if (string.IsNullOrEmpty(folder)) + return Path.Combine(outputPath, targetName); + return Path.Combine(folder, outputPath, targetName); + } + + /// + /// Gets the project's target architecture (x86 for simulator and armle-v7 for device). + /// + public static string GetTargetArchitecture(Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + return GetValue(project, "ConfigurationGeneral", "TargetArch"); + } + + /// + /// Tries to guess the full path to the target outcome of specified Visual C++ project. + /// This is a complimentary method to GetTargetFullName(). As the extended BlackBerry projects + /// are mostly based on makefiles it might be quite hard to say sure (based on Visual Studio settings only), + /// where the target binary is created. That's why we use some non-common knowledge + /// about the Cascades make system. + /// + public static string GuessTargetFullName(Project project) + { + if (project == null) + throw new ArgumentNullException("project"); + + if (project.ConfigurationManager == null || project.ConfigurationManager.ActiveConfiguration == null) + return null; + + var appType = GetValue(project, "ConfigurationGeneral", "ConfigurationAppType"); + if (string.Compare(appType, "Regular", StringComparison.OrdinalIgnoreCase) == 0 + || string.IsNullOrEmpty(appType)) + { + return GetTargetFullName(project); + } + + // get file name and extension: + var targetName = GetValue(project, "ConfigurationGeneral", "TargetName"); + if (string.IsNullOrEmpty(targetName)) + return null; + + targetName += GetValue(project, "ConfigurationGeneral", "TargetExt"); + + // check, whether we compile against device or simulator: + var targetCpu = GetValue(project, "ConfigurationGeneral", "TargetArch"); + var projectDir = Path.GetDirectoryName(project.FullName); + + if (string.Compare(targetCpu, "armle-v7", StringComparison.OrdinalIgnoreCase) == 0 && !string.IsNullOrEmpty(projectDir)) + { + var path = Path.Combine(projectDir, "arm", "o.le-v7-g", targetName); + if (File.Exists(path)) + return path; + return Path.Combine(projectDir, "arm", "o.le-v7", targetName + ".so"); // Cascades apps in Device-Release mode are regular shared-object! + } + + if (string.Compare(targetCpu, "x86", StringComparison.OrdinalIgnoreCase) == 0 && !string.IsNullOrEmpty(projectDir)) + { + var path = Path.Combine(projectDir, "x86", "o-g", targetName); + if (File.Exists(path)) + return path; + return Path.Combine(projectDir, "x86", "o", targetName); + } + + // unsupported architecture: + return null; + } + + /// + /// Gets the name of the file with info about run application on the target for passed deployment in MSBuild. + /// + public static string GetFlagFileNameForRunInfo(Project project) + { + return GetFlagFileName(project, "runinfo"); + } + + /// + /// Gets the name of the file for debug-native flag passed to MSBuild. + /// + public static string GetFlagFileNameForDebugNative(Project project) + { + return GetFlagFileName(project, "debug-native"); + } + + /// + /// Gets the name of the file for CSK-password passed to MSBuild. + /// + public static string GetFlagFileNameForCSKPassword(Project project) + { + return GetFlagFileName(project, "csk-password"); + } + + private static string GetFlagFileName(Project project, string flagName) + { + if (project == null) + throw new ArgumentNullException("project"); + if (string.IsNullOrEmpty(flagName)) + throw new ArgumentNullException("flagName"); + + // is it 'miscellaneous files'? + if (string.IsNullOrEmpty(project.FullName)) + return null; + + return Path.Combine(Path.GetDirectoryName(project.FullName), string.Concat("vsndk-", flagName, ".flag")); + } + + /// + /// Gets the global default folder, where Visual Studio is supposed to store projects (generally suggesting it at startup of New Project Wizard). + /// + public static string GetDefaultProjectFolder(DTE2 dte) + { + if (dte == null) + throw new ArgumentNullException("dte"); + + RegistryKey key = null; + try + { + key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\VisualStudio\" + dte.Version); + + return key != null ? key.GetValue("DefaultNewProjectLocation", null).ToString() : null; + } + catch + { + return null; + } + finally + { + if (key != null) + { + key.Close(); + } + } + } + } +} diff --git a/src_vs2012/Package/Languages/Qml/QmlColorizer.cs b/src_vs2012/Package/Languages/Qml/QmlColorizer.cs new file mode 100644 index 00000000..91d3c396 --- /dev/null +++ b/src_vs2012/Package/Languages/Qml/QmlColorizer.cs @@ -0,0 +1,543 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.TextManager.Interop; + +namespace BlackBerry.Package.Languages.Qml +{ + /// + /// Colorizer class responsible for correctly assigning colors to particular chars inside QML file. + /// + internal sealed class QmlColorizer : IVsColorizer, IVsColorizer2 + { + #region Internal Classes + + private const string Operators = "+-~=/\\*%&.,:;@|!?#$^(){}[]<>"; + + private static readonly string[] Keywords = new string[] + { + "alias", "and", "break", "case", "continue", "do", "decimal", "else", "if", "false", "for", "function", "import", "not", "or", "property", "return", "signal", "switch", "true", "var", "while", "ListItemData", + "ListItem" + }; + + private static readonly string[] BasicTypes = new string[] { "bool", "double", "int", "string", "variant", "QTimer" }; + + private static readonly string[] CascadeBasicTypes = new string[] + { + "ActionBar", "ActionBarPlacement", "Color", "ExpandMode", "FocusPolicy", "FontSize", "FontWeight", "InputType", "PickerKind", "ScalingMethod", "ScalingMode", "ScrollIndicatorMode", + "ScrollMode", "ScrollPosition", "SnapMode", "SupportedDisplayOrientation", "SystemDefaults", "UIOrientation", "TitleBarAppearance", "VisualStyle", + "AbsoluteLayout", "AbsoluteLayoutProperties", "DockLayout", "FlowListLayout", "FlowListLayoutProperties", "FreeFormTitleBarKindProperties", "GridLayout", "GridListLayout", + "HorizontalAlignment", "Layout", "LayoutOrientation", "LayoutProperties", + "ListHeaderMode", "ListLayout", "StackLayout", "StackLayoutProperties", "StackListLayout", "StackLayoutProperties", "TitleBarExpandableAreaIndicatorVisibility", "TitleBarKind", "TouchType", + "VerticalAlignment" + }; + + private static readonly string[] CascadesBasicSignals = new string[] + { + "actions", "animations", "attachedObjects", "eventHandlers", "gestureHandlers", "onClicked", "onCreationCompleted", "onEnded", "onHeaderDateChanged", "onSelectedValueChanged", "onStarted", "onTextChanged", "onTextChanging", "onTapped", + "onTimeout", "onTriggered", "onValueChanged" + }; + + private static readonly string[] CascadesControlTypes = new string[] + { + "ActionItem", "ActionSet", "ActivityIndicator", "Button", "CheckBox", "ComponentDefinition", "Container", "ControlDelegate", "CustomControl", "CustomListItem", + "DateTimePicker", "Divider", "DropDown", "ExpandableView", "ForeignWindowControl", "GroupDataModel", "Header", "ImageButton", "ImageToggleButton", "ImageView", "ImplicitAnimationController", "InvokeActionItem", + "Label", "ListItemComponent", "ListView", "NavigationPane", "Option", "OrientationSupport", "Page", "Picker", "PickerItemComponent", "ProgressIndicator", "RadioGroup", + "ScrollView", "SegmentedControl", "Sheet", "Slider", "StandardsListItem", "StandardPickerItem", "Tab", "TabbedPane", "TapHandler", "TextArea", "TextField", "ToggleButton", "TitleBar", "WebView" + }; + + private static readonly string[] SpecialWords = new string[] { "bb", "cascades", "codetitans", "qsTr", "system", "ui", "Retranslate", "onLocaleOrLanguageChanged", "onLanguageChanged" }; + + private enum Colors : uint + { + Unused = 0, + Text = 1, + Identifier = 2, + Comment = 3, + Keyword = 4, + Number = 5, + String = 6, + Operator = 7, + Type = 8, + Signals = 9 + } + + private enum States + { + Text = 0, + SingleLineComment = 1, + MultiLineComment = 2, + StringSingleQuoted = 3, + StringDoubleQuoted = 4, + Number = 5 + } + + /// + /// Structure representing a status of the scanner. + /// + private struct ScannerStatus + { + private States _state; + private int _level; + + /// + /// Init constructor. + /// + public ScannerStatus(int state) + { + _state = (States) ((state >> 16) & 0x0F); + _level = state & 0xFF; + } + + /// + /// Init constructor. + /// + public ScannerStatus(States state, int level) + { + _state = state; + _level = level; + } + + /// + /// Gets simple representation of the state. + /// + public int ToInt32() + { + return (((int) _state) << 16) | _level; + } + + public static implicit operator int(ScannerStatus s) + { + return s.ToInt32(); + } + + #region Properties + + public States State + { + get { return _state; } + set { _state = value; } + } + + public int Level + { + get { return _level; } + set { _level = value; } + } + + #endregion + } + + #endregion + + private readonly IVsTextLines _buffer; + + /// + /// Init constructor. + /// + public QmlColorizer(IVsTextLines buffer) + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + _buffer = buffer; + } + + #region Implementation of IVsColorizer + + /// + /// Returns the state maintenance requirement for the colorizer. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [out] true if this colorizer requires per-line state maintenance, otherwise it should be set to false. + int IVsColorizer.GetStateMaintenanceFlag(out int flag) + { + flag = 1; + return VSConstants.S_OK; + } + + /// + /// Determines the state in which colorization of the first line of the buffer should begin. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [out] Pointer to a long integer that represents the start state of the colorizer. + int IVsColorizer.GetStartState(out int startState) + { + startState = new ScannerStatus(States.Text, 0); + return VSConstants.S_OK; + } + + /// + /// Colorizes the given text. + /// + /// + /// Returns the colorizer's state at the end of the line. + /// + /// [in] Line to be colorized. + /// [in] Length of the line minus the end-of-line marker (CR, LF, CRLF pair, or 0 (EOF)). + /// [in] The line's text (examine up to characters). + /// [in] The colorizer's state at the beginning of the line. + /// [out] An array of color attributes to be filled in for the text. The array contains one member for each character in the line colorized, and an additional element which represents the background color of the space to the right of the last character. This array is + 1 characters long. Members of the pAttributes array may contain bits that can be masked with the various values provided in the enumeration to get the information required. For more information, see . + int IVsColorizer.ColorizeLine(int line, int length, IntPtr pszText, int state, uint[] attributes) + { + string text = Marshal.PtrToStringUni(pszText, length); + + return ScanLine(new ScannerStatus(state), text, attributes); + } + + /// + /// Determines the end-of-line state for a given line. + /// + /// + /// Returns the state at the end of the line. + /// + /// [in] Line whose state is to be queried. + /// [in] Length of the line minus the end-of-line marker (CR, LF, CRLF pair, or 0 (EOF)). + /// [in] The line's text (examine only up to characters). + /// [in] The colorizer's state at the beginning of the line. + int IVsColorizer.GetStateAtEndOfLine(int line, int length, IntPtr pszText, int state) + { + string text = Marshal.PtrToStringUni(pszText, length); + + return ScanLine(new ScannerStatus(state), text, null); + } + + /// + /// Releases any references held on a object. + /// + void IVsColorizer.CloseColorizer() + { + } + + #endregion + + #region Implementation of IVsColorizer2 + + /// + /// Starts or resume colorization operations. + /// + int IVsColorizer2.BeginColorization() + { + return VSConstants.S_OK; + } + + /// + /// Suspends or ends colorization operations. + /// + int IVsColorizer2.EndColorization() + { + return VSConstants.S_OK; + } + + #endregion + + #region Scanning + + private static ScannerStatus ScanLine(ScannerStatus status, string text, uint[] colors) + { + var lastWord = new StringBuilder(); + int i = 0; + + while (i < text.Length) + { + switch (status.State) + { + case States.Text: + // go through all the text and search for particular: + while (i < text.Length) + { + if (!char.IsLetterOrDigit(text[i]) && lastWord.Length > 0) + { + MarkKeyword(colors, i, lastWord.ToString()); + lastWord.Remove(0, lastWord.Length); + } + + if (IsSingleLineComment(text, i)) + { + status.State = States.SingleLineComment; + Advance(colors, ref i, 2, Colors.Comment); + break; + } + + if (IsMultiLineCommentStart(text, i)) + { + status.State = States.MultiLineComment; + Advance(colors, ref i, 2, Colors.Comment); + break; + } + + if (IsStringSingleQuoteStartChar(text, i)) + { + status.State = States.StringSingleQuoted; + Advance(colors, ref i, 1, Colors.String); + break; + } + + if (IsStringDoubleQuoteStartChar(text, i)) + { + status.State = States.StringDoubleQuoted; + Advance(colors, ref i, 1, Colors.String); + break; + } + + if (IsNumberStart(text, i)) + { + status.State = States.Number; + break; + } + + if (IsOperator(text, i)) + { + SetColor(colors, i, Colors.Operator); + i++; + continue; + } + + if (char.IsLetterOrDigit(text[i]) && colors != null) + { + lastWord.Append(text[i]); + } + + SetColor(colors, i, Colors.Text); + i++; + } + + break; + case States.SingleLineComment: + // scan single-line comment, by marking till the end of the line: + Advance(colors, ref i, text.Length - i, Colors.Comment); + break; + case States.MultiLineComment: + // scan multi-line comment, by searching the end of the comment: + while (i < text.Length) + { + if (IsMultiLineCommentEnd(text, i)) + { + status.State = States.Text; + Advance(colors, ref i, 2, Colors.Comment); + break; + } + + SetColor(colors, i, Colors.Comment); + i++; + } + break; + case States.StringSingleQuoted: + // look for the end of single-quoted string: + while (i < text.Length) + { + if (IsStringSingleQuoteEndChar(text, i)) + { + status.State = States.Text; + Advance(colors, ref i, 1, Colors.String); + break; + } + + SetColor(colors, i, Colors.String); + i++; + } + break; + case States.StringDoubleQuoted: + // look for the end of double-quoted string: + while (i < text.Length) + { + if (IsStringDoubleQuoteEndChar(text, i)) + { + status.State = States.Text; + Advance(colors, ref i, 1, Colors.String); + break; + } + + SetColor(colors, i, Colors.String); + i++; + } + break; + case States.Number: + // scan text to find end of the number: + while (i < text.Length) + { + if (IsNumber(text, i)) + { + SetColor(colors, i, Colors.Number); + i++; + continue; + } + + status.State = States.Text; + break; + } + break; + default: + throw new InvalidDataException("Invalid state, while colorizing QML file"); + } + } + + switch (status.State) + { + case States.SingleLineComment: + SetColor(colors, text.Length, Colors.Comment); + status.State = States.Text; + break; + + case States.MultiLineComment: + SetColor(colors, text.Length, Colors.Comment); + break; + default: + if (lastWord.Length > 0) + { + MarkKeyword(colors, text.Length, lastWord.ToString()); + } + + SetColor(colors, text.Length, Colors.Text); + break; + } + + return status; + } + + private static void SetColor(uint[] colors, int index, Colors color) + { + if (colors != null) + colors[index] = (uint) color; + } + + private static void Advance(uint[] colors, ref int index, int length, Colors color) + { + if (colors != null) + { + for (int i = 0; i < length; i++, index++) + { + colors[index] = (uint) color; + } + } + else + { + index += length; + } + } + + private static void MarkKeyword(uint[] colors, int index, string word) + { + Colors color; + + if (colors != null && IsKeyword(word, out color)) + { + for (int i = index - word.Length; i < index; i++) + { + colors[i] = (uint) color; + } + } + } + + private static bool IsSingleLineComment(string text, int index) + { + return index + 1 < text.Length && text[index] == '/' && text[index + 1] == '/'; + } + + private static bool IsMultiLineCommentStart(string text, int index) + { + return index + 1 < text.Length && text[index] == '/' && text[index + 1] == '*'; + } + + private static bool IsMultiLineCommentEnd(string text, int index) + { + return index + 1 < text.Length && text[index] == '*' && text[index + 1] == '/'; + } + + private static bool IsStringSingleQuoteStartChar(string text, int index) + { + return index < text.Length && text[index] == '\''; + } + + private static bool IsStringDoubleQuoteStartChar(string text, int index) + { + return index < text.Length && text[index] == '"'; + } + + private static bool IsStringSingleQuoteEndChar(string text, int index) + { + return index > 0 && index < text.Length && text[index - 1] != '\\' && text[index] == '\''; + } + + private static bool IsStringDoubleQuoteEndChar(string text, int index) + { + return index > 0 && index < text.Length && text[index - 1] != '\\' && text[index] == '"'; + } + + private static bool IsNumberStart(string text, int index) + { + return index < text.Length && IsHexDigit(text[index]) && (index == 0 || (index > 0 && !char.IsLetter(text[index - 1]) && text[index - 1] != '_')); + } + + private static bool IsNumber(string text, int index) + { + return index < text.Length && (IsHexDigit(text[index]) || text[index] == '.'); + } + + private static bool IsHexDigit(char c) + { + return char.IsDigit(c); //(c >= '0' && c <= '9') || c == 'x' || c == 'X' || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == 'h' || c == 'H'; + } + + private static bool IsOperator(string text, int index) + { + return index < text.Length && Operators.IndexOf(text[index]) >= 0; + } + + private static bool IsKeyword(string text, out Colors color) + { + if (string.IsNullOrEmpty(text)) + { + color = Colors.Unused; + return false; + } + + if (Array.IndexOf(Keywords, text) >= 0) + { + color = Colors.Keyword; + return true; + } + + if (Array.IndexOf(BasicTypes, text) >= 0) + { + color = Colors.Type; + return true; + } + + if (Array.IndexOf(CascadeBasicTypes, text) >= 0) + { + color = Colors.Signals; + return true; + } + + if (Array.IndexOf(CascadesControlTypes, text) >= 0) + { + color = Colors.Type; + return true; + } + + if (Array.IndexOf(CascadesBasicSignals, text) >= 0) + { + color = Colors.Signals; + return true; + } + + if (Array.IndexOf(SpecialWords, text) >= 0) + { + color = Colors.Identifier; + return true; + } + + color = Colors.Unused; + return false; + } + + #endregion + } +} diff --git a/src_vs2012/Package/Languages/Qml/QmlLanguageService.cs b/src_vs2012/Package/Languages/Qml/QmlLanguageService.cs new file mode 100644 index 00000000..d34fe412 --- /dev/null +++ b/src_vs2012/Package/Languages/Qml/QmlLanguageService.cs @@ -0,0 +1,137 @@ +using System.Drawing; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Package; +using Microsoft.VisualStudio.TextManager.Interop; + +namespace BlackBerry.Package.Languages.Qml +{ + [ComVisible(true)] + [Guid(LanguageGuid)] + internal sealed class QmlLanguageService : IVsLanguageInfo, IVsProvideColorableItems + { + public const string LanguageGuid = "90408888-8ce2-41af-8b01-73ec883e5b7c"; + public const string LanguageName = "QML"; + + private readonly ColorableItem[] _colorableItems; + + public QmlLanguageService() + { + _colorableItems = new[] + { + new ColorableItem("QML - Text", "QML - Text", COLORINDEX.CI_USERTEXT_FG, COLORINDEX.CI_USERTEXT_BK, Color.Empty, Color.Empty, FONTFLAGS.FF_DEFAULT), + new ColorableItem("QML - Identifier", "QML - Identifier", COLORINDEX.CI_USERTEXT_FG, COLORINDEX.CI_USERTEXT_BK, Color.Empty, Color.Empty, FONTFLAGS.FF_BOLD), + new ColorableItem("QML - Comment", "QML - Comment", COLORINDEX.CI_DARKGREEN, COLORINDEX.CI_USERTEXT_BK, Color.Empty, Color.Empty, FONTFLAGS.FF_DEFAULT), + new ColorableItem("QML - Keyword", "QML - Keyword", COLORINDEX.CI_BLUE, COLORINDEX.CI_USERTEXT_BK, Color.Empty, Color.Empty, FONTFLAGS.FF_DEFAULT), + new ColorableItem("QML - Number", "QML - Number", COLORINDEX.CI_USERTEXT_FG, COLORINDEX.CI_USERTEXT_BK, Color.DodgerBlue, Color.Empty, FONTFLAGS.FF_BOLD), + new ColorableItem("QML - String", "QML - String", COLORINDEX.CI_USERTEXT_FG, COLORINDEX.CI_USERTEXT_BK, Color.DarkRed, Color.Empty, FONTFLAGS.FF_DEFAULT), + new ColorableItem("QML - Operator", "QML - Operator", COLORINDEX.CI_DARKGRAY, COLORINDEX.CI_USERTEXT_BK, Color.Empty, Color.Empty, FONTFLAGS.FF_DEFAULT), + new ColorableItem("QML - Types", "QML - Types", COLORINDEX.CI_USERTEXT_FG, COLORINDEX.CI_USERTEXT_BK, Color.LightSeaGreen, Color.Empty, FONTFLAGS.FF_BOLD), + new ColorableItem("QML - Signals", "QML - Signals", COLORINDEX.CI_USERTEXT_FG, COLORINDEX.CI_USERTEXT_BK, Color.SeaGreen, Color.Empty, FONTFLAGS.FF_DEFAULT) + }; + } + + #region Implementation of IVsLanguageInfo + + /// + /// Returns the name of the programming language. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [out] Returns a BSTR that contains the language name. + int IVsLanguageInfo.GetLanguageName(out string name) + { + name = LanguageName; + return VSConstants.S_OK; + } + + /// + /// Returns the file extensions belonging to this language. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [out] Returns a BSTR that contains the requested file extensions. + int IVsLanguageInfo.GetFileExtensions(out string extensions) + { + extensions = ".qml;.jsqml;"; + return VSConstants.S_OK; + } + + /// + /// Returns the colorizer. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [in] The interface for the requested colorizer. + /// [out] Returns an object. + int IVsLanguageInfo.GetColorizer(IVsTextLines buffer, out IVsColorizer colorizer) + { + if (buffer == null) + { + colorizer = null; + return VSConstants.E_INVALIDARG; + } + + colorizer = new QmlColorizer(buffer); + return VSConstants.S_OK; + } + + /// + /// Allows a language to add adornments to a code editor. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [in] The interface for the requested code editor manager. + /// [out] Returns an object. + int IVsLanguageInfo.GetCodeWindowManager(IVsCodeWindow window, out IVsCodeWindowManager windowManager) + { + if (window == null) + { + windowManager = null; + return VSConstants.E_INVALIDARG; + } + + windowManager = new QmlWindowManager(window); + return VSConstants.S_OK; + } + + /// + /// Determines the number of custom colorable items proffered by the language service. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [out] The number of custom colorable items provided by the language service. + int IVsProvideColorableItems.GetItemCount(out int count) + { + count = _colorableItems.Length; + return VSConstants.S_OK; + } + + /// + /// Determines the item information for each custom colorable item proffered by the language service. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [in] Integer containing the index value for the custom colorable item. This value is never zero. + /// [out] Custom colorable item object. For more information, see . + int IVsProvideColorableItems.GetColorableItem(int index, out IVsColorableItem item) + { + if (index < 1 || index > _colorableItems.Length) + { + item = null; + return VSConstants.E_INVALIDARG; + } + + item = _colorableItems[index - 1]; + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2012/Package/Languages/Qml/QmlWindowManager.cs b/src_vs2012/Package/Languages/Qml/QmlWindowManager.cs new file mode 100644 index 00000000..26bb67d5 --- /dev/null +++ b/src_vs2012/Package/Languages/Qml/QmlWindowManager.cs @@ -0,0 +1,60 @@ +using System; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.TextManager.Interop; + +namespace BlackBerry.Package.Languages.Qml +{ + sealed class QmlWindowManager : IVsCodeWindowManager + { + private readonly IVsCodeWindow _window; + + /// + /// Init constructor. + /// + public QmlWindowManager(IVsCodeWindow window) + { + if (window == null) + throw new ArgumentNullException("window"); + + _window = window; + } + + #region Implementation of IVsCodeWindowManager + + /// + /// Adds adornments, such as drop-down bars, to a code window. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + int IVsCodeWindowManager.AddAdornments() + { + return VSConstants.S_OK; + } + + /// + /// Removes adornments, such as drop-down bars, from a code window. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + int IVsCodeWindowManager.RemoveAdornments() + { + return VSConstants.S_OK; + } + + /// + /// Called by the core editor to notify a language that a new view was created. + /// + /// + /// If the method succeeds, it returns . If it fails, it returns an error code. + /// + /// [in] The object for the new view. + int IVsCodeWindowManager.OnNewView(IVsTextView view) + { + return VSConstants.S_OK; + } + + #endregion + } +} diff --git a/src_vs2012/Package/Model/Integration/ComboBoxItem.cs b/src_vs2012/Package/Model/Integration/ComboBoxItem.cs new file mode 100644 index 00000000..7503439f --- /dev/null +++ b/src_vs2012/Package/Model/Integration/ComboBoxItem.cs @@ -0,0 +1,44 @@ +namespace BlackBerry.Package.Model.Integration +{ + /// + /// Item class to feed Windows Forms ComboBox. + /// + public sealed class ComboBoxItem + { + public ComboBoxItem() + { + } + + public ComboBoxItem(string text) + { + Text = text; + } + + public ComboBoxItem(string text, object tag) + { + Text = text; + Tag = tag; + } + + #region Properties + + public string Text + { + get; + set; + } + + public object Tag + { + get; + set; + } + + #endregion + + public override string ToString() + { + return Text ?? string.Empty; + } + } +} diff --git a/src_vs2012/Package/Model/Integration/DynamicMenuCommand.cs b/src_vs2012/Package/Model/Integration/DynamicMenuCommand.cs new file mode 100644 index 00000000..b47a3fd2 --- /dev/null +++ b/src_vs2012/Package/Model/Integration/DynamicMenuCommand.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections; +using System.ComponentModel.Design; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Model.Integration +{ + /// + /// Encapsulates displaying a collection of items as multiple menu items within Visual Studio. + /// + internal sealed class DynamicMenuCommand : OleMenuCommand + { + private readonly Predicate _displayPredicate; + private readonly Action _invokeHandler; + private readonly Action _processedQueryStatus; + private readonly Func _getCollection; + private readonly ICollection _collection; + + public DynamicMenuCommand(Predicate displayPredicate, EventHandler invokeHandler, EventHandler beforeQueryStatusHandler, CommandID id) + : base(invokeHandler, null, beforeQueryStatusHandler, id) + { + if (displayPredicate == null) + throw new ArgumentNullException("displayPredicate"); + + _displayPredicate = displayPredicate; + } + + public DynamicMenuCommand(ICollection collection, EventHandler invokeHandler, Action beforeQueryStatus, CommandID id) + : base(invokeHandler, null, InternalBeforeCollectionQueryStatusUpdate, id) + { + if (collection == null) + throw new ArgumentNullException("collection"); + if (beforeQueryStatus == null) + throw new ArgumentNullException("beforeQueryStatus"); + + _displayPredicate = InternalCollectionPredicate; + _processedQueryStatus = beforeQueryStatus; + _collection = collection; + } + + public DynamicMenuCommand(Func collectionHandler, Action invokeHandler, Action beforeQueryStatus, CommandID id) + : base(InternalInvokeHandler, null, InternalBeforeCollectionQueryStatusUpdate, id) + { + if (collectionHandler == null) + throw new ArgumentNullException("collectionHandler"); + if (beforeQueryStatus == null) + throw new ArgumentNullException("beforeQueryStatus"); + + _displayPredicate = InternalCollectionPredicate; + _invokeHandler = invokeHandler; + _processedQueryStatus = beforeQueryStatus; + _getCollection = collectionHandler; + } + + private ICollection Collection + { + get + { + ICollection result = null; + + if (_getCollection != null) + result = _getCollection(); + + if (result == null) + result = _collection; + + return result; + } + } + + public override bool DynamicItemMatch(int cmdId) + { + if (_displayPredicate(cmdId)) + { + MatchedCommandId = cmdId; + return true; + } + + MatchedCommandId = 0; + return false; + } + + private bool InternalCollectionPredicate(int cmdId) + { + var collection = Collection; + + if (collection == null || collection.Count == 0) + return false; + + return cmdId >= CommandID.ID && (cmdId - CommandID.ID) < collection.Count; + } + + private static void InternalBeforeCollectionQueryStatusUpdate(object sender, EventArgs e) + { + var command = (DynamicMenuCommand)sender; + + int index = command.MatchedCommandId == 0 ? 0 : command.MatchedCommandId - command.CommandID.ID; + command.MatchedCommandId = 0; + + // and ask for further status update: + command._processedQueryStatus(command, command.Collection, index); + } + + private static void InternalInvokeHandler(object sender, EventArgs e) + { + var command = (DynamicMenuCommand) sender; + + int index = command.MatchedCommandId == 0 ? 0 : command.MatchedCommandId - command.CommandID.ID; + command.MatchedCommandId = 0; + + // and notify about selection made: + if (command._invokeHandler != null) + { + command._invokeHandler(command, command.Collection, index); + } + } + } +} diff --git a/src_vs2012/Package/Model/Integration/WebBrowserTurbo.cs b/src_vs2012/Package/Model/Integration/WebBrowserTurbo.cs new file mode 100644 index 00000000..49eda7dd --- /dev/null +++ b/src_vs2012/Package/Model/Integration/WebBrowserTurbo.cs @@ -0,0 +1,221 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace BlackBerry.Package.Model.Integration +{ + /// + /// Extended version of WebBrowser to return more data, when navigating over URLs and notify about errors. + /// Based on sample implementation from: + /// http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.createsink%28VS.80%29.aspx + /// + public sealed class WebBrowserTurbo : WebBrowser + { + public event WebBrowserNavigateErrorEventHandler NavigateError; + public event WebBrowserBeforeNavigatingEventHandler BeforeNavigating; + + private AxHost.ConnectionPointCookie _cookie; + private EventSink _sink; + + #region COM Interfaces + + // Imports the NavigateError method from the OLE DWebBrowserEvents2 + // interface. + [ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch), TypeLibType(TypeLibTypeFlags.FHidden)] + public interface DWebBrowserEvents2 + { + [DispId(250)] + void BeforeNavigate2( + [MarshalAs(UnmanagedType.IDispatch)] object pDisp, + [In] ref object url, + [In] ref object flags, + [In] ref object targetFrameName, + [In] ref object postData, + [In] ref object headers, + [In, Out, MarshalAs(UnmanagedType.VariantBool)] ref bool cancel); + + [DispId(271)] + void NavigateError( + [In, MarshalAs(UnmanagedType.IDispatch)] object pDisp, + [In] ref object url, + [In] ref object targetFrame, + [In] ref object statusCode, + [In, Out] ref bool cancel); + } + + /// + /// Helper class that will forward COM events received from the COM-object-browser to the control. + /// + private sealed class EventSink : StandardOleMarshalObject, DWebBrowserEvents2 + { + private WebBrowserTurbo _browser; + + public EventSink(WebBrowserTurbo browser) + { + if (browser == null) + throw new ArgumentNullException("browser"); + + _browser = browser; + } + + public void BeforeNavigate2(object pDisp, ref object url, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel) + { + var e = new WebBrowserBeforeNavigatingEventArgs((string) url, (string) targetFrameName, (byte[]) postData, (string) headers, cancel); + + // notify: + _browser.OnBeforeNavigating(e); + + // update out params: + cancel = e.Cancel; + } + + public void NavigateError(object pDisp, ref object url, ref object targetFrame, ref object statusCode, ref bool cancel) + { + var e = new WebBrowserNavigateErrorEventArgs((string) url, (string) targetFrame, (int) statusCode, cancel); + + // notify + _browser.OnNavigateError(e); + + // update out params: + cancel = e.Cancel; + } + } + + #endregion + + #region Notifications + + private void OnNavigateError(WebBrowserNavigateErrorEventArgs e) + { + if (NavigateError != null) + { + NavigateError(this, e); + } + } + + private void OnBeforeNavigating(WebBrowserBeforeNavigatingEventArgs e) + { + if (BeforeNavigating != null) + { + BeforeNavigating(this, e); + } + } + + #endregion + + protected override void CreateSink() + { + base.CreateSink(); + + // initialize object, that will forward events from associated ActiveX control: + _sink = new EventSink(this); + _cookie = new AxHost.ConnectionPointCookie(ActiveXInstance, _sink, typeof(DWebBrowserEvents2)); + } + + protected override void DetachSink() + { + // remove even forwarder: + if (_cookie != null) + { + _cookie.Disconnect(); + _cookie = null; + } + base.DetachSink(); + } + } + + public delegate void WebBrowserNavigateErrorEventHandler(object sender, WebBrowserNavigateErrorEventArgs e); + + public delegate void WebBrowserBeforeNavigatingEventHandler(object sender, WebBrowserBeforeNavigatingEventArgs e); + + /// + /// Arguments passed along with browser navigation error events. + /// + public sealed class WebBrowserNavigateErrorEventArgs : EventArgs + { + public WebBrowserNavigateErrorEventArgs(string url, string targetFrame, int statusCode, bool cancel) + { + Url = url; + TargetFrame = targetFrame; + StatusCode = statusCode; + Cancel = cancel; + } + + #region Properties + + public string Url + { + get; + private set; + } + + public string TargetFrame + { + get; + private set; + } + + public int StatusCode + { + get; + private set; + } + + public bool Cancel + { + get; + set; + } + + #endregion + } + + /// + /// Arguments passed along with browser navigation events. + /// + public sealed class WebBrowserBeforeNavigatingEventArgs : EventArgs + { + public WebBrowserBeforeNavigatingEventArgs(string url, string targetFrame, byte[] postData, string headers, bool cancel) + { + Url = url; + TargetFrame = targetFrame; + PostData = postData; + Headers = headers; + Cancel = cancel; + } + + #region Properties + + public string Url + { + get; + private set; + } + + public string TargetFrame + { + get; + private set; + } + + public byte[] PostData + { + get; + private set; + } + + public string Headers + { + get; + private set; + } + + public bool Cancel + { + get; + set; + } + + #endregion + } +} diff --git a/src_vs2012/Package/Model/Wizards/ContextParams.cs b/src_vs2012/Package/Model/Wizards/ContextParams.cs new file mode 100644 index 00000000..ad8a06cf --- /dev/null +++ b/src_vs2012/Package/Model/Wizards/ContextParams.cs @@ -0,0 +1,70 @@ +using System; + +namespace BlackBerry.Package.Model.Wizards +{ + /// + /// Base class of context parameters passed from Visual Studio to the wizard engine. + /// + class ContextParams + { + /// + /// Hidden constructor. + /// + protected ContextParams(Guid type, string projectName) + { + if (string.IsNullOrEmpty(projectName)) + throw new ArgumentNullException("projectName"); + + Type = type; + ProjectName = projectName; + } + + /// + /// Hidden constructor. + /// + protected ContextParams(string typeGuid, object projectName) + { + if (string.IsNullOrEmpty(typeGuid)) + throw new ArgumentNullException("typeGuid"); + if (projectName == null) + throw new ArgumentNullException("projectName"); + + Type = new Guid(typeGuid); + ProjectName = projectName.ToString(); + } + + #region Properties + + /// + /// Predefined type of the wizard (new-project, new-project-item, new-sub-project). + /// + public Guid Type + { + get; + private set; + } + + public string ProjectName + { + get; + private set; + } + + #endregion + + protected static bool GetBoolValue(object value) + { + if (value == null) + return false; + + var textValue = value.ToString(); + + if (string.Compare(textValue, "true", StringComparison.OrdinalIgnoreCase) == 0) + return true; + if (string.Compare(textValue, "1", StringComparison.CurrentCulture) == 0) + return true; + + return false; + } + } +} diff --git a/src_vs2012/Package/Model/Wizards/NewProjectItemParams.cs b/src_vs2012/Package/Model/Wizards/NewProjectItemParams.cs new file mode 100644 index 00000000..76d60ee1 --- /dev/null +++ b/src_vs2012/Package/Model/Wizards/NewProjectItemParams.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using EnvDTE; + +namespace BlackBerry.Package.Model.Wizards +{ + /// + /// Context parameters passed by Visual Studio, when creating new project item. + /// + sealed class NewProjectItemParams : ContextParams + { + internal const string TypeGuid = "{0f90e1d1-4999-11d1-b6d1-00a0c90f2744}"; + + /// + /// Init constructor. + /// + public NewProjectItemParams(object[] contextParams) + : base(TypeGuid, contextParams != null && contextParams.Length > 1 ? contextParams[1] : null) + { + if (contextParams == null) + throw new ArgumentNullException("contextParams"); + if (contextParams.Length < 6) + throw new ArgumentOutOfRangeException("contextParams"); + + ProjectItems = (ProjectItems) contextParams[2]; + LocalDirectory = contextParams[3] != null ? contextParams[3].ToString() : null; + ItemName = contextParams[4] != null ? contextParams[4].ToString() : null; + InstallationDirectory = contextParams[5] != null ? contextParams[5].ToString() : null; + Silent = contextParams.Length < 7 || GetBoolValue(contextParams[6]); // optional in VS2010, set to 'true' then + + // if item is created via 'File->New->File...' it will have no folder at name start, so let's try to add it to keep the convention: + if (!string.IsNullOrEmpty(LocalDirectory) && !string.IsNullOrEmpty(ItemName) && !Path.IsPathRooted(ItemName)) + { + ItemName = Path.Combine(LocalDirectory, ItemName); + } + } + + #region Properties + + public ProjectItems ProjectItems + { + get; + private set; + } + + public string LocalDirectory + { + get; + private set; + } + + public string ItemName + { + get; + private set; + } + + public string InstallationDirectory + { + get; + private set; + } + + public bool Silent + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/Package/Model/Wizards/NewProjectParams.cs b/src_vs2012/Package/Model/Wizards/NewProjectParams.cs new file mode 100644 index 00000000..317a28ad --- /dev/null +++ b/src_vs2012/Package/Model/Wizards/NewProjectParams.cs @@ -0,0 +1,64 @@ +using System; + +namespace BlackBerry.Package.Model.Wizards +{ + /// + /// Context parameters passed by Visual Studio, when creating new project. + /// + sealed class NewProjectParams : ContextParams + { + internal const string TypeGuid = "{0f90e1d0-4999-11d1-b6d1-00a0c90f2744}"; + + /// + /// Init constructor. + /// + public NewProjectParams(object[] contextParams) + : base(TypeGuid, contextParams != null && contextParams.Length > 1 ? contextParams[1] : null) + { + if (contextParams == null) + throw new ArgumentNullException("contextParams"); + if (contextParams.Length < 7) + throw new ArgumentOutOfRangeException("contextParams"); + + LocalDirectory = contextParams[2] != null ? contextParams[2].ToString() : null; + InstallationDirectory = contextParams[3] != null ? contextParams[3].ToString() : null; + IsExclusive = GetBoolValue(contextParams[4]); + SolutionName = contextParams[5] != null ? contextParams[5].ToString() : null; + IsSilent = GetBoolValue(contextParams[6]); + } + + #region Properties + + public string LocalDirectory + { + get; + private set; + } + + public string InstallationDirectory + { + get; + private set; + } + + public bool IsExclusive + { + get; + private set; + } + + public string SolutionName + { + get; + private set; + } + + public bool IsSilent + { + get; + private set; + } + + #endregion + } +} diff --git a/src_vs2012/Package/Model/bar-descriptor.Extensions.cs b/src_vs2012/Package/Model/bar-descriptor.Extensions.cs new file mode 100644 index 00000000..dd628627 --- /dev/null +++ b/src_vs2012/Package/Model/bar-descriptor.Extensions.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace BlackBerry.BarDescriptor.Model +{ + /// + /// Following are some extensions for all the classes defining bar-descriptor structure. + /// The base bar-descriptor.cs file was automatically generated from XSD using command: + /// + /// xsd /n:BlackBerry.BarDescriptor.Model /classes /language:CS /edb bar-descriptor.xsl + /// + /// Having the 'working' part here guarantees it's not lost each new bar-descriptor classes re-creation. + /// + partial class QnxRootType + { + public void AddPermission(PermissionType newPermission) + { + if (permission == null) + { + permission = new PermissionType[0]; + } + + var newPermissionsList = permission; + Array.Resize(ref newPermissionsList, newPermissionsList.Length + 1); + newPermissionsList[newPermissionsList.Length - 1] = newPermission; + permission = newPermissionsList; + } + + + public void DeletePermission(PermissionType oldPermission) + { + foreach (var perm in permission) + { + if (perm.Value == oldPermission.Value) + { + var permissionList = new List(permission); + permissionList.Remove(perm); + permission = permissionList.ToArray(); + } + } + } + + public void AddLocalAsset(AssetType newAsset) + { + if (asset == null) + { + asset = new AssetType[0]; + } + + var localAsset = asset; + Array.Resize(ref localAsset, localAsset.Length + 1); + localAsset[localAsset.Length - 1] = newAsset; + asset = localAsset; + } + + public void DeleteLocalAsset(AssetType removeAsset) + { + var assetList = new List(asset); + assetList.Remove(removeAsset); + asset = assetList.ToArray(); + } + } + + partial class ConfigurationType + { + public void AddAsset(AssetType newAsset) + { + if (asset == null) + { + asset = new AssetType[0]; + } + + var localAsset = asset; + Array.Resize(ref localAsset, localAsset.Length + 1); + localAsset[localAsset.Length - 1] = newAsset; + asset = localAsset; + } + + public void DeleteAsset(AssetType removeAsset) + { + var assetList = new List(asset); + assetList.Remove(removeAsset); + asset = assetList.ToArray(); + } + } + + partial class LocalizedStringType + { + [XmlIgnore] + public string Value + { + get { return Text != null && Text.Length > 0 ? Text[0] : null; } + set { Text = value != null ? new[] { value } : null; } + } + } + + partial class AssetType + { + private static readonly string[] AssetTypeList = {"Other", "Library", "Executable", "Entry-point"}; + private string _assetType = "Other"; + + + [XmlIgnore] + public string Value + { + get { return Text != null && Text.Length > 0 ? Text[0] : null; } + set { Text = value != null ? new[] { value } : null; } + } + + [XmlIgnore] + public string publicAsset + { + get { return @public; } + set + { + if (value != @public) + { + @public = value; + this.RaisePropertyChanged("publicAsset"); + } + } + } + + [XmlIgnore] + public string assettype + { + get + { + _assetType = GetAssetType(); + return _assetType; + } + set + { + if (value != _assetType) + { + _assetType = value; + this.RaisePropertyChanged("assettype"); + } + } + } + + [XmlIgnore] + public string[] assettypelist + { + get { return AssetTypeList; } + } + + private string GetAssetType() + { + if (Value.StartsWith("lib/")) + { + return "Library"; + } + if (typeField == "Qnx/Elf") + { + if (entry == "true") + { + return "Entry-point"; + } + return "Executable"; + } + + return "Other"; + } + } + + partial class ImageType + { + [XmlIgnore] + public string defaultImage + { + get { return image != null && image.Length > 0 ? image[0] : null; } + set + { + if (image != null && image.Length > 0) + { + image[0] = value; + } + } + } + + public void AddImage(string icon) + { + if (image == null) + { + image = new string[0]; + } + + var iconImages = image; + Array.Resize(ref iconImages, iconImages.Length + 1); + iconImages[iconImages.Length - 1] = icon; + image = iconImages; + } + + public void DeleteImage(string icon) + { + var iconList = new List(image); + iconList.Remove(icon); + image = iconList.ToArray(); + } + } +} diff --git a/src_vs2012/Package/Model/bar-descriptor.cs b/src_vs2012/Package/Model/bar-descriptor.cs new file mode 100644 index 00000000..5d152dcd --- /dev/null +++ b/src_vs2012/Package/Model/bar-descriptor.cs @@ -0,0 +1,1050 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// +// This source code was auto-generated by xsd, Version=4.0.30319.1. +// +namespace BlackBerry.BarDescriptor.Model { + using System.Xml.Serialization; + + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + [System.Xml.Serialization.XmlRootAttribute("qnx", Namespace="http://www.qnx.com/schemas/application/1.0", IsNullable=false)] + public partial class QnxRootType : object, System.ComponentModel.INotifyPropertyChanged { + + private string idField; + + private LocalizedStringType nameField; + + private string versionNumberField; + + private string platformVersionField; + + private string buildIdField; + + private LocalizedStringType descriptionField; + + private LocalizedStringType copyrightField; + + private string authorField; + + private string authorIdField; + + private string categoryField; + + private WindowType initialWindowField; + + private AssetType[] assetField; + + private ConfigurationType[] configurationField; + + private EntryPointType[] entryPointField; + + private ImageType iconField; + + private ImageType splashScreensField; + + private string splashscreenField; + + private PermissionType[] actionField; + + private PermissionType[] permissionField; + + private EnvironmentVarType[] envField; + + private InvokeTargetType[] invoketargetField; + + /// + public string id { + get { + return this.idField; + } + set { + this.idField = value; + this.RaisePropertyChanged("id"); + } + } + + /// + public LocalizedStringType name { + get { + return this.nameField; + } + set { + this.nameField = value; + this.RaisePropertyChanged("name"); + } + } + + /// + public string versionNumber { + get { + return this.versionNumberField; + } + set { + this.versionNumberField = value; + this.RaisePropertyChanged("versionNumber"); + } + } + + /// + public string platformVersion { + get { + return this.platformVersionField; + } + set { + this.platformVersionField = value; + this.RaisePropertyChanged("platformVersion"); + } + } + + /// + public string buildId { + get { + return this.buildIdField; + } + set { + this.buildIdField = value; + this.RaisePropertyChanged("buildId"); + } + } + + /// + public LocalizedStringType description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + this.RaisePropertyChanged("description"); + } + } + + /// + public LocalizedStringType copyright { + get { + return this.copyrightField; + } + set { + this.copyrightField = value; + this.RaisePropertyChanged("copyright"); + } + } + + /// + public string author { + get { + return this.authorField; + } + set { + this.authorField = value; + this.RaisePropertyChanged("author"); + } + } + + /// + public string authorId { + get { + return this.authorIdField; + } + set { + this.authorIdField = value; + this.RaisePropertyChanged("authorId"); + } + } + + /// + public string category { + get { + return this.categoryField; + } + set { + this.categoryField = value; + this.RaisePropertyChanged("category"); + } + } + + /// + public WindowType initialWindow { + get { + return this.initialWindowField; + } + set { + this.initialWindowField = value; + this.RaisePropertyChanged("initialWindow"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("asset")] + public AssetType[] asset { + get { + return this.assetField; + } + set { + this.assetField = value; + this.RaisePropertyChanged("asset"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("configuration")] + public ConfigurationType[] configuration { + get { + return this.configurationField; + } + set { + this.configurationField = value; + this.RaisePropertyChanged("configuration"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("entryPoint")] + public EntryPointType[] entryPoint { + get { + return this.entryPointField; + } + set { + this.entryPointField = value; + this.RaisePropertyChanged("entryPoint"); + } + } + + /// + public ImageType icon { + get { + return this.iconField; + } + set { + this.iconField = value; + this.RaisePropertyChanged("icon"); + } + } + + /// + public ImageType splashScreens { + get { + return this.splashScreensField; + } + set { + this.splashScreensField = value; + this.RaisePropertyChanged("splashScreens"); + } + } + + /// + public string splashscreen { + get { + return this.splashscreenField; + } + set { + this.splashscreenField = value; + this.RaisePropertyChanged("splashscreen"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("action", IsNullable=true)] + public PermissionType[] action { + get { + return this.actionField; + } + set { + this.actionField = value; + this.RaisePropertyChanged("action"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("permission")] + public PermissionType[] permission { + get { + return this.permissionField; + } + set { + this.permissionField = value; + this.RaisePropertyChanged("permission"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("env")] + public EnvironmentVarType[] env { + get { + return this.envField; + } + set { + this.envField = value; + this.RaisePropertyChanged("env"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("invoke-target")] + public InvokeTargetType[] invoketarget { + get { + return this.invoketargetField; + } + set { + this.invoketargetField = value; + this.RaisePropertyChanged("invoketarget"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class LocalizedStringType : object, System.ComponentModel.INotifyPropertyChanged { + + private string[] textField; + + private string[] textField1; + + /// + [System.Xml.Serialization.XmlElementAttribute("text")] + public string[] text { + get { + return this.textField; + } + set { + this.textField = value; + this.RaisePropertyChanged("text"); + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string[] Text { + get { + return this.textField1; + } + set { + this.textField1 = value; + this.RaisePropertyChanged("Text"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class InvokeTargetFilterType : object, System.ComponentModel.INotifyPropertyChanged { + + private string actionField; + + private string mimetypeField; + + private EnvironmentVarType propertyField; + + /// + public string action { + get { + return this.actionField; + } + set { + this.actionField = value; + this.RaisePropertyChanged("action"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("mime-type")] + public string mimetype { + get { + return this.mimetypeField; + } + set { + this.mimetypeField = value; + this.RaisePropertyChanged("mimetype"); + } + } + + /// + public EnvironmentVarType property { + get { + return this.propertyField; + } + set { + this.propertyField = value; + this.RaisePropertyChanged("property"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class EnvironmentVarType : object, System.ComponentModel.INotifyPropertyChanged { + + private string varField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string var { + get { + return this.varField; + } + set { + this.varField = value; + this.RaisePropertyChanged("var"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value { + get { + return this.valueField; + } + set { + this.valueField = value; + this.RaisePropertyChanged("value"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class InvokeTargetType : object, System.ComponentModel.INotifyPropertyChanged { + + private string invoketargettypeField; + + private string invoketargetnameField; + + private string entrypointidField; + + private ImageType iconField; + + private InvokeTargetFilterType filterField; + + private string idField; + + /// + [System.Xml.Serialization.XmlElementAttribute("invoke-target-type")] + public string invoketargettype { + get { + return this.invoketargettypeField; + } + set { + this.invoketargettypeField = value; + this.RaisePropertyChanged("invoketargettype"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("invoke-target-name")] + public string invoketargetname { + get { + return this.invoketargetnameField; + } + set { + this.invoketargetnameField = value; + this.RaisePropertyChanged("invoketargetname"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("entry-point-id")] + public string entrypointid { + get { + return this.entrypointidField; + } + set { + this.entrypointidField = value; + this.RaisePropertyChanged("entrypointid"); + } + } + + /// + public ImageType icon { + get { + return this.iconField; + } + set { + this.iconField = value; + this.RaisePropertyChanged("icon"); + } + } + + /// + public InvokeTargetFilterType filter { + get { + return this.filterField; + } + set { + this.filterField = value; + this.RaisePropertyChanged("filter"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string id { + get { + return this.idField; + } + set { + this.idField = value; + this.RaisePropertyChanged("id"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class ImageType : object, System.ComponentModel.INotifyPropertyChanged { + + private string[] imageField; + + /// + [System.Xml.Serialization.XmlElementAttribute("image")] + public string[] image { + get { + return this.imageField; + } + set { + this.imageField = value; + this.RaisePropertyChanged("image"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class PermissionType : object, System.ComponentModel.INotifyPropertyChanged { + + private string systemField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string system { + get { + return this.systemField; + } + set { + this.systemField = value; + this.RaisePropertyChanged("system"); + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + this.RaisePropertyChanged("Value"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class EntryPointType : object, System.ComponentModel.INotifyPropertyChanged { + + private string nameField; + + private string entryPointTypeField; + + private PermissionType[] permissionField; + + private string idField; + + /// + public string name { + get { + return this.nameField; + } + set { + this.nameField = value; + this.RaisePropertyChanged("name"); + } + } + + /// + public string entryPointType { + get { + return this.entryPointTypeField; + } + set { + this.entryPointTypeField = value; + this.RaisePropertyChanged("entryPointType"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("permission")] + public PermissionType[] permission { + get { + return this.permissionField; + } + set { + this.permissionField = value; + this.RaisePropertyChanged("permission"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string id { + get { + return this.idField; + } + set { + this.idField = value; + this.RaisePropertyChanged("id"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class ConfigurationType : object, System.ComponentModel.INotifyPropertyChanged { + + private string[] platformArchitectureField; + + private string[] entryPointTypeField; + + private AssetType[] assetField; + + private string idField; + + private string nameField; + + /// + [System.Xml.Serialization.XmlElementAttribute("platformArchitecture")] + public string[] platformArchitecture { + get { + return this.platformArchitectureField; + } + set { + this.platformArchitectureField = value; + this.RaisePropertyChanged("platformArchitecture"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("entryPointType")] + public string[] entryPointType { + get { + return this.entryPointTypeField; + } + set { + this.entryPointTypeField = value; + this.RaisePropertyChanged("entryPointType"); + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("asset")] + public AssetType[] asset { + get { + return this.assetField; + } + set { + this.assetField = value; + this.RaisePropertyChanged("asset"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string id { + get { + return this.idField; + } + set { + this.idField = value; + this.RaisePropertyChanged("id"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name { + get { + return this.nameField; + } + set { + this.nameField = value; + this.RaisePropertyChanged("name"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class AssetType : object, System.ComponentModel.INotifyPropertyChanged { + + private AssetTypeInclude[] includeField; + + private string[] textField; + + private string publicField; + + private string pathField; + + private string entryField; + + private string typeField; + + private string entryPointIdField; + + private string destField; + + /// + [System.Xml.Serialization.XmlElementAttribute("include")] + public AssetTypeInclude[] include { + get { + return this.includeField; + } + set { + this.includeField = value; + this.RaisePropertyChanged("include"); + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string[] Text { + get { + return this.textField; + } + set { + this.textField = value; + this.RaisePropertyChanged("Text"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string @public { + get { + return this.publicField; + } + set { + this.publicField = value; + this.RaisePropertyChanged("public"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string path { + get { + return this.pathField; + } + set { + this.pathField = value; + this.RaisePropertyChanged("path"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string entry { + get { + return this.entryField; + } + set { + this.entryField = value; + this.RaisePropertyChanged("entry"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string type { + get { + return this.typeField; + } + set { + this.typeField = value; + this.RaisePropertyChanged("type"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string entryPointId { + get { + return this.entryPointIdField; + } + set { + this.entryPointIdField = value; + this.RaisePropertyChanged("entryPointId"); + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string dest { + get { + return this.destField; + } + set { + this.destField = value; + this.RaisePropertyChanged("dest"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class AssetTypeInclude : object, System.ComponentModel.INotifyPropertyChanged { + + private string nameField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified)] + public string name { + get { + return this.nameField; + } + set { + this.nameField = value; + this.RaisePropertyChanged("name"); + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + this.RaisePropertyChanged("Value"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.qnx.com/schemas/application/1.0")] + public partial class WindowType : object, System.ComponentModel.INotifyPropertyChanged { + + private string aspectRatioField; + + private string autoOrientsField; + + private string systemChromeField; + + private string transparentField; + + /// + public string aspectRatio { + get { + return this.aspectRatioField; + } + set { + this.aspectRatioField = value; + this.RaisePropertyChanged("aspectRatio"); + } + } + + /// + public string autoOrients { + get { + return this.autoOrientsField; + } + set { + this.autoOrientsField = value; + this.RaisePropertyChanged("autoOrients"); + } + } + + /// + public string systemChrome { + get { + return this.systemChromeField; + } + set { + this.systemChromeField = value; + this.RaisePropertyChanged("systemChrome"); + } + } + + /// + public string transparent { + get { + return this.transparentField; + } + set { + this.transparentField = value; + this.RaisePropertyChanged("transparent"); + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + protected void RaisePropertyChanged(string propertyName) { + System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; + if ((propertyChanged != null)) { + propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + } +} diff --git a/src_vs2012/Package/Model/bar-descriptor.xsd b/src_vs2012/Package/Model/bar-descriptor.xsd new file mode 100644 index 00000000..08046cd3 --- /dev/null +++ b/src_vs2012/Package/Model/bar-descriptor.xsd @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2012/Package/Options/ApiLevelOptionControl.Designer.cs b/src_vs2012/Package/Options/ApiLevelOptionControl.Designer.cs new file mode 100644 index 00000000..9c253db9 --- /dev/null +++ b/src_vs2012/Package/Options/ApiLevelOptionControl.Designer.cs @@ -0,0 +1,153 @@ +namespace BlackBerry.Package.Options +{ + internal partial class ApiLevelOptionControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + if (disposing) + { + if (_vm != null) + { + _vm.Dispose(); + } + } + + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.txtDescription = new System.Windows.Forms.TextBox(); + this.cmbNDKs = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.bttInstallNew = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.bttStatus = new System.Windows.Forms.Button(); + this.lblMore = new System.Windows.Forms.LinkLabel(); + this.SuspendLayout(); + // + // txtDescription + // + this.txtDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtDescription.Location = new System.Drawing.Point(6, 85); + this.txtDescription.Multiline = true; + this.txtDescription.Name = "txtDescription"; + this.txtDescription.ReadOnly = true; + this.txtDescription.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtDescription.Size = new System.Drawing.Size(528, 193); + this.txtDescription.TabIndex = 3; + // + // cmbNDKs + // + this.cmbNDKs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cmbNDKs.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbNDKs.FormattingEnabled = true; + this.cmbNDKs.Location = new System.Drawing.Point(6, 58); + this.cmbNDKs.MaxDropDownItems = 25; + this.cmbNDKs.Name = "cmbNDKs"; + this.cmbNDKs.Size = new System.Drawing.Size(528, 21); + this.cmbNDKs.TabIndex = 2; + this.cmbNDKs.SelectedIndexChanged += new System.EventHandler(this.cmbNDKs_SelectedIndexChanged); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 36); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(93, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Current API Level:"; + // + // bttInstallNew + // + this.bttInstallNew.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttInstallNew.Location = new System.Drawing.Point(459, 284); + this.bttInstallNew.Name = "bttInstallNew"; + this.bttInstallNew.Size = new System.Drawing.Size(75, 23); + this.bttInstallNew.TabIndex = 5; + this.bttInstallNew.Text = "&Install..."; + this.bttInstallNew.UseVisualStyleBackColor = true; + this.bttInstallNew.Click += new System.EventHandler(this.bttInstallNew_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 11); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(248, 13); + this.label2.TabIndex = 0; + this.label2.Text = "Select the API Level that your application supports."; + // + // bttStatus + // + this.bttStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttStatus.Location = new System.Drawing.Point(6, 284); + this.bttStatus.Name = "bttStatus"; + this.bttStatus.Size = new System.Drawing.Size(75, 23); + this.bttStatus.TabIndex = 4; + this.bttStatus.Text = "&Status..."; + this.bttStatus.UseVisualStyleBackColor = true; + this.bttStatus.Click += new System.EventHandler(this.bttStatus_Click); + // + // lblMore + // + this.lblMore.AutoSize = true; + this.lblMore.Location = new System.Drawing.Point(257, 11); + this.lblMore.Name = "lblMore"; + this.lblMore.Size = new System.Drawing.Size(60, 13); + this.lblMore.TabIndex = 6; + this.lblMore.TabStop = true; + this.lblMore.Text = "More info..."; + this.lblMore.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lblMore_LinkClicked); + // + // ApiLevelOptionControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.lblMore); + this.Controls.Add(this.bttStatus); + this.Controls.Add(this.label2); + this.Controls.Add(this.txtDescription); + this.Controls.Add(this.cmbNDKs); + this.Controls.Add(this.label1); + this.Controls.Add(this.bttInstallNew); + this.Name = "ApiLevelOptionControl"; + this.Size = new System.Drawing.Size(537, 310); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox txtDescription; + private System.Windows.Forms.ComboBox cmbNDKs; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button bttInstallNew; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button bttStatus; + private System.Windows.Forms.LinkLabel lblMore; + } +} diff --git a/src_vs2012/Package/Options/ApiLevelOptionControl.cs b/src_vs2012/Package/Options/ApiLevelOptionControl.cs new file mode 100644 index 00000000..88516d61 --- /dev/null +++ b/src_vs2012/Package/Options/ApiLevelOptionControl.cs @@ -0,0 +1,96 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore.Components; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Dialogs; +using BlackBerry.Package.ViewModels; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Options +{ + internal partial class ApiLevelOptionControl : UserControl + { + private readonly ApiLevelOptionViewModel _vm = new ApiLevelOptionViewModel(); + + public ApiLevelOptionControl() + { + InitializeComponent(); + + _vm.Dispatcher = EventDispatcher.From(this); + _vm.UpdateManager.Completed += OnApiLevelChanged; + PopulateNDKs(true); + } + + private void OnApiLevelChanged(object sender, UpdateManagerCompletedEventArgs e) + { + PopulateNDKs(false); + } + + private void PopulateNDKs(bool ignoreCurrentSelection) + { + var currentlySelected = ignoreCurrentSelection ? _vm.ActiveNDK : SelectedNDK; + + txtDescription.Text = string.Empty; + cmbNDKs.Items.Clear(); + + foreach (var ndk in _vm.InstalledNDKs) + { + cmbNDKs.Items.Add(ndk); + } + + _vm.ActiveNDK = currentlySelected; // here the currentlySelected will cause a match-by-folders-search + cmbNDKs.SelectedItem = _vm.ActiveNDK; // and _vm.ActiveNDK != currentlySelected instances + } + + private void cmbNDKs_SelectedIndexChanged(object sender, EventArgs e) + { + var selectedItem = cmbNDKs.SelectedItem as NdkInfo; + + txtDescription.Text = selectedItem != null ? selectedItem.ToLongDescription() : string.Empty; + } + + #region Properties + + public bool HasSelectedNDK + { + get { return cmbNDKs.SelectedItem != null; } + } + + public NdkInfo SelectedNDK + { + get { return cmbNDKs.SelectedItem as NdkInfo; } + set { cmbNDKs.SelectedItem = value; } + } + + #endregion + + internal void OnApply() + { + _vm.ActiveNDK = SelectedNDK; + } + + public void OnClosed() + { + PopulateNDKs(true); + } + + private void bttInstallNew_Click(object sender, EventArgs e) + { + var form = new InstallForm(_vm); + form.ShowDialog(); + PopulateNDKs(false); + } + + private void bttStatus_Click(object sender, EventArgs e) + { + var form = new UpdateManagerStatusForm(_vm); + form.ShowDialog(); + } + + private void lblMore_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL("http://developer.blackberry.com/native/documentation/cascades/dev/tools/api_levels.html"); + } + } +} diff --git a/src_vs2012/Package/Options/ApiLevelOptionControl.resx b/src_vs2012/Package/Options/ApiLevelOptionControl.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Options/ApiLevelOptionControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Options/ApiLevelOptionPage.cs b/src_vs2012/Package/Options/ApiLevelOptionPage.cs new file mode 100644 index 00000000..576d9e0c --- /dev/null +++ b/src_vs2012/Package/Options/ApiLevelOptionPage.cs @@ -0,0 +1,68 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.ViewModels; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Options +{ + /// + /// Option page to manage API levels. + /// + [Guid("5389599f-f906-4c23-b976-c7d75f1ae1ce")] + public sealed class ApiLevelOptionPage : DialogPage + { + #region Control + + private ApiLevelOptionControl _control; + + private ApiLevelOptionControl Control + { + get + { + if (_control == null) + { + _control = new ApiLevelOptionControl(); + _control.Location = new Point(0, 0); + } + + return _control; + } + } + + [Browsable(false)] + protected override IWin32Window Window + { + get + { + return Control; + } + } + + #endregion + + protected override void OnApply(PageApplyEventArgs e) + { + Control.OnApply(); + + if (!Control.HasSelectedNDK || PackageViewModel.Instance.ActiveNDK == null) + { + if (MessageBoxHelper.Show("No NDK is set as active. You won't be able to compile anything.\r\nDo you want to correct it manually?", + "API Level Settings", + MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + e.ApplyBehavior = ApplyKind.Cancel; + } + } + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + Control.OnClosed(); + } + } +} diff --git a/src_vs2012/Package/Options/BackupOptionControl.Designer.cs b/src_vs2012/Package/Options/BackupOptionControl.Designer.cs new file mode 100644 index 00000000..bc7fd71c --- /dev/null +++ b/src_vs2012/Package/Options/BackupOptionControl.Designer.cs @@ -0,0 +1,102 @@ +namespace BlackBerry.Package.Options +{ + partial class BackupOptionControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BackupOptionControl)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttBackup = new System.Windows.Forms.Button(); + this.bttRestore = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttBackup); + this.groupBox1.Controls.Add(this.bttRestore); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Location = new System.Drawing.Point(3, 3); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(396, 134); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "BlackBerry Developer Certificate"; + // + // bttBackup + // + this.bttBackup.Location = new System.Drawing.Point(9, 97); + this.bttBackup.Name = "bttBackup"; + this.bttBackup.Size = new System.Drawing.Size(75, 23); + this.bttBackup.TabIndex = 12; + this.bttBackup.Text = "&Backup..."; + this.bttBackup.UseVisualStyleBackColor = true; + this.bttBackup.Click += new System.EventHandler(this.bttBackup_Click); + // + // bttRestore + // + this.bttRestore.Location = new System.Drawing.Point(90, 97); + this.bttRestore.Name = "bttRestore"; + this.bttRestore.Size = new System.Drawing.Size(75, 23); + this.bttRestore.TabIndex = 13; + this.bttRestore.Text = "R&estore..."; + this.bttRestore.UseVisualStyleBackColor = true; + this.bttRestore.Click += new System.EventHandler(this.bttRestore_Click); + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label4.Location = new System.Drawing.Point(6, 25); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(384, 73); + this.label4.TabIndex = 11; + this.label4.Text = resources.GetString("label4.Text"); + // + // BackupOptionControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupBox1); + this.Name = "BackupOptionControl"; + this.Size = new System.Drawing.Size(402, 298); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button bttBackup; + private System.Windows.Forms.Button bttRestore; + private System.Windows.Forms.Label label4; + } +} diff --git a/src_vs2012/Package/Options/BackupOptionControl.cs b/src_vs2012/Package/Options/BackupOptionControl.cs new file mode 100644 index 00000000..0ab38b07 --- /dev/null +++ b/src_vs2012/Package/Options/BackupOptionControl.cs @@ -0,0 +1,51 @@ +using System; +using System.Windows.Forms; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Options +{ + public partial class BackupOptionControl : UserControl + { + private BackupOptionViewModel _vm = new BackupOptionViewModel(); + + public BackupOptionControl() + { + InitializeComponent(); + } + + private void bttBackup_Click(object sender, EventArgs e) + { + var form = DialogHelper.SaveZipFile("Exporting Developer Profile", "profile_backup_" + DateTime.Now.ToString("yyyy-MM-dd") + ".zip"); + + if (form.ShowDialog() == DialogResult.OK) + { + if (_vm.Developer.BackupProfile(form.FileName)) + { + MessageBoxHelper.Show("Developer profile exported", null, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBoxHelper.Show("Error while exporting developer profile", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void bttRestore_Click(object sender, EventArgs e) + { + var form = DialogHelper.OpenZipFile("Restoring Developer Profile"); + + if (form.ShowDialog() == DialogResult.OK) + { + if (_vm.Developer.RestoreProfile(form.FileName)) + { + MessageBoxHelper.Show("Developer profile restored", null, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBoxHelper.Show("Error while importing developer profile", null, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + } +} diff --git a/src_vs2012/Package/Options/BackupOptionControl.resx b/src_vs2012/Package/Options/BackupOptionControl.resx new file mode 100644 index 00000000..b7da4152 --- /dev/null +++ b/src_vs2012/Package/Options/BackupOptionControl.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + If you lose your signing keys, or forget your password, you will be required to re-register with BlackBerry. After re-registration, new versions of your applications will appear as new applications, and will not have access to shared data from previous releases. Exporting your signing keys will also allow you to import them on multiple computers and sign from any of them. + + \ No newline at end of file diff --git a/src_vs2012/Package/Options/BackupOptionPage.cs b/src_vs2012/Package/Options/BackupOptionPage.cs new file mode 100644 index 00000000..0f0ac084 --- /dev/null +++ b/src_vs2012/Package/Options/BackupOptionPage.cs @@ -0,0 +1,44 @@ +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Options +{ + /// + /// Options page to present some BlackBerry related backup possibilities. + /// + [Guid("ca5cca60-ada6-4342-8a7b-1c258e8b3060")] + public sealed class BackupOptionPage : DialogPage + { + #region Control + + private BackupOptionControl _control; + + private BackupOptionControl Control + { + get + { + if (_control == null) + { + _control = new BackupOptionControl(); + _control.Location = new Point(0, 0); + } + + return _control; + } + } + + [Browsable(false)] + protected override IWin32Window Window + { + get + { + return Control; + } + } + + #endregion + } +} diff --git a/src_vs2012/Package/Options/GeneralOptionControl.Designer.cs b/src_vs2012/Package/Options/GeneralOptionControl.Designer.cs new file mode 100644 index 00000000..71a503f0 --- /dev/null +++ b/src_vs2012/Package/Options/GeneralOptionControl.Designer.cs @@ -0,0 +1,242 @@ +namespace BlackBerry.Package.Options +{ + partial class GeneralOptionControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.txtNdkPath = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttOpenProfile = new System.Windows.Forms.Button(); + this.txtProfilePath = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.bttJavaBrowse = new System.Windows.Forms.Button(); + this.bttToolsBrowse = new System.Windows.Forms.Button(); + this.bttNdkBrowse = new System.Windows.Forms.Button(); + this.txtJavaPath = new System.Windows.Forms.TextBox(); + this.txtToolsPath = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.chkOpenInExternal = new System.Windows.Forms.CheckBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // txtNdkPath + // + this.txtNdkPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtNdkPath.Location = new System.Drawing.Point(91, 23); + this.txtNdkPath.Name = "txtNdkPath"; + this.txtNdkPath.Size = new System.Drawing.Size(429, 20); + this.txtNdkPath.TabIndex = 1; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttOpenProfile); + this.groupBox1.Controls.Add(this.txtProfilePath); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.bttJavaBrowse); + this.groupBox1.Controls.Add(this.bttToolsBrowse); + this.groupBox1.Controls.Add(this.bttNdkBrowse); + this.groupBox1.Controls.Add(this.txtJavaPath); + this.groupBox1.Controls.Add(this.txtToolsPath); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.txtNdkPath); + this.groupBox1.Location = new System.Drawing.Point(0, 0); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(616, 195); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Locations"; + // + // bttOpenProfile + // + this.bttOpenProfile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttOpenProfile.Location = new System.Drawing.Point(526, 148); + this.bttOpenProfile.Name = "bttOpenProfile"; + this.bttOpenProfile.Size = new System.Drawing.Size(75, 23); + this.bttOpenProfile.TabIndex = 12; + this.bttOpenProfile.Text = "Open..."; + this.bttOpenProfile.UseVisualStyleBackColor = true; + this.bttOpenProfile.Click += new System.EventHandler(this.bttOpenProfile_Click); + // + // txtProfilePath + // + this.txtProfilePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtProfilePath.Location = new System.Drawing.Point(91, 149); + this.txtProfilePath.Name = "txtProfilePath"; + this.txtProfilePath.ReadOnly = true; + this.txtProfilePath.Size = new System.Drawing.Size(429, 20); + this.txtProfilePath.TabIndex = 11; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(15, 154); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(64, 13); + this.label4.TabIndex = 10; + this.label4.Text = "Profile Path:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(15, 78); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(58, 13); + this.label5.TabIndex = 4; + this.label5.Text = "Java Path:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(15, 115); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(61, 13); + this.label3.TabIndex = 7; + this.label3.Text = "Tools Path:"; + // + // bttJavaBrowse + // + this.bttJavaBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttJavaBrowse.Location = new System.Drawing.Point(526, 74); + this.bttJavaBrowse.Name = "bttJavaBrowse"; + this.bttJavaBrowse.Size = new System.Drawing.Size(75, 23); + this.bttJavaBrowse.TabIndex = 6; + this.bttJavaBrowse.Text = "Browse..."; + this.bttJavaBrowse.UseVisualStyleBackColor = true; + this.bttJavaBrowse.Click += new System.EventHandler(this.bttJavaBrowse_Click); + // + // bttToolsBrowse + // + this.bttToolsBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttToolsBrowse.Location = new System.Drawing.Point(526, 111); + this.bttToolsBrowse.Name = "bttToolsBrowse"; + this.bttToolsBrowse.Size = new System.Drawing.Size(75, 23); + this.bttToolsBrowse.TabIndex = 9; + this.bttToolsBrowse.Text = "Browse..."; + this.bttToolsBrowse.UseVisualStyleBackColor = true; + this.bttToolsBrowse.Click += new System.EventHandler(this.bttToolsBrowse_Click); + // + // bttNdkBrowse + // + this.bttNdkBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttNdkBrowse.Location = new System.Drawing.Point(526, 22); + this.bttNdkBrowse.Name = "bttNdkBrowse"; + this.bttNdkBrowse.Size = new System.Drawing.Size(75, 23); + this.bttNdkBrowse.TabIndex = 2; + this.bttNdkBrowse.Text = "Browse..."; + this.bttNdkBrowse.UseVisualStyleBackColor = true; + this.bttNdkBrowse.Click += new System.EventHandler(this.bttNdkBrowse_Click); + // + // txtJavaPath + // + this.txtJavaPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtJavaPath.Location = new System.Drawing.Point(91, 75); + this.txtJavaPath.Name = "txtJavaPath"; + this.txtJavaPath.Size = new System.Drawing.Size(429, 20); + this.txtJavaPath.TabIndex = 5; + // + // txtToolsPath + // + this.txtToolsPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtToolsPath.Location = new System.Drawing.Point(91, 112); + this.txtToolsPath.Name = "txtToolsPath"; + this.txtToolsPath.Size = new System.Drawing.Size(429, 20); + this.txtToolsPath.TabIndex = 8; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(15, 46); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(109, 13); + this.label2.TabIndex = 3; + this.label2.Text = "(Visual Studio Edition)"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 26); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(58, 13); + this.label1.TabIndex = 0; + this.label1.Text = "NDK Path:"; + // + // chkOpenInExternal + // + this.chkOpenInExternal.AutoSize = true; + this.chkOpenInExternal.Location = new System.Drawing.Point(18, 201); + this.chkOpenInExternal.Name = "chkOpenInExternal"; + this.chkOpenInExternal.Size = new System.Drawing.Size(167, 17); + this.chkOpenInExternal.TabIndex = 1; + this.chkOpenInExternal.Text = "Open links in external browser"; + this.chkOpenInExternal.UseVisualStyleBackColor = true; + // + // GeneralOptionControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.chkOpenInExternal); + this.Controls.Add(this.groupBox1); + this.Name = "GeneralOptionControl"; + this.Size = new System.Drawing.Size(619, 261); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox txtNdkPath; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button bttToolsBrowse; + private System.Windows.Forms.Button bttNdkBrowse; + private System.Windows.Forms.TextBox txtToolsPath; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox txtProfilePath; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button bttOpenProfile; + private System.Windows.Forms.CheckBox chkOpenInExternal; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Button bttJavaBrowse; + private System.Windows.Forms.TextBox txtJavaPath; + } +} diff --git a/src_vs2012/Package/Options/GeneralOptionControl.cs b/src_vs2012/Package/Options/GeneralOptionControl.cs new file mode 100644 index 00000000..7cf24568 --- /dev/null +++ b/src_vs2012/Package/Options/GeneralOptionControl.cs @@ -0,0 +1,80 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Options +{ + public partial class GeneralOptionControl : UserControl + { + public GeneralOptionControl() + { + InitializeComponent(); + OnReset(); + } + + #region Properties + + public string NdkPath + { + get { return txtNdkPath.Text; } + set { txtNdkPath.Text = value; } + } + + public string JavaHomePath + { + get { return txtJavaPath.Text; } + set { txtJavaPath.Text = value; } + } + + public string ToolsPath + { + get { return txtToolsPath.Text; } + set { txtToolsPath.Text = value; } + } + + public string ProfilePath + { + get { return txtProfilePath.Text; } + set { txtProfilePath.Text = value; } + } + + /// + /// Checks if open URL links in internal or external browser. + /// + public bool IsOpeningExternal + { + get { return chkOpenInExternal.Checked; } + set { chkOpenInExternal.Checked = value; } + } + + #endregion + + private void bttNdkBrowse_Click(object sender, EventArgs e) + { + txtNdkPath.Text = DialogHelper.BrowseForFolder(txtNdkPath.Text, "Browse for NDK folder"); + } + + private void bttToolsBrowse_Click(object sender, EventArgs e) + { + txtToolsPath.Text = DialogHelper.BrowseForFolder(txtToolsPath.Text, "Browse for Tools folder"); + } + + private void bttJavaBrowse_Click(object sender, EventArgs e) + { + txtJavaPath.Text = DialogHelper.BrowseForFolder(txtJavaPath.Text, "Browse for Java Home folder"); + } + + private void bttOpenProfile_Click(object sender, EventArgs e) + { + DialogHelper.StartExplorer(ProfilePath); + } + + public void OnReset() + { + txtNdkPath.Text = ConfigDefaults.NdkDirectory; + txtToolsPath.Text = ConfigDefaults.ToolsDirectory; + txtProfilePath.Text = ConfigDefaults.DataDirectory; + } + } +} diff --git a/src_vs2012/Package/Options/GeneralOptionControl.resx b/src_vs2012/Package/Options/GeneralOptionControl.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Options/GeneralOptionControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Options/GeneralOptionPage.cs b/src_vs2012/Package/Options/GeneralOptionPage.cs new file mode 100644 index 00000000..1c51afd0 --- /dev/null +++ b/src_vs2012/Package/Options/GeneralOptionPage.cs @@ -0,0 +1,102 @@ +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using BlackBerry.NativeCore; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Options +{ + /// + /// Option page to manage general config - like PATHs!. + /// + [Guid("4dbdc58d-98ec-4908-b7e7-0638c71eae81")] + public sealed class GeneralOptionPage : DialogPage + { + #region Control + + private GeneralOptionControl _control; + + private GeneralOptionControl Control + { + get + { + if (_control == null) + { + _control = new GeneralOptionControl(); + _control.Location = new Point(0, 0); + } + + return _control; + } + } + + [Browsable(false)] + protected override IWin32Window Window + { + get + { + return Control; + } + } + + #endregion + + #region Properties + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string NdkPath + { + get { return Control.NdkPath; } + set { Control.NdkPath = value; } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string ToolsPath + { + get { return Control.ToolsPath; } + set { Control.ToolsPath = value; } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string JavaHomePath + { + get { return Control.JavaHomePath; } + set { Control.JavaHomePath = value; } + } + + public bool IsOpeningExternal + { + get { return Control.IsOpeningExternal; } + set { Control.IsOpeningExternal = value; } + } + + #endregion + + protected override void OnActivate(CancelEventArgs e) + { + base.OnActivate(e); + NdkPath = ConfigDefaults.NdkDirectory; + ToolsPath = ConfigDefaults.ToolsDirectory; + JavaHomePath = ConfigDefaults.JavaHome; + } + + protected override void OnApply(PageApplyEventArgs e) + { + base.OnApply(e); + if (e.ApplyBehavior == ApplyKind.Apply) + { + ConfigDefaults.Apply(NdkPath, ToolsPath, JavaHomePath); + } + } + + protected override void OnClosed(System.EventArgs e) + { + base.OnClosed(e); + Control.OnReset(); + } + } +} diff --git a/src_vs2012/Package/Options/LogsOptionControl.Designer.cs b/src_vs2012/Package/Options/LogsOptionControl.Designer.cs new file mode 100644 index 00000000..9ce92ffd --- /dev/null +++ b/src_vs2012/Package/Options/LogsOptionControl.Designer.cs @@ -0,0 +1,292 @@ +namespace BlackBerry.Package.Options +{ + partial class LogsOptionControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.chbInjectLogs = new System.Windows.Forms.CheckBox(); + this.chbLimitLogs = new System.Windows.Forms.CheckBox(); + this.label1 = new System.Windows.Forms.Label(); + this.txtLogPath = new System.Windows.Forms.TextBox(); + this.bttBrowse = new System.Windows.Forms.Button(); + this.numLogLimit = new System.Windows.Forms.NumericUpDown(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.txtSlog2BufferSets = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.cmbSlog2Formatter = new System.Windows.Forms.ComboBox(); + this.cmbSlog2Level = new System.Windows.Forms.ComboBox(); + this.label5 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.cmbLogsInterval = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.chbDebuggedOnly = new System.Windows.Forms.CheckBox(); + ((System.ComponentModel.ISupportInitialize)(this.numLogLimit)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // chbInjectLogs + // + this.chbInjectLogs.AutoSize = true; + this.chbInjectLogs.Checked = true; + this.chbInjectLogs.CheckState = System.Windows.Forms.CheckState.Checked; + this.chbInjectLogs.Location = new System.Drawing.Point(9, 19); + this.chbInjectLogs.Name = "chbInjectLogs"; + this.chbInjectLogs.Size = new System.Drawing.Size(216, 17); + this.chbInjectLogs.TabIndex = 0; + this.chbInjectLogs.Text = "Inject logs into standard \'Debug\' window"; + this.chbInjectLogs.UseVisualStyleBackColor = true; + // + // chbLimitLogs + // + this.chbLimitLogs.AutoSize = true; + this.chbLimitLogs.Checked = true; + this.chbLimitLogs.CheckState = System.Windows.Forms.CheckState.Checked; + this.chbLimitLogs.Location = new System.Drawing.Point(9, 56); + this.chbLimitLogs.Name = "chbLimitLogs"; + this.chbLimitLogs.Size = new System.Drawing.Size(167, 17); + this.chbLimitLogs.TabIndex = 3; + this.chbLimitLogs.Text = "Limit number of old log files to:"; + this.chbLimitLogs.UseVisualStyleBackColor = true; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(6, 28); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(76, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Logs directory:"; + // + // txtLogPath + // + this.txtLogPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtLogPath.Location = new System.Drawing.Point(88, 25); + this.txtLogPath.Name = "txtLogPath"; + this.txtLogPath.Size = new System.Drawing.Size(435, 20); + this.txtLogPath.TabIndex = 1; + // + // bttBrowse + // + this.bttBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttBrowse.Location = new System.Drawing.Point(529, 23); + this.bttBrowse.Name = "bttBrowse"; + this.bttBrowse.Size = new System.Drawing.Size(75, 23); + this.bttBrowse.TabIndex = 2; + this.bttBrowse.Text = "Browse..."; + this.bttBrowse.UseVisualStyleBackColor = true; + this.bttBrowse.Click += new System.EventHandler(this.bttBrowse_Click); + // + // numLogLimit + // + this.numLogLimit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.numLogLimit.Location = new System.Drawing.Point(477, 55); + this.numLogLimit.Name = "numLogLimit"; + this.numLogLimit.Size = new System.Drawing.Size(46, 20); + this.numLogLimit.TabIndex = 4; + this.numLogLimit.Value = new decimal(new int[] { + 25, + 0, + 0, + 0}); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.numLogLimit); + this.groupBox1.Controls.Add(this.txtLogPath); + this.groupBox1.Controls.Add(this.chbLimitLogs); + this.groupBox1.Controls.Add(this.bttBrowse); + this.groupBox1.Location = new System.Drawing.Point(6, 3); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(610, 80); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Host"; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.txtSlog2BufferSets); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.cmbSlog2Formatter); + this.groupBox2.Controls.Add(this.cmbSlog2Level); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.cmbLogsInterval); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.chbDebuggedOnly); + this.groupBox2.Controls.Add(this.chbInjectLogs); + this.groupBox2.Location = new System.Drawing.Point(6, 89); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(610, 204); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Device"; + // + // txtSlog2BufferSets + // + this.txtSlog2BufferSets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSlog2BufferSets.Location = new System.Drawing.Point(121, 163); + this.txtSlog2BufferSets.Name = "txtSlog2BufferSets"; + this.txtSlog2BufferSets.Size = new System.Drawing.Size(473, 20); + this.txtSlog2BufferSets.TabIndex = 9; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(8, 166); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(87, 13); + this.label4.TabIndex = 8; + this.label4.Text = "slog2 buffer-sets:"; + // + // cmbSlog2Formatter + // + this.cmbSlog2Formatter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cmbSlog2Formatter.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbSlog2Formatter.FormattingEnabled = true; + this.cmbSlog2Formatter.Items.AddRange(new object[] { + "message-only", + "~ + message", + "# + message", + "PID + message", + "appID + message", + "buffer + message", + "appID + buffer + message", + "PID + buffer + message", + "PID + appID + message"}); + this.cmbSlog2Formatter.Location = new System.Drawing.Point(121, 133); + this.cmbSlog2Formatter.Name = "cmbSlog2Formatter"; + this.cmbSlog2Formatter.Size = new System.Drawing.Size(402, 21); + this.cmbSlog2Formatter.TabIndex = 7; + // + // cmbSlog2Level + // + this.cmbSlog2Level.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbSlog2Level.FormattingEnabled = true; + this.cmbSlog2Level.Items.AddRange(new object[] { + "nothing", + "applications", + "system"}); + this.cmbSlog2Level.Location = new System.Drawing.Point(121, 103); + this.cmbSlog2Level.Name = "cmbSlog2Level"; + this.cmbSlog2Level.Size = new System.Drawing.Size(117, 21); + this.cmbSlog2Level.TabIndex = 5; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(8, 136); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(79, 13); + this.label5.TabIndex = 6; + this.label5.Text = "slog2 formatter:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(8, 106); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(99, 13); + this.label3.TabIndex = 4; + this.label3.Text = "slog2 capture level:"; + // + // cmbLogsInterval + // + this.cmbLogsInterval.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbLogsInterval.FormattingEnabled = true; + this.cmbLogsInterval.Location = new System.Drawing.Point(121, 73); + this.cmbLogsInterval.Name = "cmbLogsInterval"; + this.cmbLogsInterval.Size = new System.Drawing.Size(117, 21); + this.cmbLogsInterval.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(8, 76); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(107, 13); + this.label2.TabIndex = 2; + this.label2.Text = "Console logs interval:"; + // + // chbDebuggedOnly + // + this.chbDebuggedOnly.AutoSize = true; + this.chbDebuggedOnly.Location = new System.Drawing.Point(9, 45); + this.chbDebuggedOnly.Name = "chbDebuggedOnly"; + this.chbDebuggedOnly.Size = new System.Drawing.Size(227, 17); + this.chbDebuggedOnly.TabIndex = 1; + this.chbDebuggedOnly.Text = "Monitor logs of debugged applications only"; + this.chbDebuggedOnly.UseVisualStyleBackColor = true; + // + // LogsOptionControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Name = "LogsOptionControl"; + this.Size = new System.Drawing.Size(619, 296); + ((System.ComponentModel.ISupportInitialize)(this.numLogLimit)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.CheckBox chbInjectLogs; + private System.Windows.Forms.CheckBox chbLimitLogs; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox txtLogPath; + private System.Windows.Forms.Button bttBrowse; + private System.Windows.Forms.NumericUpDown numLogLimit; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox txtSlog2BufferSets; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox cmbSlog2Level; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox cmbLogsInterval; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.CheckBox chbDebuggedOnly; + private System.Windows.Forms.ComboBox cmbSlog2Formatter; + private System.Windows.Forms.Label label5; + } +} diff --git a/src_vs2012/Package/Options/LogsOptionControl.cs b/src_vs2012/Package/Options/LogsOptionControl.cs new file mode 100644 index 00000000..34e22fbe --- /dev/null +++ b/src_vs2012/Package/Options/LogsOptionControl.cs @@ -0,0 +1,122 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore.QConn.Services; +using BlackBerry.Package.Helpers; + +namespace BlackBerry.Package.Options +{ + public partial class LogsOptionControl : UserControl + { + private static readonly uint[] LogsIntervals = { 100, 250, 500, 750, 1000, 2000, 5000}; + + public LogsOptionControl() + { + InitializeComponent(); + + // add intervals on UI: + foreach (var interval in LogsIntervals) + { + cmbLogsInterval.Items.Add(interval >= 1000 ? (interval / 1000) + " s" : interval + " ms"); + } + + OnReset(); + } + + #region Properties + + public bool LimitLogs + { + get { return chbLimitLogs.Checked; } + set { chbLimitLogs.Checked = value; } + } + + public int LimitCount + { + get { return (int) numLogLimit.Value; } + set { numLogLimit.Value = value; } + } + + public string Path + { + get { return txtLogPath.Text; } + set { txtLogPath.Text = value; } + } + + public bool InjectLogs + { + get { return chbInjectLogs.Checked; } + set { chbInjectLogs.Checked = value; } + } + + public bool DebuggedOnly + { + get { return chbDebuggedOnly.Checked; } + set { chbDebuggedOnly.Checked = value; } + } + + public uint LogsInterval + { + get { return LogsIntervals[cmbLogsInterval.SelectedIndex]; } + set { cmbLogsInterval.SelectedIndex = GetNearest(LogsIntervals, value); } + } + + public int SLog2Level + { + get { return cmbSlog2Level.SelectedIndex; } + set { cmbSlog2Level.SelectedIndex = value; } + } + + public int SLog2Formatter + { + get { return cmbSlog2Formatter.SelectedIndex; } + set { cmbSlog2Formatter.SelectedIndex = value; } + } + + public string SLog2BufferSets + { + get { return txtSlog2BufferSets.Text; } + set { txtSlog2BufferSets.Text = value; } + } + + #endregion + + private static int GetNearest(uint[] values, uint value) + { + if (values == null) + throw new ArgumentNullException("values"); + + int result = -1; + uint delta = uint.MaxValue; + + for (int i = 0; i < values.Length; i++) + { + uint diff = (uint) Math.Abs(values[i] - (long) value); + if (diff < delta) + { + delta = diff; + result = i; + } + } + + return result; + } + + private void bttBrowse_Click(object sender, System.EventArgs e) + { + txtLogPath.Text = DialogHelper.BrowseForFolder(txtLogPath.Text, "Browse for Logs folder"); + } + + public void OnReset() + { + txtLogPath.Text = string.Empty; + chbLimitLogs.Checked = true; + numLogLimit.Value = 25; + chbInjectLogs.Checked = true; + chbDebuggedOnly.Checked = false; + cmbLogsInterval.SelectedIndex = GetNearest(LogsIntervals, TargetServiceConsoleLog.DefaultInterval); + cmbSlog2Level.SelectedIndex = 1; + cmbSlog2Formatter.SelectedIndex = 0; + txtSlog2BufferSets.Text = "default"; + } + } +} diff --git a/src_vs2012/Package/Options/LogsOptionControl.resx b/src_vs2012/Package/Options/LogsOptionControl.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Options/LogsOptionControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Options/LogsOptionPage.cs b/src_vs2012/Package/Options/LogsOptionPage.cs new file mode 100644 index 00000000..3e9a0d05 --- /dev/null +++ b/src_vs2012/Package/Options/LogsOptionPage.cs @@ -0,0 +1,128 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using BlackBerry.NativeCore.Components; +using BlackBerry.Package.Components; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Options +{ + /// + /// Option page to manage log settings. + /// + [Guid("fa49d8e4-61b9-4d8f-9872-26cf73a67687")] + public sealed class LogsOptionPage : DialogPage + { + #region Control + + private LogsOptionControl _control; + + private LogsOptionControl Control + { + get + { + if (_control == null) + { + _control = new LogsOptionControl(); + _control.Location = new Point(0, 0); + } + + return _control; + } + } + + [Browsable(false)] + protected override IWin32Window Window + { + get + { + return Control; + } + } + + #endregion + + #region Properties + + public bool LimitLogs + { + get { return Control.LimitLogs; } + set { Control.LimitLogs = value; } + } + + public int LimitCount + { + get { return Control.LimitCount; } + set { Control.LimitCount = value; } + } + + public string Path + { + get { return Control.Path; } + set { Control.Path = value; } + } + + public bool InjectLogs + { + get { return Control.InjectLogs; } + set { Control.InjectLogs = value; } + } + + public bool DebuggedOnly + { + get { return Control.DebuggedOnly; } + set { Control.DebuggedOnly = value; } + } + + public uint LogsInterval + { + get { return Control.LogsInterval; } + set { Control.LogsInterval = value; } + } + + public int SLog2Level + { + get { return Control.SLog2Level; } + set { Control.SLog2Level = value; } + } + + public int SLog2Formatter + { + get { return Control.SLog2Formatter; } + set { Control.SLog2Formatter = value; } + } + + public string SLog2BufferSets + { + get { return Control.SLog2BufferSets; } + set { Control.SLog2BufferSets = value; } + } + + #endregion + + internal string[] GetSLog2BufferSets() + { + return SLog2BufferSets.Split(new[] { ',', '|', ' ' }, StringSplitOptions.RemoveEmptyEntries); + } + + protected override void OnApply(PageApplyEventArgs e) + { + base.OnApply(e); + + if (e.ApplyBehavior == ApplyKind.Apply) + { + LogManager.Update(Path, LimitLogs ? LimitCount : -1); + Targets.TraceOptions(DebuggedOnly, LogsInterval, SLog2Level, SLog2Formatter, GetSLog2BufferSets(), InjectLogs, null); + } + else + { + if (e.ApplyBehavior == ApplyKind.Cancel || e.ApplyBehavior == ApplyKind.CancelNoNavigate) + { + Control.OnReset(); + } + } + } + } +} diff --git a/src_vs2012/Package/Options/SigningOptionControl.Designer.cs b/src_vs2012/Package/Options/SigningOptionControl.Designer.cs new file mode 100644 index 00000000..fd84dc82 --- /dev/null +++ b/src_vs2012/Package/Options/SigningOptionControl.Designer.cs @@ -0,0 +1,283 @@ +namespace BlackBerry.Package.Options +{ + partial class SigningOptionControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bttEditPublisher = new System.Windows.Forms.Button(); + this.lblStatus = new System.Windows.Forms.Label(); + this.bttUnregister = new System.Windows.Forms.Button(); + this.bttRegister = new System.Windows.Forms.Button(); + this.lblMore = new System.Windows.Forms.LinkLabel(); + this.label1 = new System.Windows.Forms.Label(); + this.bttDeletePassword = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.txtCertPath = new System.Windows.Forms.TextBox(); + this.txtAuthor = new System.Windows.Forms.TextBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.bttRefresh = new System.Windows.Forms.Button(); + this.bttChangeCert = new System.Windows.Forms.Button(); + this.bttNavigate = new System.Windows.Forms.Button(); + this.lblWarning = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.bttEditPublisher); + this.groupBox1.Controls.Add(this.lblStatus); + this.groupBox1.Controls.Add(this.bttUnregister); + this.groupBox1.Controls.Add(this.bttRegister); + this.groupBox1.Controls.Add(this.lblMore); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(3, 3); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(396, 134); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "BlackBerry Signing Authority"; + // + // bttEditPublisher + // + this.bttEditPublisher.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttEditPublisher.Location = new System.Drawing.Point(9, 99); + this.bttEditPublisher.Name = "bttEditPublisher"; + this.bttEditPublisher.Size = new System.Drawing.Size(156, 23); + this.bttEditPublisher.TabIndex = 9; + this.bttEditPublisher.Text = "&Edit Publisher info..."; + this.bttEditPublisher.UseVisualStyleBackColor = true; + this.bttEditPublisher.Click += new System.EventHandler(this.bttEditPublisher_Click); + // + // lblStatus + // + this.lblStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); + this.lblStatus.Location = new System.Drawing.Point(234, 48); + this.lblStatus.Name = "lblStatus"; + this.lblStatus.Size = new System.Drawing.Size(156, 76); + this.lblStatus.TabIndex = 4; + this.lblStatus.TextAlign = System.Drawing.ContentAlignment.BottomLeft; + // + // bttUnregister + // + this.bttUnregister.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttUnregister.Location = new System.Drawing.Point(90, 70); + this.bttUnregister.Name = "bttUnregister"; + this.bttUnregister.Size = new System.Drawing.Size(75, 23); + this.bttUnregister.TabIndex = 3; + this.bttUnregister.Text = "&Unregister"; + this.bttUnregister.UseVisualStyleBackColor = true; + this.bttUnregister.Click += new System.EventHandler(this.bttUnregister_Click); + // + // bttRegister + // + this.bttRegister.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.bttRegister.Location = new System.Drawing.Point(9, 70); + this.bttRegister.Name = "bttRegister"; + this.bttRegister.Size = new System.Drawing.Size(75, 23); + this.bttRegister.TabIndex = 2; + this.bttRegister.Text = "&Register..."; + this.bttRegister.UseVisualStyleBackColor = true; + this.bttRegister.Click += new System.EventHandler(this.bttRegister_Click); + // + // lblMore + // + this.lblMore.AutoSize = true; + this.lblMore.Location = new System.Drawing.Point(6, 48); + this.lblMore.Name = "lblMore"; + this.lblMore.Size = new System.Drawing.Size(60, 13); + this.lblMore.TabIndex = 1; + this.lblMore.TabStop = true; + this.lblMore.Text = "More info..."; + this.lblMore.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lblMore_LinkClicked); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Location = new System.Drawing.Point(6, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(384, 32); + this.label1.TabIndex = 0; + this.label1.Text = "You must register with BlackBerry to sign applications and create debug tokens fo" + + "r your device."; + // + // bttDeletePassword + // + this.bttDeletePassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttDeletePassword.Location = new System.Drawing.Point(315, 46); + this.bttDeletePassword.Name = "bttDeletePassword"; + this.bttDeletePassword.Size = new System.Drawing.Size(75, 23); + this.bttDeletePassword.TabIndex = 7; + this.bttDeletePassword.Text = "&Forget"; + this.bttDeletePassword.UseVisualStyleBackColor = true; + this.bttDeletePassword.Click += new System.EventHandler(this.bttDeletePassword_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 25); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(55, 13); + this.label2.TabIndex = 0; + this.label2.Text = "File name:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(6, 51); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(41, 13); + this.label3.TabIndex = 4; + this.label3.Text = "Author:"; + // + // txtCertPath + // + this.txtCertPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtCertPath.Location = new System.Drawing.Point(90, 22); + this.txtCertPath.Name = "txtCertPath"; + this.txtCertPath.ReadOnly = true; + this.txtCertPath.Size = new System.Drawing.Size(138, 20); + this.txtCertPath.TabIndex = 1; + // + // txtAuthor + // + this.txtAuthor.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtAuthor.Location = new System.Drawing.Point(90, 48); + this.txtAuthor.Name = "txtAuthor"; + this.txtAuthor.ReadOnly = true; + this.txtAuthor.Size = new System.Drawing.Size(138, 20); + this.txtAuthor.TabIndex = 5; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.bttRefresh); + this.groupBox2.Controls.Add(this.bttDeletePassword); + this.groupBox2.Controls.Add(this.bttChangeCert); + this.groupBox2.Controls.Add(this.bttNavigate); + this.groupBox2.Controls.Add(this.txtAuthor); + this.groupBox2.Controls.Add(this.txtCertPath); + this.groupBox2.Controls.Add(this.lblWarning); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Location = new System.Drawing.Point(3, 145); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(396, 100); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Developer Certificate to sign applications:"; + // + // bttRefresh + // + this.bttRefresh.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttRefresh.Location = new System.Drawing.Point(234, 46); + this.bttRefresh.Name = "bttRefresh"; + this.bttRefresh.Size = new System.Drawing.Size(75, 23); + this.bttRefresh.TabIndex = 6; + this.bttRefresh.Text = "&Load"; + this.bttRefresh.UseVisualStyleBackColor = true; + this.bttRefresh.Click += new System.EventHandler(this.bttRefresh_Click); + // + // bttChangeCert + // + this.bttChangeCert.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttChangeCert.Location = new System.Drawing.Point(234, 19); + this.bttChangeCert.Name = "bttChangeCert"; + this.bttChangeCert.Size = new System.Drawing.Size(75, 23); + this.bttChangeCert.TabIndex = 2; + this.bttChangeCert.Text = "&Import..."; + this.bttChangeCert.UseVisualStyleBackColor = true; + this.bttChangeCert.Click += new System.EventHandler(this.bttChangeCert_Click); + // + // bttNavigate + // + this.bttNavigate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttNavigate.Location = new System.Drawing.Point(315, 19); + this.bttNavigate.Name = "bttNavigate"; + this.bttNavigate.Size = new System.Drawing.Size(75, 23); + this.bttNavigate.TabIndex = 3; + this.bttNavigate.Text = "Detail&s..."; + this.bttNavigate.UseVisualStyleBackColor = true; + this.bttNavigate.Click += new System.EventHandler(this.bttNavigate_Click); + // + // lblWarning + // + this.lblWarning.AutoSize = true; + this.lblWarning.BackColor = System.Drawing.SystemColors.Control; + this.lblWarning.ForeColor = System.Drawing.Color.Red; + this.lblWarning.Location = new System.Drawing.Point(87, 71); + this.lblWarning.Name = "lblWarning"; + this.lblWarning.Size = new System.Drawing.Size(121, 13); + this.lblWarning.TabIndex = 0; + this.lblWarning.Text = "(if empty, signing will fail)"; + // + // SigningOptionControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Name = "SigningOptionControl"; + this.Size = new System.Drawing.Size(402, 298); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.LinkLabel lblMore; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox txtAuthor; + private System.Windows.Forms.TextBox txtCertPath; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button bttUnregister; + private System.Windows.Forms.Button bttRegister; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Button bttDeletePassword; + private System.Windows.Forms.Button bttNavigate; + private System.Windows.Forms.Button bttRefresh; + private System.Windows.Forms.Button bttChangeCert; + private System.Windows.Forms.Label lblStatus; + private System.Windows.Forms.Label lblWarning; + private System.Windows.Forms.Button bttEditPublisher; + } +} diff --git a/src_vs2012/Package/Options/SigningOptionControl.cs b/src_vs2012/Package/Options/SigningOptionControl.cs new file mode 100644 index 00000000..d9ac5526 --- /dev/null +++ b/src_vs2012/Package/Options/SigningOptionControl.cs @@ -0,0 +1,164 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore.Tools; +using BlackBerry.Package.Dialogs; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Options +{ + public partial class SigningOptionControl : UserControl + { + private readonly SigningOptionViewModel _vm = new SigningOptionViewModel(); + + public SigningOptionControl() + { + InitializeComponent(); + UpdateUI(); + } + + #region Properties + + public string CertificatePath + { + get { return txtCertPath.Text; } + set { txtCertPath.Text = value; } + } + + public string Author + { + get { return txtAuthor.Text; } + set { txtAuthor.Text = value; } + } + + #endregion + + private void UpdateUI() + { + CertificatePath = _vm.Developer.CertificateFileName; + Author = _vm.Developer.Name; + lblWarning.Visible = string.IsNullOrEmpty(Author); + + bttRegister.Enabled = !_vm.Developer.IsBB10Registered || !_vm.Developer.IsTabletRegistered; + bttUnregister.Enabled = _vm.Developer.HasCertificate; + // bttBackup.Enabled = bttUnregister.Enabled; + lblStatus.Text = _vm.Developer.ToShortStatusDescription(); + + bttNavigate.Enabled = !string.IsNullOrEmpty(CertificatePath); + bttDeletePassword.Enabled = _vm.Developer.IsPasswordSaved; + bttRefresh.Enabled = bttNavigate.Enabled; + } + + /// + /// Control has become visible again, when user navigated over Settings. + /// + public void OnActivate() + { + UpdateUI(); + } + + private void ReloadAuthor() + { + if (CertHelper.ReloadAuthor(_vm.Developer)) + { + UpdateUI(); + } + } + + private void lblMore_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL("http://www.blackberry.com/go/codesigning/"); + } + + private void bttChangeCert_Click(object sender, EventArgs e) + { + CertHelper.Import(_vm.Developer); + UpdateUI(); + } + + private void bttNavigate_Click(object sender, EventArgs e) + { + var form = new CertificateDetailsForm(_vm.Developer); + form.ShowDialog(); + + UpdateUI(); + } + + private void bttDeletePassword_Click(object sender, EventArgs e) + { + if (MessageBoxHelper.Show("Are you sure to delete stored certificate password?\r\n\r\nYou will need to type it in, whenever required.", + null, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) + return; + + _vm.Developer.ClearPassword(); + UpdateUI(); + } + + private void bttRefresh_Click(object sender, EventArgs e) + { + ReloadAuthor(); + } + + private void bttUnregister_Click(object sender, EventArgs e) + { + if (MessageBoxHelper.Show("Do you want to unregister and remove the BlackBerry ID Token file?\r\nThis operation can not be reverted. Make sure you have created a backup.", "UNREGISTRATION!!", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + /////////////////////// + // UNREGISTER + // this is the only place, where doing it synchronously is OK: + var runner = new KeyToolRemoveRunner(); + var success = runner.Execute(); + + // and delete all profile-related files: + _vm.Developer.DeleteProfile(); + UpdateUI(); + + // finally, show result message: + if (success && string.IsNullOrEmpty(runner.LastError)) + { + if (!string.IsNullOrEmpty(runner.LastOutput)) + { + MessageBoxHelper.Show(runner.LastOutput.Replace("CSK", "BlackBerry ID token"), "Unregistered developer profile", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + else + { + if (!string.IsNullOrEmpty(runner.LastError)) + { + MessageBoxHelper.Show(runner.LastError, "Failed to remove developer profile", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + } + + private void bttRegister_Click(object sender, EventArgs e) + { + /* + if (_vm.Developer.IsRegistered) + { + MessageBoxHelper.Show("You are already registered, please unregister first, if you want to create new BlackBerry ID token!", "Registration", + MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + */ + + /////////////////////////////// + // REGISTER + + var registrationForm = new RegistrationForm(_vm.Developer, 0); + registrationForm.ShowDialog(); + + UpdateUI(); + } + + private void bttEditPublisher_Click(object sender, EventArgs e) + { + var form = new CachedAuthorForm(null, _vm.Developer.CachedAuthor); + + if (form.ShowDialog() == DialogResult.OK) + { + _vm.Developer.CachedAuthor = form.ToAuthor(); + } + } + } +} diff --git a/src_vs2012/Package/Options/SigningOptionControl.resx b/src_vs2012/Package/Options/SigningOptionControl.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Options/SigningOptionControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Options/SigningOptionPage.cs b/src_vs2012/Package/Options/SigningOptionPage.cs new file mode 100644 index 00000000..61979c8e --- /dev/null +++ b/src_vs2012/Package/Options/SigningOptionPage.cs @@ -0,0 +1,50 @@ +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Options +{ + /// + /// Option page to manage developer signing process. + /// + [Guid("db5d17b9-8973-498b-a32d-194e8b31e431")] + public sealed class SigningOptionPage : DialogPage + { + #region Control + + private SigningOptionControl _control; + + private SigningOptionControl Control + { + get + { + if (_control == null) + { + _control = new SigningOptionControl(); + _control.Location = new Point(0, 0); + } + + return _control; + } + } + + [Browsable(false)] + protected override IWin32Window Window + { + get + { + return Control; + } + } + + #endregion + + protected override void OnActivate(CancelEventArgs e) + { + base.OnActivate(e); + Control.OnActivate(); + } + } +} diff --git a/src_vs2012/Package/Options/TargetsOptionControl.Designer.cs b/src_vs2012/Package/Options/TargetsOptionControl.Designer.cs new file mode 100644 index 00000000..f59d1467 --- /dev/null +++ b/src_vs2012/Package/Options/TargetsOptionControl.Designer.cs @@ -0,0 +1,223 @@ +namespace BlackBerry.Package.Options +{ + partial class TargetsOptionControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.listTargets = new System.Windows.Forms.ListView(); + this.columnActive = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnIP = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.label1 = new System.Windows.Forms.Label(); + this.bttAdd = new System.Windows.Forms.Button(); + this.bttEdit = new System.Windows.Forms.Button(); + this.bttRemove = new System.Windows.Forms.Button(); + this.lnkMoreInfo = new System.Windows.Forms.LinkLabel(); + this.bttDebugToken = new System.Windows.Forms.Button(); + this.bttActivate = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.listTargets); + this.groupBox1.Location = new System.Drawing.Point(3, 46); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(461, 301); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Known Targets"; + // + // listTargets + // + this.listTargets.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listTargets.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnActive, + this.columnType, + this.columnName, + this.columnIP}); + this.listTargets.FullRowSelect = true; + this.listTargets.GridLines = true; + this.listTargets.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listTargets.HideSelection = false; + this.listTargets.Location = new System.Drawing.Point(6, 19); + this.listTargets.MultiSelect = false; + this.listTargets.Name = "listTargets"; + this.listTargets.Size = new System.Drawing.Size(449, 276); + this.listTargets.TabIndex = 0; + this.listTargets.UseCompatibleStateImageBehavior = false; + this.listTargets.View = System.Windows.Forms.View.Details; + this.listTargets.SelectedIndexChanged += new System.EventHandler(this.listTargets_SelectedIndexChanged); + this.listTargets.DoubleClick += new System.EventHandler(this.listTargets_DoubleClick); + // + // columnActive + // + this.columnActive.Text = "A"; + this.columnActive.Width = 20; + // + // columnType + // + this.columnType.Text = "T"; + this.columnType.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnType.Width = 20; + // + // columnName + // + this.columnName.Text = "Name"; + this.columnName.Width = 140; + // + // columnIP + // + this.columnIP.Text = "IP"; + this.columnIP.Width = 100; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Location = new System.Drawing.Point(0, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(551, 33); + this.label1.TabIndex = 1; + this.label1.Text = "To connect to a device, you must turn on development mode on the device using Set" + + "tings > Security and Privacy > Development Mode."; + // + // bttAdd + // + this.bttAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttAdd.Location = new System.Drawing.Point(470, 51); + this.bttAdd.Name = "bttAdd"; + this.bttAdd.Size = new System.Drawing.Size(88, 23); + this.bttAdd.TabIndex = 2; + this.bttAdd.Text = "A&dd..."; + this.bttAdd.UseVisualStyleBackColor = true; + this.bttAdd.Click += new System.EventHandler(this.bttAdd_Click); + // + // bttEdit + // + this.bttEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttEdit.Enabled = false; + this.bttEdit.Location = new System.Drawing.Point(470, 80); + this.bttEdit.Name = "bttEdit"; + this.bttEdit.Size = new System.Drawing.Size(88, 23); + this.bttEdit.TabIndex = 2; + this.bttEdit.Text = "&Edit..."; + this.bttEdit.UseVisualStyleBackColor = true; + this.bttEdit.Click += new System.EventHandler(this.bttEdit_Click); + // + // bttRemove + // + this.bttRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttRemove.Enabled = false; + this.bttRemove.Location = new System.Drawing.Point(470, 109); + this.bttRemove.Name = "bttRemove"; + this.bttRemove.Size = new System.Drawing.Size(88, 23); + this.bttRemove.TabIndex = 2; + this.bttRemove.Text = "&Remove"; + this.bttRemove.UseVisualStyleBackColor = true; + this.bttRemove.Click += new System.EventHandler(this.bttRemove_Click); + // + // lnkMoreInfo + // + this.lnkMoreInfo.AutoSize = true; + this.lnkMoreInfo.Location = new System.Drawing.Point(0, 28); + this.lnkMoreInfo.Name = "lnkMoreInfo"; + this.lnkMoreInfo.Size = new System.Drawing.Size(60, 13); + this.lnkMoreInfo.TabIndex = 3; + this.lnkMoreInfo.TabStop = true; + this.lnkMoreInfo.Text = "More info..."; + this.lnkMoreInfo.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkMoreInfo_LinkClicked); + // + // bttDebugToken + // + this.bttDebugToken.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.bttDebugToken.Enabled = false; + this.bttDebugToken.Location = new System.Drawing.Point(470, 299); + this.bttDebugToken.Name = "bttDebugToken"; + this.bttDebugToken.Size = new System.Drawing.Size(88, 48); + this.bttDebugToken.TabIndex = 2; + this.bttDebugToken.Text = "&Upload debug token..."; + this.bttDebugToken.UseVisualStyleBackColor = true; + this.bttDebugToken.Click += new System.EventHandler(this.bttDebugToken_Click); + // + // bttActivate + // + this.bttActivate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bttActivate.Enabled = false; + this.bttActivate.Location = new System.Drawing.Point(470, 138); + this.bttActivate.Name = "bttActivate"; + this.bttActivate.Size = new System.Drawing.Size(88, 23); + this.bttActivate.TabIndex = 4; + this.bttActivate.Text = "Set &Active"; + this.bttActivate.UseVisualStyleBackColor = true; + this.bttActivate.Click += new System.EventHandler(this.bttActivate_Click); + // + // TargetsOptionControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.bttActivate); + this.Controls.Add(this.lnkMoreInfo); + this.Controls.Add(this.bttDebugToken); + this.Controls.Add(this.bttRemove); + this.Controls.Add(this.bttEdit); + this.Controls.Add(this.bttAdd); + this.Controls.Add(this.label1); + this.Controls.Add(this.groupBox1); + this.Name = "TargetsOptionControl"; + this.Size = new System.Drawing.Size(558, 355); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button bttAdd; + private System.Windows.Forms.Button bttEdit; + private System.Windows.Forms.Button bttRemove; + private System.Windows.Forms.LinkLabel lnkMoreInfo; + private System.Windows.Forms.Button bttDebugToken; + private System.Windows.Forms.ListView listTargets; + private System.Windows.Forms.ColumnHeader columnActive; + private System.Windows.Forms.ColumnHeader columnName; + private System.Windows.Forms.ColumnHeader columnIP; + private System.Windows.Forms.Button bttActivate; + private System.Windows.Forms.ColumnHeader columnType; + + } +} diff --git a/src_vs2012/Package/Options/TargetsOptionControl.cs b/src_vs2012/Package/Options/TargetsOptionControl.cs new file mode 100644 index 00000000..97802e94 --- /dev/null +++ b/src_vs2012/Package/Options/TargetsOptionControl.cs @@ -0,0 +1,162 @@ +using System; +using System.Windows.Forms; +using BlackBerry.NativeCore.Model; +using BlackBerry.Package.Dialogs; +using BlackBerry.Package.Helpers; +using BlackBerry.Package.ViewModels; + +namespace BlackBerry.Package.Options +{ + public partial class TargetsOptionControl : UserControl + { + private readonly TargetsOptionViewModel _vm = new TargetsOptionViewModel(); + + public TargetsOptionControl() + { + InitializeComponent(); + + PopulateDevices(); + } + + #region Properties + + private DeviceDefinition SelectedDevice + { + get + { + if (listTargets.SelectedItems.Count != 1) + return null; + + return listTargets.SelectedItems[0].Tag as DeviceDefinition; + } + } + + #endregion + + private void PopulateDevices() + { + listTargets.Items.Clear(); + + foreach (var device in _vm.Devices) + { + var item = new ListViewItem(); + item.Tag = device; + item.Text = _vm.IsActive(device) ? "x" : string.Empty; + item.SubItems.Add(device.Type == DeviceDefinitionType.Simulator ? "S" : string.Empty); + item.SubItems.Add(device.Name); + item.SubItems.Add(device.IP); + + listTargets.Items.Add(item); + } + + bttDebugToken.Enabled = _vm.RealDevicesCount > 0; + + // select first item: + if (listTargets.Items.Count > 0) + listTargets.Items[0].Selected = true; + } + + private void lnkMoreInfo_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + DialogHelper.StartURL("http://developer.blackberry.com/native/documentation/core/vs_get_started.html"); + } + + private void listTargets_SelectedIndexChanged(object sender, EventArgs e) + { + var device = SelectedDevice; + + bttEdit.Enabled = bttRemove.Enabled = bttActivate.Enabled = device != null; + + // update the button with 'debug-token' deployment, to limit it only to valid devices: + device = SelectedDevice ?? _vm.ActiveDevice; + if (device != null && device.Type != DeviceDefinitionType.Device) + device = null; + bttDebugToken.Enabled = _vm.RealDevicesCount > 0 && device != null; + } + + private void listTargets_DoubleClick(object sender, EventArgs e) + { + if (SelectedDevice != null) + { + bttEdit_Click(sender, e); + } + } + + private void bttAdd_Click(object sender, EventArgs e) + { + var form = new DeviceForm("Add New Target Device"); + + if (form.ShowDialog() == DialogResult.OK) + { + _vm.Add(form.ToDevice()); + PopulateDevices(); + } + } + + private void bttEdit_Click(object sender, EventArgs e) + { + var form = new DeviceForm("Edit Target Device"); + var device = SelectedDevice; + form.FromDevice(device); + + if (form.ShowDialog() == DialogResult.OK) + { + _vm.Update(device, form.ToDevice()); + PopulateDevices(); + } + } + + private void bttActivate_Click(object sender, EventArgs e) + { + _vm.SetActive(SelectedDevice); + PopulateDevices(); + } + + private void bttRemove_Click(object sender, EventArgs e) + { + var device = SelectedDevice; + + if (device != null + && MessageBoxHelper.Show(device.Type == DeviceDefinitionType.Device ? "Remove the device?" : "Remove the simulator?", + device.ToString(), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + _vm.Remove(device); + PopulateDevices(); + listTargets_SelectedIndexChanged(null, EventArgs.Empty); + } + } + + private void bttDebugToken_Click(object sender, EventArgs e) + { + var device = SelectedDevice ?? _vm.ActiveDevice; + + if (device != null && device.Type != DeviceDefinitionType.Device) + device = null; + + if (device != null) + { + var form = new DebugTokenDeploymentForm(_vm, device); + form.AskOnStartup = false; + form.ShowDialog(); + + // refresh the list, as it's possible to add new device from debug-token deployment form: + PopulateDevices(); + } + else + { + MessageBoxHelper.Show("Please select a device first", null, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + + public void OnApply() + { + _vm.Apply(); + } + + public void OnReset() + { + _vm.Reset(); + PopulateDevices(); + } + } +} diff --git a/src_vs2012/Package/Options/TargetsOptionControl.resx b/src_vs2012/Package/Options/TargetsOptionControl.resx new file mode 100644 index 00000000..29dcb1b3 --- /dev/null +++ b/src_vs2012/Package/Options/TargetsOptionControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src_vs2012/Package/Options/TargetsOptionPage.cs b/src_vs2012/Package/Options/TargetsOptionPage.cs new file mode 100644 index 00000000..232293fc --- /dev/null +++ b/src_vs2012/Package/Options/TargetsOptionPage.cs @@ -0,0 +1,56 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Options +{ + /// + /// Option page to manage list of targets and debug-tokens. + /// + [Guid("acd13513-da2b-4862-a4fc-30672233d812")] + public sealed class TargetsOptionPage : DialogPage + { + #region Control + + private TargetsOptionControl _control; + + private TargetsOptionControl Control + { + get + { + if (_control == null) + { + _control = new TargetsOptionControl(); + _control.Location = new Point(0, 0); + } + + return _control; + } + } + + [Browsable(false)] + protected override IWin32Window Window + { + get + { + return Control; + } + } + + #endregion + + protected override void OnApply(PageApplyEventArgs e) + { + Control.OnApply(); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + Control.OnReset(); + } + } +} diff --git a/src_vs2012/Package/PackageCommands.cs b/src_vs2012/Package/PackageCommands.cs new file mode 100644 index 00000000..c6ebc45b --- /dev/null +++ b/src_vs2012/Package/PackageCommands.cs @@ -0,0 +1,41 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +namespace BlackBerry.Package +{ + internal static class PackageCommands + { + public const int cmdidBlackBerryCommonAddPlatformTargets = 0x0201; + public const int cmdidBlackBerryCommonProjectImport = 0x0202; + + public const int cmdidBlackBerryToolWindowsTargetNavigator = 0x251; + + public const int cmdidBlackBerryOptions = 0x301; + public const int cmdidBlackBerryTargetsDevicesPlaceholder = 0x501; + public const int cmdidBlackBerryTargetsApiLevelsPlaceholder = 0x601; + public const int cmdidBlackBerryTargetsRuntimeLibrariesPlaceholder = 0x701; + public const int cmdidBlackBerryTargetsConfigure = 0x801; + + public const int cmdidBlackBerryHelpWelcomePage = 0x1001; + public const int cmdidBlackBerryHelpSupportForum = 0x1002; + public const int cmdidBlackBerryHelpDocNative = 0x1101; + public const int cmdidBlackBerryHelpDocCascades = 0x1102; + public const int cmdidBlackBerryHelpDocPlayBook = 0x1103; + public const int cmdidBlackBerryHelpSamplesNative = 0x1201; + public const int cmdidBlackBerryHelpSamplesCascades = 0x1202; + public const int cmdidBlackBerryHelpSamplesPlayBook = 0x1203; + public const int cmdidBlackBerryHelpSamplesOpenSource = 0x1204; + public const int cmdidBlackBerryHelpAbout = 0x1301; + } +} diff --git a/src_vs2012/Package/Registration/DebugEngineRegistrationAttribute.cs b/src_vs2012/Package/Registration/DebugEngineRegistrationAttribute.cs new file mode 100644 index 00000000..c30e7a5b --- /dev/null +++ b/src_vs2012/Package/Registration/DebugEngineRegistrationAttribute.cs @@ -0,0 +1,246 @@ +using System; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Registration +{ + /// + /// Registration attribute providing info about custom DebugEndine implemented withing this package. + /// + public sealed class DebugEngineRegistrationAttribute : RegistrationAttribute + { + private const string DefaultInprocServerPath = "$WinDir$\\System32\\mscoree.dll"; + + /// + /// Init constructor. + /// + public DebugEngineRegistrationAttribute(string name, object debugEngineGUID) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentNullException("name"); + if (debugEngineGUID == null) + throw new ArgumentNullException("debugEngineGUID"); + + Name = name; + DebugEngineGUID = debugEngineGUID; + AllowUserEnteredPorts = true; + } + + #region Properties + + public string Name + { + get; + private set; + } + + /// + /// Gets or sets the indication of support for attachment to existing programs. + /// + public bool Attach + { + get; + set; + } + + /// + /// Gets or sets an indication of support for address breakpoints. + /// + public bool AddressBreakpoints + { + get; + set; + } + + /// + /// Gets or set an indication of support for callstack breakpoints. + /// + public bool CallstackBreakpoints + { + get; + set; + } + + /// + /// Gets or sets an indication of support for suspending thread execution. + /// + public bool SuspendThread + { + get; + set; + } + + /// + /// Gets or sets indication if always load the debug engine locally. + /// + public bool AlwaysLoadLocal + { + get; + set; + } + + public uint AutoSelectPriority + { + get; + set; + } + + public object DebugEngineGUID + { + get; + private set; + } + + /// + /// Gets or sets the GUID for a class implementing IDebugEngine interface. + /// + public object DebugEngineClassGUID + { + get; + set; + } + + public string DebugEngineClassName + { + get; + set; + } + + /// + /// Gets or sets the GUID of the program provider class. + /// + public object ProgramProviderClassGUID + { + get; + set; + } + + public string ProgramProviderClassName + { + get; + set; + } + + /// + /// Gets or set the comma-separated list of the port supplier(s) + /// + public object PortSupplierClassGUID + { + get; + set; + } + + public string PortSupplierClassName + { + get; + set; + } + + public string AssemblyName + { + get; + set; + } + + /// + /// Gets or sets if developer can input any text in 'Qualifier' field in 'Attach to...' window of Visual Studio. + /// + public bool AllowUserEnteredPorts + { + get; + set; + } + + #endregion + + public override void Register(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + var key = context.CreateKey(@"AD7Metrics\Engine\" + AttributeHelper.Format(DebugEngineGUID)); + + key.SetValue("Attach", Format(Attach)); + key.SetValue("AddressBP", Format(AddressBreakpoints)); + key.SetValue("CallstackBP", Format(CallstackBreakpoints)); + key.SetValue("SuspendThread", Format(SuspendThread)); + key.SetValue("AlwaysLoadLocal", Format(AlwaysLoadLocal)); + key.SetValue("AutoSelectPriority", AutoSelectPriority); + if (DebugEngineClassGUID != null) + key.SetValue("CLSID", AttributeHelper.Format(DebugEngineClassGUID)); + if (ProgramProviderClassGUID != null) + key.SetValue("ProgramProvider", AttributeHelper.Format(ProgramProviderClassGUID)); + + // Port suppliers + if (PortSupplierClassGUID != null) + { + var portSupplierFormattedGuid = AttributeHelper.Format(PortSupplierClassGUID); + + key.SetValue("PortSupplier", portSupplierFormattedGuid); + var supplierDetailsKey = context.CreateKey(@"AD7Metrics\PortSupplier\" + portSupplierFormattedGuid); + supplierDetailsKey.SetValue("DisallowUserEnteredPorts", AllowUserEnteredPorts ? 0u : 1u); + supplierDetailsKey.SetValue("CLSID", portSupplierFormattedGuid); + supplierDetailsKey.SetValue("PortPickerCLSID", portSupplierFormattedGuid); + supplierDetailsKey.Close(); + } + key.Close(); + + // describe classes: + RegisterClass(context, DebugEngineClassGUID, DebugEngineClassName); + RegisterClass(context, ProgramProviderClassGUID, ProgramProviderClassName); + RegisterClass(context, PortSupplierClassGUID, PortSupplierClassName); + } + + /// + /// Registers reference to specified class. + /// + private void RegisterClass(RegistrationContext context, object classGuid, string className) + { + if (classGuid != null) + { + var key = context.CreateKey(@"CLSID\" + AttributeHelper.Format(classGuid)); + if (!string.IsNullOrEmpty(className)) + key.SetValue("Class", className); + if (!string.IsNullOrEmpty(AssemblyName)) + { + key.SetValue("InprocServer32", DefaultInprocServerPath); + + // check if full-path specified or relative to the package location: + if ((AssemblyName.Length > 2 && AssemblyName[1] == ':') || AssemblyName.StartsWith("file://", StringComparison.InvariantCultureIgnoreCase)) + { + key.SetValue("CodeBase", AssemblyName); + } + else + { + key.SetValue("CodeBase", "$PackageFolder$\\" + AssemblyName); + } + } + key.Close(); + } + } + + private static void UnregisterClass(RegistrationContext context, object classGuid) + { + if (classGuid != null) + { + context.RemoveKey(@"CLSID\" + AttributeHelper.Format(classGuid)); + } + } + + private static uint Format(bool value) + { + return value ? 1u : 0u; + } + + public override void Unregister(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + context.RemoveKey(@"AD7Metrics\Engine\" + AttributeHelper.Format(DebugEngineGUID)); + UnregisterClass(context, DebugEngineClassGUID); + UnregisterClass(context, ProgramProviderClassGUID); + UnregisterClass(context, PortSupplierClassGUID); + } + } +} diff --git a/src_vs2012/Package/Registration/ProvideProjects.cs b/src_vs2012/Package/Registration/ProvideProjects.cs new file mode 100644 index 00000000..29506934 --- /dev/null +++ b/src_vs2012/Package/Registration/ProvideProjects.cs @@ -0,0 +1,107 @@ +using System; +using System.IO; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Registration +{ + /// + /// Custom registration attribute, that will let to define new custom VC++ projects within the VSIP package. + /// + public sealed class ProvideProjects : RegistrationAttribute + { + /// + /// Init constructor. + /// + public ProvideProjects(object projectFactoryType, string categoryName, string templatesDir, int priority) + { + if (projectFactoryType == null) + throw new ArgumentNullException("projectFactoryType"); + if (string.IsNullOrEmpty(templatesDir)) + throw new ArgumentNullException("templatesDir"); + if (string.IsNullOrEmpty(categoryName)) + throw new ArgumentNullException("categoryName"); + + ProjectFactoryType = projectFactoryType; + Name = categoryName; + TemplatesDir = templatesDir; + Priority = priority; + + Activity = "VC++"; + } + + #region Properties + + public object ProjectFactoryType + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public string TemplatesDir + { + get; + private set; + } + + public int Priority + { + get; + private set; + } + + public string Activity + { + get; + set; + } + + #endregion + + private string GetRegistryPath() + { + var factoryGuid = AttributeHelper.GetGuidFrom(ProjectFactoryType); + + return string.Concat(@"NewProjectTemplates\TemplateDirs\", factoryGuid.ToString("B"), @"\/1"); + } + + public override void Register(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + // register templates folder: + using (var key = context.CreateKey(GetRegistryPath())) + { + key.SetValue("", Name); + key.SetValue("SortPriority", Priority); + + if (!string.IsNullOrEmpty(Activity)) + { + // put the info in a node of active development activities or inside 'Other Languages': + // more info: http://blogs.msdn.com/b/vsdocs/archive/2006/10/30/new-project-generation-under-the-hood.aspx + key.SetValue("DeveloperActivity", Activity); + } + + string path = Path.Combine(Path.GetDirectoryName(new Uri(context.ComponentType.Assembly.CodeBase).LocalPath), TemplatesDir); + path = context.EscapePath(Path.GetFullPath(path)); + key.SetValue("TemplatesDir", path); + } + } + + public override void Unregister(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + // remove registered templates folder: + context.RemoveKey(GetRegistryPath()); + } + } +} diff --git a/src_vs2012/Package/Registration/ProvideWizardEngineAttribute.cs b/src_vs2012/Package/Registration/ProvideWizardEngineAttribute.cs new file mode 100644 index 00000000..11a8d05b --- /dev/null +++ b/src_vs2012/Package/Registration/ProvideWizardEngineAttribute.cs @@ -0,0 +1,139 @@ +using System; +using System.Runtime.InteropServices; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio.Shell; + +namespace BlackBerry.Package.Registration +{ + /// + /// Registration attribute that creates entries to publish specified type as a custom wizard engine within current version of Visual Studio only. + /// + /// More about VC++ wizards: + /// * http://msdn.microsoft.com/en-us/library/7k3w6w59.aspx + /// * http://go.microsoft.com/fwlink/?LinkId=229844 + /// * http://msdn.microsoft.com/en-us/library/vstudio/96xz4cw2(v=vs.100).aspx + /// + public sealed class ProvideWizardEngineAttribute : RegistrationAttribute + { + /// + /// Default constructor. + /// + public ProvideWizardEngineAttribute() + { + } + + /// + /// Init constructor. + /// + public ProvideWizardEngineAttribute(Type engineType) + { + if (engineType == null) + throw new ArgumentNullException("engineType"); + if (engineType.GUID == Guid.Empty) + throw new ArgumentOutOfRangeException("engineType"); + + ClassGUID = engineType.GUID; + ClassName = engineType.FullName; + AssemblyName = engineType.Assembly.Location; + + var progIdAttribute = (ProgIdAttribute)GetCustomAttribute(engineType, typeof(ProgIdAttribute)); + ProgId = progIdAttribute != null ? progIdAttribute.Value : null; + } + + #region Properties + + public object ClassGUID + { + get; + set; + } + + public string ClassName + { + get; + set; + } + + public string ProgId + { + get; + set; + } + + public string AssemblyName + { + get; + set; + } + + #endregion + + private string GetWizardClassGuidString() + { + return AttributeHelper.GetGuidFrom(ClassGUID).ToString("B").ToUpperInvariant(); + } + + public override void Register(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + // class registration: + var wizardClassGuid = GetWizardClassGuidString(); + using (var key = context.CreateKey(@"CLSID\" + wizardClassGuid)) + { + key.SetValue(null, ClassName); + key.SetValue("Class", ClassName); + + // check if full-path specified or relative to the package location: + if ((AssemblyName.Length > 2 && AssemblyName[1] == ':') || AssemblyName.StartsWith("file://", StringComparison.InvariantCultureIgnoreCase)) + { + key.SetValue("CodeBase", AssemblyName); + } + else + { + key.SetValue("CodeBase", @"$PackageFolder$\" + AssemblyName); + } + + key.SetValue("InprocServer32", @"$WinDir$\System32\mscoree.dll"); + key.SetValue("ThreadingModel", "Both"); + + if (!string.IsNullOrEmpty(ProgId)) + { + using (var p = key.CreateSubkey("ProgId")) + { + p.SetValue(null, ProgId); + } + } + } + + // ProgId registration, if specified: + if (!string.IsNullOrEmpty(ProgId)) + { + using (var key = context.CreateKey(@"ProgId\" + ProgId)) + { + key.SetValue(null, ClassName); + using (var clsid = key.CreateSubkey("CLSID")) + { + clsid.SetValue(null, wizardClassGuid); + } + } + } + } + + public override void Unregister(RegistrationContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + // remove class registration: + context.RemoveKey(@"CLSID\" + GetWizardClassGuidString()); + + // remove ProgId registration: + if (!string.IsNullOrEmpty(ProgId)) + { + context.RemoveKey(@"ProgId\" + ProgId); + } + } + } +} diff --git a/src_vs2012/Package/Registration/XmlEditorDesignerViewRegistrationAttribute.cs b/src_vs2012/Package/Registration/XmlEditorDesignerViewRegistrationAttribute.cs new file mode 100644 index 00000000..61e3070c --- /dev/null +++ b/src_vs2012/Package/Registration/XmlEditorDesignerViewRegistrationAttribute.cs @@ -0,0 +1,176 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +using System; +using BlackBerry.Package.Helpers; +using Microsoft.VisualStudio.Shell; +using System.IO; +using Microsoft.VisualStudio; + +namespace BlackBerry.Package.Registration +{ + /// + /// Register our bardescriptor.xml custom editor + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] + public sealed class XmlEditorDesignerViewRegistrationAttribute : RegistrationAttribute + { + /// Declare Constants + const string XmlChooserFactory = "XmlChooserFactory"; + const string XmlChooserEditorExtensionsKeyPath = @"Editors\{32CC8DFA-2D70-49b2-94CD-22D57349B778}\Extensions"; + const string XmlEditorFactoryGuid = "{FA3CD31E-987B-443A-9B81-186104E8DAC1}"; + + /// Declare Private Member Variables + private readonly string _keyName; + private readonly string _defaultExtension; + private readonly Guid _defaultLogicalView; + private readonly int _xmlChooserPriority; + + /// + /// Init constructor + /// + /// Registry key name + /// Default extension for editor + /// Default Editor Factory + /// XML Priority + public XmlEditorDesignerViewRegistrationAttribute(string keyName, string defaultExtension, object defaultLogicalViewEditorFactory, int xmlChooserPriority) + { + // Validate parameter input + if (string.IsNullOrWhiteSpace(keyName)) + throw new ArgumentException("Editor description cannot be null or empty.", "editorDescription"); + if (string.IsNullOrWhiteSpace(defaultExtension)) + throw new ArgumentException("Extension cannot be null or empty.", "extension"); + if (defaultLogicalViewEditorFactory == null) + throw new ArgumentNullException("defaultLogicalViewEditorFactory"); + + // Set Member Variables + _keyName = keyName; + _defaultExtension = defaultExtension.StartsWith(".") ? defaultExtension.Substring(1) : defaultExtension; + _defaultLogicalView = AttributeHelper.GetGuidFrom(defaultLogicalViewEditorFactory); + _xmlChooserPriority = xmlChooserPriority; + + CodeLogicalViewEditor = XmlEditorFactoryGuid; + DebuggingLogicalViewEditor = XmlEditorFactoryGuid; + DesignerLogicalViewEditor = XmlEditorFactoryGuid; + TextLogicalViewEditor = XmlEditorFactoryGuid; + } + + /// + /// Register the custom editor + /// + public override void Register(RegistrationContext context) + { + // Validate parameter input + if (context == null) + throw new ArgumentNullException("context"); + + // Set extension key + Key extensionKey = context.CreateKey(XmlChooserEditorExtensionsKeyPath); + extensionKey.SetValue(_defaultExtension, _xmlChooserPriority); + extensionKey.Close(); + + // Set editor key + Key editorKey = context.CreateKey(Path.Combine(XmlChooserFactory, _keyName)); + editorKey.SetValue("DefaultLogicalView", AttributeHelper.Format(_defaultLogicalView)); + editorKey.SetValue("Extension", _defaultExtension); + if (!string.IsNullOrWhiteSpace(Namespace)) + { + editorKey.SetValue("Namespace", Namespace); + } + if (MatchExtensionAndNamespace) + { + editorKey.SetValue("Match", "both"); + } + if (IsDataSet.HasValue) + { + editorKey.SetValue("IsDataSet", Convert.ToInt32(IsDataSet.Value)); + } + + // Set DebuggingLogicalViewEditor Mapping + if (DebuggingLogicalViewEditor != null) + { + editorKey.SetValue(AttributeHelper.Format(VSConstants.LOGVIEWID_Debugging), AttributeHelper.Format(DebuggingLogicalViewEditor)); + } + + // Set CodeLogicalViewEditor Mapping + if (CodeLogicalViewEditor != null) + { + editorKey.SetValue(AttributeHelper.Format(VSConstants.LOGVIEWID_Code), AttributeHelper.Format(CodeLogicalViewEditor)); + } + + // Set DesignerLogicalViewEditor Mapping + if (DesignerLogicalViewEditor != null) + { + editorKey.SetValue(AttributeHelper.Format(VSConstants.LOGVIEWID_Designer), AttributeHelper.Format(DesignerLogicalViewEditor)); + } + + // Set TextLogicalViewEditor Mapping + if (TextLogicalViewEditor != null) + { + editorKey.SetValue(AttributeHelper.Format(VSConstants.LOGVIEWID_TextView), AttributeHelper.Format(TextLogicalViewEditor)); + } + editorKey.Close(); + } + + /// + /// Unregister the custom editor + /// + public override void Unregister(RegistrationContext context) + { + // Validate parameter input + if (context == null) + throw new ArgumentNullException("context"); + + // Remove Key + context.RemoveKey(Path.Combine(XmlChooserFactory, _keyName)); + context.RemoveValue(XmlChooserEditorExtensionsKeyPath, _defaultExtension); + context.RemoveKeyIfEmpty(XmlChooserEditorExtensionsKeyPath); + } + + /// + /// The editor factor for the Code View Editor + /// + public object CodeLogicalViewEditor { get; set; } + + /// + /// The editor factory for the Debugging View Editor + /// + public object DebuggingLogicalViewEditor { get; set; } + + /// + /// The editor factor for the Designer View Editor + /// + public object DesignerLogicalViewEditor { get; set; } + + /// + /// The edtior factgory for the Text View Editor + /// + public object TextLogicalViewEditor { get; set; } + + /// + /// Namespace property + /// + public string Namespace { get; set; } + + /// + /// Property + /// + public bool MatchExtensionAndNamespace { get; set; } + + /// + /// Special value used only by the DataSet designer. + /// + public bool? IsDataSet { get; set; } + } +} diff --git a/src_vs2012/Package/Resources/License.txt b/src_vs2012/Package/Resources/License.txt new file mode 100644 index 00000000..5dc29dc0 --- /dev/null +++ b/src_vs2012/Package/Resources/License.txt @@ -0,0 +1,10 @@ +Author: Paweł Hofman (@CodeTitans) +Site: https://github.com/phofman/vs-plugin +Wiki: https://github.com/phofman/vs-plugin/wiki + +This software is provided "AS IS" and 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. +In no event shall the regents or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. + +I do not spy any user data, project information, nor usage statistics. If you like to share anything with me, please visit the project site. The same is also understood in context of bugs. I put my best skills to let this software keep highest standards. However if you do find any bug, please report at: +https://github.com/phofman/vs-plugin/issues + diff --git a/src_vs2012/Package/Resources/Logo.png b/src_vs2012/Package/Resources/Logo.png new file mode 100644 index 00000000..9b1f19f5 Binary files /dev/null and b/src_vs2012/Package/Resources/Logo.png differ diff --git a/src_vs2012/Package/Resources/Navigator/folder_closed.png b/src_vs2012/Package/Resources/Navigator/folder_closed.png new file mode 100644 index 00000000..7931bf2f Binary files /dev/null and b/src_vs2012/Package/Resources/Navigator/folder_closed.png differ diff --git a/src_vs2012/Package/Resources/Navigator/folder_opened.png b/src_vs2012/Package/Resources/Navigator/folder_opened.png new file mode 100644 index 00000000..2940d2e8 Binary files /dev/null and b/src_vs2012/Package/Resources/Navigator/folder_opened.png differ diff --git a/src_vs2012/Package/Resources/Navigator/process.png b/src_vs2012/Package/Resources/Navigator/process.png new file mode 100644 index 00000000..df19b8ed Binary files /dev/null and b/src_vs2012/Package/Resources/Navigator/process.png differ diff --git a/src_vs2012/Package/Resources/Navigator/target.png b/src_vs2012/Package/Resources/Navigator/target.png new file mode 100644 index 00000000..ccca6323 Binary files /dev/null and b/src_vs2012/Package/Resources/Navigator/target.png differ diff --git a/src_vs2012/Package/Resources/Navigator/target_disconnected.png b/src_vs2012/Package/Resources/Navigator/target_disconnected.png new file mode 100644 index 00000000..f4c57e5a Binary files /dev/null and b/src_vs2012/Package/Resources/Navigator/target_disconnected.png differ diff --git a/src_vs2012/Package/Resources/Navigator/thread.png b/src_vs2012/Package/Resources/Navigator/thread.png new file mode 100644 index 00000000..37676ea5 Binary files /dev/null and b/src_vs2012/Package/Resources/Navigator/thread.png differ diff --git a/src_vs2012/Package/Resources/Package.Bitmaps.vsct b/src_vs2012/Package/Resources/Package.Bitmaps.vsct new file mode 100644 index 00000000..f8870ecd --- /dev/null +++ b/src_vs2012/Package/Resources/Package.Bitmaps.vsct @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src_vs2012/Package/Resources/Package.Menu.vsct b/src_vs2012/Package/Resources/Package.Menu.vsct new file mode 100644 index 00000000..8aef165d --- /dev/null +++ b/src_vs2012/Package/Resources/Package.Menu.vsct @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + &Targets + + + + + + + + &Help + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src_vs2012/Package/Resources/Package.vsct b/src_vs2012/Package/Resources/Package.vsct new file mode 100644 index 00000000..8c84ab3a --- /dev/null +++ b/src_vs2012/Package/Resources/Package.vsct @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + B&lackBerry + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/VSNDK.Package/Resources/BlackBerryMessager.bmp b/src_vs2012/Package/Resources/Permissions/BlackBerryMessager.bmp similarity index 100% rename from src/VSNDK.Package/Resources/BlackBerryMessager.bmp rename to src_vs2012/Package/Resources/Permissions/BlackBerryMessager.bmp diff --git a/src/VSNDK.Package/Resources/Calendar.bmp b/src_vs2012/Package/Resources/Permissions/Calendar.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Calendar.bmp rename to src_vs2012/Package/Resources/Permissions/Calendar.bmp diff --git a/src/VSNDK.Package/Resources/Camera.bmp b/src_vs2012/Package/Resources/Permissions/Camera.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Camera.bmp rename to src_vs2012/Package/Resources/Permissions/Camera.bmp diff --git a/src/VSNDK.Package/Resources/CaptureScreen.bmp b/src_vs2012/Package/Resources/Permissions/CaptureScreen.bmp similarity index 100% rename from src/VSNDK.Package/Resources/CaptureScreen.bmp rename to src_vs2012/Package/Resources/Permissions/CaptureScreen.bmp diff --git a/src/VSNDK.Package/Resources/Contacts.bmp b/src_vs2012/Package/Resources/Permissions/Contacts.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Contacts.bmp rename to src_vs2012/Package/Resources/Permissions/Contacts.bmp diff --git a/src/VSNDK.Package/Resources/DeviceIdentifyingInfo.bmp b/src_vs2012/Package/Resources/Permissions/DeviceIdentifyingInfo.bmp similarity index 100% rename from src/VSNDK.Package/Resources/DeviceIdentifyingInfo.bmp rename to src_vs2012/Package/Resources/Permissions/DeviceIdentifyingInfo.bmp diff --git a/src/VSNDK.Package/Resources/EmailPINMessages.bmp b/src_vs2012/Package/Resources/Permissions/EmailPINMessages.bmp similarity index 100% rename from src/VSNDK.Package/Resources/EmailPINMessages.bmp rename to src_vs2012/Package/Resources/Permissions/EmailPINMessages.bmp diff --git a/src/VSNDK.Package/Resources/GPSLocation.bmp b/src_vs2012/Package/Resources/Permissions/GPSLocation.bmp similarity index 100% rename from src/VSNDK.Package/Resources/GPSLocation.bmp rename to src_vs2012/Package/Resources/Permissions/GPSLocation.bmp diff --git a/src/VSNDK.Package/Resources/Gamepad.bmp b/src_vs2012/Package/Resources/Permissions/Gamepad.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Gamepad.bmp rename to src_vs2012/Package/Resources/Permissions/Gamepad.bmp diff --git a/src/VSNDK.Package/Resources/Internet.bmp b/src_vs2012/Package/Resources/Permissions/Internet.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Internet.bmp rename to src_vs2012/Package/Resources/Permissions/Internet.bmp diff --git a/src/VSNDK.Package/Resources/Location.bmp b/src_vs2012/Package/Resources/Permissions/Location.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Location.bmp rename to src_vs2012/Package/Resources/Permissions/Location.bmp diff --git a/src/VSNDK.Package/Resources/Mircrophone.bmp b/src_vs2012/Package/Resources/Permissions/Mircrophone.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Mircrophone.bmp rename to src_vs2012/Package/Resources/Permissions/Mircrophone.bmp diff --git a/src/VSNDK.Package/Resources/MyContactInfo.bmp b/src_vs2012/Package/Resources/Permissions/MyContactInfo.bmp similarity index 100% rename from src/VSNDK.Package/Resources/MyContactInfo.bmp rename to src_vs2012/Package/Resources/Permissions/MyContactInfo.bmp diff --git a/src/VSNDK.Package/Resources/Notebooks.bmp b/src_vs2012/Package/Resources/Permissions/Notebooks.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Notebooks.bmp rename to src_vs2012/Package/Resources/Permissions/Notebooks.bmp diff --git a/src/VSNDK.Package/Resources/Phone.bmp b/src_vs2012/Package/Resources/Permissions/Phone.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Phone.bmp rename to src_vs2012/Package/Resources/Permissions/Phone.bmp diff --git a/src/VSNDK.Package/Resources/PhoneControl.bmp b/src_vs2012/Package/Resources/Permissions/PhoneControl.bmp similarity index 100% rename from src/VSNDK.Package/Resources/PhoneControl.bmp rename to src_vs2012/Package/Resources/Permissions/PhoneControl.bmp diff --git a/src/VSNDK.Package/Resources/PostNotifications.bmp b/src_vs2012/Package/Resources/Permissions/PostNotifications.bmp similarity index 100% rename from src/VSNDK.Package/Resources/PostNotifications.bmp rename to src_vs2012/Package/Resources/Permissions/PostNotifications.bmp diff --git a/src/VSNDK.Package/Resources/Push.bmp b/src_vs2012/Package/Resources/Permissions/Push.bmp similarity index 100% rename from src/VSNDK.Package/Resources/Push.bmp rename to src_vs2012/Package/Resources/Permissions/Push.bmp diff --git a/src/VSNDK.Package/Resources/RunBackgrounded.bmp b/src_vs2012/Package/Resources/Permissions/RunBackgrounded.bmp similarity index 100% rename from src/VSNDK.Package/Resources/RunBackgrounded.bmp rename to src_vs2012/Package/Resources/Permissions/RunBackgrounded.bmp diff --git a/src/VSNDK.Package/Resources/SharedFiles.bmp b/src_vs2012/Package/Resources/Permissions/SharedFiles.bmp similarity index 100% rename from src/VSNDK.Package/Resources/SharedFiles.bmp rename to src_vs2012/Package/Resources/Permissions/SharedFiles.bmp diff --git a/src/VSNDK.Package/Resources/TextMessages.bmp b/src_vs2012/Package/Resources/Permissions/TextMessages.bmp similarity index 100% rename from src/VSNDK.Package/Resources/TextMessages.bmp rename to src_vs2012/Package/Resources/Permissions/TextMessages.bmp diff --git a/src_vs2012/Package/Resources/ReleaseNotes.txt b/src_vs2012/Package/Resources/ReleaseNotes.txt new file mode 100644 index 00000000..cfa6ffbe --- /dev/null +++ b/src_vs2012/Package/Resources/ReleaseNotes.txt @@ -0,0 +1,82 @@ +v3.3.1 (2015-01-14) +Changes in this version: + * small UI tweaks of project-import dialog + * fixed detection of MSBuild extensions on Windows XP + * fixed persistance of web-browser settings in Visual Studio 2010 + +v3.3.0 (2015-01-09) +Changes in this version: + * added basic QML colorizer (#29) + * fixed missing separator in makefile linker command + * fixed crash, when upgrading VC++ non-BlackBerry project + +v3.2.2 (2014-12-30) +Changes in this version: + * improved importing Momentics project: + - updates author info inside bar-descriptor.xml on the fly (#38) + - updates displayed project name on UI, when loaded another project + - avoids adding the same file several times into the project, when doing merge + - updating import-summary at runtime + - recognizes also additional-include-dirs from the original project + * added extra handlers to avoid Visual Studio crash, when lost connection to the device and trying to close used services + * small update to main project filters + * other small tweaks and refactorings + +v3.2.1 (2014-12-27) +Changes in this version: + * fixed loading process-list, when 5+ applications running simultaneously (#37) + +v3.2.0 (2014-12-25) +Changes in this version: + * .bar file editor is not default one for all XML files anymore! (#36) + * improved presentation of compilation errors (#35) to let Visual Studio jump into right place in source-code + * totally changed the way importing Momentics project works: + - loads original project name (#34) + - loads properties from manifest.properties too + - can check/uncheck/remove files by whole folders (#35) + - can specify custom list of defines (among the ones read from existing settings) + - can specify custom references to libraries + - detects the output location by parsing bar-descriptor.xml (using new MSBuild properties: $(TargetArchPre) / $(TargetArchPost) to build that path) + * added project-item template for new empty makefile + * added project template of Qt4 on PlayBook (experimental) + * fixed problem with launching slog2info on PlayBook (it's simply not supported there) + * other small tweaks and refactorings + +v3.1.0 (2014-12-09) +Changes in this version: + * introduced device logs capture feature (#32) + * added process launcher (on target device) + * updated Target Navigator + - exposing buttons to manage logs + - presenting command-line of running process + - presenting environment variables of running process + - small UI fixes (i.e. improper background in dark theme) + * suggesting download of BBNDK for VS, when not found + * other small tweaks and refactorings + +v3.0.4 (2014-11-27) +Changes in this version: + * improved first-launch experience (when nothing is configured and installed yet) + * avoiding new project wizard, when MSBuild 'BlackBerry' build platform is missing + +v3.0.3 (2014-11-26) +Changes in this version: + * improved stability, when no satellite components are installed (bbndk_vs, QNX tools, MSBuild extensions, Java) + * fixed missing [Download] button next to PlayBook NDK in API-Levels + * revisited project and project-item templates + * added default '_DEBUG' preprocessor definition into each new project + * enabled IntelliSense code-completion, while C++ coding + * respecting library references via properties of Cascades Application project + * fixed usage of precompiled header + * hidden GDB output in release builds + * more strictly following directory structure, when adding new files into a project, by producting expected sub-filters + * other small tweaks and refactorings + +v3.0.2 (2014-11-16) +Changes in this version: + * VSIX package verifies, if proper MSBuild 'BlackBerry' platform exists (#28) + * made GDB output-window shown in public releases + * fixed PlayBook QNX-tools selection + +v3.0.1 (2014-11-13) + * initial release of the plugin after 6 months of refactorings of original BlackBerry source-code and development of new features diff --git a/src_vs2012/Package/Resources/StartGuide.txt b/src_vs2012/Package/Resources/StartGuide.txt new file mode 100644 index 00000000..63c15545 --- /dev/null +++ b/src_vs2012/Package/Resources/StartGuide.txt @@ -0,0 +1,34 @@ +Start Guide +=========== + + Unless Momentics (or any previous version of this plugin) was used before, few extra +MANUAL steps have to be made before this package works smoothly without errors and warnings. + +1) Ensure BlackBerry Native SDK (NDK) is installed. It can be any available edition (distributed directly by + BlackBerry as MSI installer, or using Momentics, or as BBNDK_VS - compacted NDK skeleton - available as + separate part of this plugin at https://github.com/phofman/vs-plugin/releases/tag/v3.0.1-bbndk, allowing + downloads of new NDKs automatically), although the last option is preferred as it enables UI to manipulate + NDKs inside Visual Studio. + +2) Ensure MSBuild extensions (also distributed separately at https://github.com/phofman/vs-plugin/releases/latest) + has been copied into "C:\Program Files (x86)\MSBuild". + Without them it won't be possible to create new project, compile and deploy applications. + +In case of any problems, please visit the wiki pages at https://github.com/phofman/vs-plugin/wiki/Installation +or https://github.com/phofman/vs-plugin/wiki/ for general details and documentation. + + +Also note, that the plugin doesn't spy on you. It doesn't collect any usage statistics, nor send any crash-reports. +Then if you want anything fixed or imporved visit the project page at https://github.com/phofman/vs-plugin/. + + +Contact info +============ + + Paweł Hofman + CodeTitans.pl + Wroclaw, Poland + +Twitter: https://twitter.com/CodeTitans +Email: pawel@codetitans.pl + diff --git a/src_vs2012/Package/Resources/Template.Icons.resx b/src_vs2012/Package/Resources/Template.Icons.resx new file mode 100644 index 00000000..8fcbfb78 --- /dev/null +++ b/src_vs2012/Package/Resources/Template.Icons.resx @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + TemplateIcons\EmptyProj.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + templateicons\cascadesproj.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + templateicons\newitem.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + templateicons\newqitem.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/src_vs2012/Package/Resources/Template.Strings.resx b/src_vs2012/Package/Resources/Template.Strings.resx new file mode 100644 index 00000000..f456d11e --- /dev/null +++ b/src_vs2012/Package/Resources/Template.Strings.resx @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Native Core - Empty Project + + + Creates new C/C++ project with a BAR descriptor file only. No source code is provided. + + + NativeApp + + + Native Core - Screen Application + + + Creates C/C++ application using the minimum Core Native APIs to display a window on a screen. + + + ScreenApp + + + Cascades - Empty Application + + + Creates a basic 'Hello World' Cascades application that only loads a QML file. + + + CascadesProject + + + Native Core - OpenGL v1.1 + + + Creates a C/C++ application using OpenGL ES v1.1 and Core Native APIs. Includes code to add a window to the screen and render a trivial scene. + + + OpenGL11App + + + Native Core - OpenGL v2.0 + + + Creates a C/C++ application using OpenGL ES 2.0 and Core Native APIs. Includes code to add a window to the screen and render a trivial scene. + + + OpenGL2App + + + Native Core - Static Library + + + Creates a C/C++ static library + + + StaticLib + + + NativeCore - Shared Library + + + Creates a C/C++ shared library + + + SharedLib + + + Cascades - List View Application + + + Creates an application that uses a list-view + + + CascadesListViewApp + + + Cascades - Tabbed Pane Application + + + Creates an application that allows users to switch between tabs + + + CascadesTabsApp + + + Cascades - Navigation Pane Application + + + Creates an application that uses a navigation pane to display a details screen + + + CascadesNavigationApp + + + Cascades - Headless App + + + Creates a headless application consisting of a project for the UI component and a project for the background service + + + HeadlessApp + + + Cascades - Card Application + + + Creates a card application with a user UI component able to send a message to a UI card + + + CascadesCardApp + + + PlayBook - Qt4 Application (experimental) + + + Creates a Qt4 application with initial user UI. It requires PlayBook NDK 2.1+ installed for Qt headers and additional set of libraries downloaded and extracted manually into project's "QtLibs" folder. The ones distributed with the NDK somehow doesn't load properly on the device. + + + QtAppForPlayBook + + + BAR Descriptor + + + Adds a BAR descriptor file into the project + + + bar-descriptor.xml + + + QObject Class + + + Adds new class inheriting from QObject + + + Class.cpp + + + QML Control + + + Adds new QML file defining a custom control + + + Control.qml + + + QML Dialog + + + Adds new QML file defining an empty dialog + + + Dialog.qml + + + QML Page + + + Adds new QML file defining an empty page + + + Page.qml + + + QML Navigation Pane + + + Adds new QML file defining a custom navigation pane usage + + + NavigationPane.qml + + + QML Sheet + + + Adds new QML file defining an empty sheet + + + Sheet.qml + + + EGL Utility + + + Adds a basic code to manage EGL surface - initialize, swap buffers, render text and draw textures + + + bbutil.c + + + QML Tabbed Pane + + + Adds new QML file defining a custom tabbed pane usage + + + Tab.qml + + + makefile + + + Adds new empty makefile for custom build actions + + + makefile + + \ No newline at end of file diff --git a/src_vs2012/Package/Resources/TemplateIcons/CascadesProj.ico b/src_vs2012/Package/Resources/TemplateIcons/CascadesProj.ico new file mode 100644 index 00000000..c79e356e Binary files /dev/null and b/src_vs2012/Package/Resources/TemplateIcons/CascadesProj.ico differ diff --git a/src_vs2012/Package/Resources/TemplateIcons/EmptyProj.ico b/src_vs2012/Package/Resources/TemplateIcons/EmptyProj.ico new file mode 100644 index 00000000..b5980b86 Binary files /dev/null and b/src_vs2012/Package/Resources/TemplateIcons/EmptyProj.ico differ diff --git a/src_vs2012/Package/Resources/TemplateIcons/NewItem.ico b/src_vs2012/Package/Resources/TemplateIcons/NewItem.ico new file mode 100644 index 00000000..16dbff39 Binary files /dev/null and b/src_vs2012/Package/Resources/TemplateIcons/NewItem.ico differ diff --git a/src_vs2012/Package/Resources/TemplateIcons/NewQItem.ico b/src_vs2012/Package/Resources/TemplateIcons/NewQItem.ico new file mode 100644 index 00000000..a2842481 Binary files /dev/null and b/src_vs2012/Package/Resources/TemplateIcons/NewQItem.ico differ diff --git a/src_vs2012/Package/StandardCommands.cs b/src_vs2012/Package/StandardCommands.cs new file mode 100644 index 00000000..75fee10d --- /dev/null +++ b/src_vs2012/Package/StandardCommands.cs @@ -0,0 +1,39 @@ +//* Copyright 2010-2011 Research In Motion Limited. +//* +//* 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. + +namespace BlackBerry.Package +{ + /// + /// Command IDs exposed by VisualStudio. + /// + internal static class StandardCommands + { + public const int cmdidAddSolutionSCC = 21016; + public const int cmdidUndoCheckoutSCC = 21009; + public const int cmdidGetLatestVersionSCC = 21011; + public const int cmdidGetSCC = 21501; + public const int cmdidViewHistorySCC = 21508; + public const int cmdidStartDebug = 295; + public const int cmdidStartDebugContext = 356; + public const int cmdidRestartDebug = 296; + public const int cmdidStopDebug = 179; + public const int cmdidPreviewInBrowser = 334; + public const int cmdidBrowseWith = 336; + public const int cmdidStartNoDebug = 368; + public const int cmdidSolutionCfg = 684; + public const int cmdidSolutionPlatform = 1990; + public const int cmdidSolutionPlatformGetList = 1991; + public const int cmdidDebugBreakatFunction = 311; + } +} diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry.vsdir b/src_vs2012/Package/Templates/ProjectItems/BlackBerry.vsdir new file mode 100644 index 00000000..323ad6a7 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry.vsdir @@ -0,0 +1 @@ +BlackBerry| |BlackBerry Items|10 diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/items.vsdir b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/items.vsdir new file mode 100644 index 00000000..3ad3aa45 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/items.vsdir @@ -0,0 +1,7 @@ +qclass.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6010|10|#6011|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#9031|0|#6012 +qcontrol.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6020|23|#6021|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6023|0|#6022 +qdialog.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6030|24|#6031|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6023|0|#6032 +qpage.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6040|20|#6041|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6023|0|#6042 +qpane.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6050|21|#6051|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6023|0|#6052 +qsheet.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6060|25|#6061|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6023|0|#6062 +qtab.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6080|22|#6081|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6023|0|#6082 diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qclass.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qclass.vsz new file mode 100644 index 00000000..02fc426c --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qclass.vsz @@ -0,0 +1,5 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = QObject Child Class" +Param="FILE = Shared/qclass.cpp #> .cpp" +Param="FILE = Shared/qclass.hpp #> .hpp" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qcontrol.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qcontrol.vsz new file mode 100644 index 00000000..d915213a --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qcontrol.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = QML Container Definition" +Param="FILE = Shared/qcontrol.qml" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qdialog.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qdialog.vsz new file mode 100644 index 00000000..821773e7 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qdialog.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = QML Empty Dialog Definition" +Param="FILE = Shared/qdialog.qml" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qpage.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qpage.vsz new file mode 100644 index 00000000..fe782f2e --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qpage.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = QML Empty Page Definition" +Param="FILE = Shared/qpage.qml" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qpane.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qpane.vsz new file mode 100644 index 00000000..99b41ca5 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qpane.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = QML Simple NavigationPane Definition" +Param="FILE = Shared/qpane.qml" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qsheet.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qsheet.vsz new file mode 100644 index 00000000..5ce63ee8 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qsheet.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = QML Empty Sheet Definition" +Param="FILE = Shared/qsheet.qml" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qtab.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qtab.vsz new file mode 100644 index 00000000..0c9ffa81 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/Cascades/qtab.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = QML Simple TabbedPane Definition" +Param="FILE = Shared/qtab.qml" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/bar-descriptor.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/bar-descriptor.vsz new file mode 100644 index 00000000..2a4f4f14 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/bar-descriptor.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BAR descriptor" +Param="FILE = Shared/bar-descriptor.xml" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/bbutil.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/bbutil.vsz new file mode 100644 index 00000000..c60c4304 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/bbutil.vsz @@ -0,0 +1,5 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = bbutil Helper Class" +Param="FILE = Shared/Utils/bbutil.c #> .c" +Param="FILE = Shared/Utils/bbutil.h #> .h" diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/items.vsdir b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/items.vsdir new file mode 100644 index 00000000..256ce3bb --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/items.vsdir @@ -0,0 +1,4 @@ +Cascades| |Cascades|10 +bar-descriptor.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6000|20|#6001|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#9019|0|#6002 +bbutil.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6070|30|#6071|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#9032|0|#6072 +makefile.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#6090|40|#6091|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#9036|0|#6092 diff --git a/src_vs2012/Package/Templates/ProjectItems/BlackBerry/makefile.vsz b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/makefile.vsz new file mode 100644 index 00000000..79f57b43 --- /dev/null +++ b/src_vs2012/Package/Templates/ProjectItems/BlackBerry/makefile.vsz @@ -0,0 +1,4 @@ +VSWizard 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = Empty makefile" +Param="FILE = Shared/makefile-empty -> makefile" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry.vsdir b/src_vs2012/Package/Templates/Projects/BlackBerry.vsdir new file mode 100644 index 00000000..10bd2701 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry.vsdir @@ -0,0 +1 @@ +BlackBerry| |BlackBerry Projects|10 diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_card.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_card.vsz new file mode 100644 index 00000000..1749ed80 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_card.vsz @@ -0,0 +1,21 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Cascades Card Application" +Param="PROJECT = cascades-default.vcxproj" +Param="FILTERS = assets;config;src;trans" +Param="FILE = Shared/Assets/Card/bar-descriptor.xml -> bar-descriptor.xml" +Param="FILE = Shared/makefile-cascades -> makefile" +Param="FILE = Shared/Assets/Card/qmake.pro -> $ProjectName$.pro" +Param="FILE = Shared/qmake-config.pri -> config.pri" +Param="FILE = Shared/Translations/makefile-cascades -> translations/makefile" +Param="FILE = Shared/Translations/qmake-default.pro -> translations/$ProjectName$.pro" +Param="FILE = Shared/precompiled-cascades.h -> precompiled.h" +Param="FILE = Shared/Assets/Card/main.cpp -> src/main.cpp" +Param="FILE = Shared/Assets/Card/applicationui.cpp -> src/ApplicationUI.cpp" +Param="FILE = Shared/Assets/Card/applicationui.hpp -> src/ApplicationUI.hpp" +Param="FILE = Shared/Assets/Card/applicationuibase.cpp -> src/ApplicationUIBase.cpp" +Param="FILE = Shared/Assets/Card/applicationuibase.hpp -> src/ApplicationUIBase.hpp" +Param="FILE = Shared/Assets/Card/cardui.cpp -> src/CardUI.cpp" +Param="FILE = Shared/Assets/Card/cardui.hpp -> src/CardUI.hpp" +Param="FILE = * Shared/Assets/Card/main.qml -> assets/main.qml" +Param="FILE = * Shared/Assets/Card/card.qml -> assets/card.qml" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_headless.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_headless.vsz new file mode 100644 index 00000000..c1ececc0 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_headless.vsz @@ -0,0 +1,28 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Cascades Headless Application" +Param="PROJECT#1 = cascades-default.vcxproj -> $Name$/$Name$.vcxproj" +Param="FILTERS#1 = assets;config;src;trans" +Param="FILE#1 = Shared/Assets/Headless/bar-descriptor.xml -> bar-descriptor.xml" +Param="FILE#1 = Shared/makefile-cascades -> makefile" +Param="FILE#1 = Shared/Assets/Headless/qmake.pro -> $ProjectName$.pro" +Param="FILE#1 = Shared/qmake-config.pri -> config.pri" +Param="FILE#1 = Shared/Translations/makefile-cascades -> translations/makefile" +Param="FILE#1 = Shared/Translations/qmake-default.pro -> translations/$ProjectName$.pro" +Param="FILE#1 = Shared/precompiled-cascades.h -> precompiled.h" +Param="FILE#1 = Shared/main-cascades.cpp -> src/main.cpp" +Param="FILE#1 = * Shared/Assets/Headless/applicationui.cpp -> src/ApplicationUI.cpp" +Param="FILE#1 = Shared/Assets/Headless/applicationui.hpp -> src/ApplicationUI.hpp" +Param="FILE#1 = Shared/Assets/Headless/main.qml -> assets/main.qml" + +Param="PROJECT#2 = cascades-default.vcxproj -> $Name$Service/$Name$Service.vcxproj" +Param="FILTERS#2 = assets;config;src;trans" +Param="FILE#2 = Shared/makefile-cascades -> makefile" +Param="FILE#2 = Shared/Assets/Headless/qmake-service.pro -> $ProjectName$.pro" +Param="FILE#2 = Shared/qmake-config.pri -> config.pri" +Param="FILE#2 = Shared/Translations/makefile-cascades -> translations/makefile" +Param="FILE#2 = Shared/Translations/qmake-default.pro -> translations/$ProjectName$.pro" +Param="FILE#2 = Shared/precompiled-empty.h -> precompiled.h" +Param="FILE#2 = Shared/Assets/Headless/main-service.cpp -> main.cpp" +Param="FILE#2 = * Shared/Assets/Headless/service.cpp -> Service.cpp" +Param="FILE#2 = Shared/Assets/Headless/service.hpp -> Service.hpp" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_listview.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_listview.vsz new file mode 100644 index 00000000..cbc511f7 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_listview.vsz @@ -0,0 +1,18 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry ListView Cascades Application" +Param="PROJECT = cascades-default.vcxproj" +Param="FILTERS = assets;config;src;trans" +Param="FILE = Shared/bar-descriptor-cascades.xml -> bar-descriptor.xml" +Param="FILE = Shared/makefile-cascades -> makefile" +Param="FILE = Shared/Assets/ListView/qmake.pro -> $ProjectName$.pro" +Param="FILE = Shared/qmake-config.pri -> config.pri" +Param="FILE = Shared/Translations/makefile-cascades -> translations/makefile" +Param="FILE = Shared/Translations/qmake-default.pro -> translations/$ProjectName$.pro" +Param="FILE = Shared/precompiled-cascades.h -> precompiled.h" +Param="FILE = Shared/main-cascades.cpp -> src/main.cpp" +Param="FILE = Shared/applicationui.cpp -> src/ApplicationUI.cpp" +Param="FILE = Shared/applicationui.hpp -> src/ApplicationUI.hpp" +Param="FILE = * Shared/Assets/ListView/main.qml -> assets/main.qml" +Param="FILE = Shared/Assets/ListView/ItemPage.qml -> assets/ItemPage.qml" +Param="FILE = Shared/Assets/ListView/data.xml -> assets/data.xml" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_navigationpane.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_navigationpane.vsz new file mode 100644 index 00000000..a3aadb62 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_navigationpane.vsz @@ -0,0 +1,17 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Navigation Pane Cascades Application" +Param="PROJECT = cascades-default.vcxproj" +Param="FILTERS = assets;config;src;trans" +Param="FILE = Shared/bar-descriptor-cascades.xml -> bar-descriptor.xml" +Param="FILE = Shared/makefile-cascades -> makefile" +Param="FILE = Shared/qmake-default.pro -> $ProjectName$.pro" +Param="FILE = Shared/qmake-config.pri -> config.pri" +Param="FILE = Shared/Translations/makefile-cascades -> translations/makefile" +Param="FILE = Shared/Translations/qmake-default.pro -> translations/$ProjectName$.pro" +Param="FILE = Shared/precompiled-cascades.h -> precompiled.h" +Param="FILE = Shared/main-cascades.cpp -> src/main.cpp" +Param="FILE = Shared/applicationui.cpp -> src/ApplicationUI.cpp" +Param="FILE = Shared/applicationui.hpp -> src/ApplicationUI.hpp" +Param="FILE = * Shared/Assets/NavigationPane/main.qml -> assets/main.qml" +Param="FILE = Shared/Assets/NavigationPane/DetailsPage.qml -> assets/DetailsPage.qml" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_tabs.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_tabs.vsz new file mode 100644 index 00000000..129b4266 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/cascadesproj_tabs.vsz @@ -0,0 +1,16 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Tabbed Pane Cascades Application" +Param="PROJECT = cascades-default.vcxproj" +Param="FILTERS = assets;config;src;trans" +Param="FILE = Shared/bar-descriptor-cascades.xml -> bar-descriptor.xml" +Param="FILE = Shared/makefile-cascades -> makefile" +Param="FILE = Shared/qmake-default.pro -> $ProjectName$.pro" +Param="FILE = Shared/qmake-config.pri -> config.pri" +Param="FILE = Shared/Translations/makefile-cascades -> translations/makefile" +Param="FILE = Shared/Translations/qmake-default.pro -> translations/$ProjectName$.pro" +Param="FILE = Shared/precompiled-cascades.h -> precompiled.h" +Param="FILE = Shared/main-cascades.cpp -> src/main.cpp" +Param="FILE = Shared/applicationui.cpp -> src/ApplicationUI.cpp" +Param="FILE = Shared/applicationui.hpp -> src/ApplicationUI.hpp" +Param="FILE = * Shared/Assets/main-tabs.qml -> assets/main.qml" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/items.vsdir b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/items.vsdir new file mode 100644 index 00000000..bcab9c10 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Cascades/items.vsdir @@ -0,0 +1,6 @@ +..\CascadesProj.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5020|10|#5021|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5022 +CascadesProj_ListView.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5070|20|#5071|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5072 +CascadesProj_Tabs.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5080|30|#5081|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5082 +CascadesProj_NavigationPane.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5090|40|#5091|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5092 +CascadesProj_Headless.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5100|50|#5101|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5102 +CascadesProj_Card.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5110|60|#5111|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5112 diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/OpenGL/items.vsdir b/src_vs2012/Package/Templates/Projects/BlackBerry/OpenGL/items.vsdir new file mode 100644 index 00000000..4aec8675 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/OpenGL/items.vsdir @@ -0,0 +1,2 @@ +..\OpenGLProj1.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5030|10|#5031|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5032 +..\OpenGLProj2.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5040|20|#5041|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5042 diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Qt/items.vsdir b/src_vs2012/Package/Templates/Projects/BlackBerry/Qt/items.vsdir new file mode 100644 index 00000000..708e1fe6 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Qt/items.vsdir @@ -0,0 +1 @@ +qtproj_playbook.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5120|10|#5121|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5122 diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/Qt/qtproj_playbook.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/Qt/qtproj_playbook.vsz new file mode 100644 index 00000000..278a01f9 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/Qt/qtproj_playbook.vsz @@ -0,0 +1,11 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Qt4 for PlayBook Application" +Param="PROJECT = native-default.vcxproj" +Param="FILTERS = assets;config;src;trans" +Param="DEFINE = QT_BOOTSTRAPPED" +Param="DEPENDENCY = QtCore;QtGui;QtOpenGL" +Param="DEPENDENCY-DIR = $(QNX_TARGET)\$(CPUVARDIR)\usr\lib\qt4\lib" +Param="FILE = Shared/Assets/QtPlayBook/bar-descriptor.xml -> bar-descriptor.xml" +Param="FILE = Shared/Assets/QtPlayBook/main.cpp -> src/main.cpp" +Param="FILE = * Shared/Assets/QtPlayBook/README.txt -> README.txt" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/cascadesproj.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/cascadesproj.vsz new file mode 100644 index 00000000..12816949 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/cascadesproj.vsz @@ -0,0 +1,16 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Hello-World Cascades Application" +Param="PROJECT = cascades-default.vcxproj" +Param="FILTERS = assets;config;src;trans" +Param="FILE = Shared/bar-descriptor-cascades.xml -> bar-descriptor.xml" +Param="FILE = Shared/makefile-cascades -> makefile" +Param="FILE = Shared/qmake-default.pro -> $ProjectName$.pro" +Param="FILE = Shared/qmake-config.pri -> config.pri" +Param="FILE = ! Shared/Translations/makefile-cascades -> translations/makefile" +Param="FILE = ! Shared/Translations/qmake-default.pro -> translations/$ProjectName$.pro" +Param="FILE = Shared/precompiled-cascades.h -> precompiled.h" +Param="FILE = Shared/main-cascades.cpp -> src/main.cpp" +Param="FILE = Shared/applicationui.cpp -> src/ApplicationUI.cpp" +Param="FILE = Shared/applicationui.hpp -> src/ApplicationUI.hpp" +Param="FILE = * Shared/Assets/main-helloworld.qml -> assets/main.qml" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/emptyproj.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/emptyproj.vsz new file mode 100644 index 00000000..3c6abf03 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/emptyproj.vsz @@ -0,0 +1,8 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Empty Native Core Application" +Param="PROJECT = native-default.vcxproj" +Param="FILTERS = assets;config;src" +Param="FILE = Shared/bar-descriptor.xml" +Param="FILE = * Shared/main-empty.c -> src/main.c" + diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/items.vsdir b/src_vs2012/Package/Templates/Projects/BlackBerry/items.vsdir new file mode 100644 index 00000000..04c9aacb --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/items.vsdir @@ -0,0 +1,10 @@ +Cascades| |Cascades|10 +OpenGL| |OpenGL|30 +Qt| |Qt|20 +EmptyProj.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5000|10|#5001|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5002 +ScreenProj.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5010|30|#5011|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5012 +CascadesProj.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5020|20|#5021|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5013|0|#5022 +OpenGLProj1.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5030|40|#5031|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5032 +OpenGLProj2.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5040|50|#5041|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5042 +LibStaticProj.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5050|60|#5051|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5052 +LibSharedProj.vsz|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5060|70|#5061|{db9f9c5f-fb27-4297-ab44-fa8774e962ca}|#5003|0|#5062 diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/libsharedproj.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/libsharedproj.vsz new file mode 100644 index 00000000..7c185fd5 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/libsharedproj.vsz @@ -0,0 +1,5 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Empty Native Core Shared Library" +Param="PROJECT = native-libshared-default.vcxproj" +Param="FILTERS = config;src" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/libstaticproj.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/libstaticproj.vsz new file mode 100644 index 00000000..e16f04bb --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/libstaticproj.vsz @@ -0,0 +1,5 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Empty Native Core Static Library" +Param="PROJECT = native-libstatic-default.vcxproj" +Param="FILTERS = config;src" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/openglproj1.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/openglproj1.vsz new file mode 100644 index 00000000..61554368 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/openglproj1.vsz @@ -0,0 +1,11 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Empty OpenGL 1.1 Project" +Param="PROJECT = opengl-default.vcxproj" +Param="FILTERS = assets;config;src" +Param="DEPENDENCY = bps;screen;EGL;GLESv1_CM;freetype;png;m" +Param="DEFINE = USING_GL11" +Param="FILE = Shared/bar-descriptor.xml" +Param="FILE = * Shared/main-opengl1.c -> src/main.c" +Param="FILE = Shared/Utils/bbutil.c -> src/bbutil.c" +Param="FILE = Shared/Utils/bbutil.h -> src/bbutil.h" diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/openglproj2.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/openglproj2.vsz new file mode 100644 index 00000000..a2815965 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/openglproj2.vsz @@ -0,0 +1,12 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Empty OpenGL 2.0 Project" +Param="PROJECT = opengl-default.vcxproj" +Param="FILTERS = assets;config;src" +Param="DEPENDENCY = bps;screen;EGL;GLESv2;freetype;png;m" +Param="DEFINE = USING_GL20" +Param="FILE = Shared/bar-descriptor.xml" +Param="FILE = * Shared/main-opengl2.c -> src/main.c" +Param="FILE = Shared/Utils/bbutil.c -> src/bbutil.c" +Param="FILE = Shared/Utils/bbutil.h -> src/bbutil.h" + diff --git a/src_vs2012/Package/Templates/Projects/BlackBerry/screenproj.vsz b/src_vs2012/Package/Templates/Projects/BlackBerry/screenproj.vsz new file mode 100644 index 00000000..9eabab04 --- /dev/null +++ b/src_vs2012/Package/Templates/Projects/BlackBerry/screenproj.vsz @@ -0,0 +1,9 @@ +VSWIZARD 7.0 +Wizard={0cb934ba-06c8-4919-9498-bc6517940bcd} +Param="TITLE = BlackBerry Empty Native Core Application with Screen API" +Param="PROJECT = native-default.vcxproj" +Param="FILTERS = assets;config;src" +Param="DEPENDENCY = bps;screen;m" +Param="FILE = Shared/bar-descriptor.xml" +Param="FILE = * Shared/main-screen.c -> src/main.c" + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationui.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationui.cpp new file mode 100644 index 00000000..5505d3b0 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationui.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include + +#include "ApplicationUI.hpp" + +using namespace bb::cascades; +using namespace bb::system; + +ApplicationUI::ApplicationUI(InvokeManager *invokeManager) + : ApplicationUIBase(invokeManager) +{ + bool res = connect(m_pInvokeManager, SIGNAL(childCardDone(const bb::system::CardDoneMessage&)), this, SLOT(cardDone(const bb::system::CardDoneMessage&))); + Q_ASSERT(res); + + // Since the variable is not used in the app, this is added to avoid a + // compiler warning + Q_UNUSED(res); + + // Create scene document from main.qml asset, the parent is set + // to ensure the document gets destroyed properly at shut down. + QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this); + // Make app UI available to the qml. + qml->setContextProperty("app", this); + + // Create root object for the UI + AbstractPane *root = qml->createRootObject(); + + // Set created root object as the application scene + Application::instance()->setScene(root); +} + +void ApplicationUI::invokeCard(const QString &memo) +{ + InvokeRequest cardRequest; + cardRequest.setTarget("com.$AuthorSafe$.$ProjectName$"); + cardRequest.setAction("bb.action.VIEW"); + cardRequest.setMimeType("application/text"); + cardRequest.setData(memo.toUtf8()); + m_pInvokeManager->invoke(cardRequest); +} + +void ApplicationUI::cardDone(const bb::system::CardDoneMessage &doneMessage) +{ + qDebug() << "cardDone: " << doneMessage.reason(); +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationui.hpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationui.hpp new file mode 100644 index 00000000..a5130fdd --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationui.hpp @@ -0,0 +1,34 @@ +#ifndef __APPLICATIONUI_HPP__ +#define __APPLICATIONUI_HPP__ + +#include "ApplicationUIBase.hpp" + +namespace bb +{ + namespace system + { + class CardDoneMessage; + } +} + +/*! + * @brief Application UI object + * + * Use this object to create and init app UI, to create context objects, to register the new meta types etc. + */ +class ApplicationUI: public ApplicationUIBase +{ + Q_OBJECT + +public: + ApplicationUI(bb::system::InvokeManager* invokeManager); + virtual ~ApplicationUI() {} + +public: + Q_INVOKABLE void invokeCard(const QString &memo); + +private slots: + void cardDone(const bb::system::CardDoneMessage& doneMessage); +}; + +#endif /* __APPLICATIONUI_HPP__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationuibase.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationuibase.cpp new file mode 100644 index 00000000..e49cf168 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationuibase.cpp @@ -0,0 +1,41 @@ +#include +#include + +#include "ApplicationUIBase.hpp" + +using namespace bb::cascades; +using namespace bb::system; + +ApplicationUIBase::ApplicationUIBase(InvokeManager *invokeManager) + : m_pInvokeManager(invokeManager) +{ + m_translator = new QTranslator(this); + m_pLocaleHandler = new LocaleHandler(this); + + connect(m_pLocaleHandler, SIGNAL(systemLanguageChanged()), this, SLOT(onSystemLanguageChanged())); + + // initial load + onSystemLanguageChanged(); +} + +ApplicationUIBase::~ApplicationUIBase() +{ + // TODO Auto-generated destructor stub +} + +void ApplicationUIBase::onSystemLanguageChanged() +{ + QCoreApplication::instance()->removeTranslator(m_translator); + + // Initiate, load and install the application translation files. + QString locale_string = QLocale().name(); + QString file_name = QString("$ProjectName$_%1").arg(locale_string); + if (m_translator->load(file_name, "app/native/qm")) + { + QCoreApplication::instance()->installTranslator(m_translator); + } + else + { + qWarning() << tr("cannot load language file '%1").arg(file_name); + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationuibase.hpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationuibase.hpp new file mode 100644 index 00000000..6f918c3a --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/applicationuibase.hpp @@ -0,0 +1,39 @@ +#ifndef __APPLICATIONUIBASE_HPP__ +#define __APPLICATIONUIBASE_HPP__ + +#include + +namespace bb +{ + namespace system + { + class InvokeManager; + } + namespace cascades + { + class LocaleHandler; + } +} + +class QTranslator; + +class ApplicationUIBase : public QObject +{ + Q_OBJECT + +public: + ApplicationUIBase(bb::system::InvokeManager* invokeManager); + virtual ~ApplicationUIBase(); + +private slots: + void onSystemLanguageChanged(); + +protected: + bb::system::InvokeManager* m_pInvokeManager; + +private: + QTranslator* m_translator; + bb::cascades::LocaleHandler* m_pLocaleHandler; +}; + +#endif /* __APPLICATIONUIBASE_HPP__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/bar-descriptor.xml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/bar-descriptor.xml new file mode 100644 index 00000000..7910427a --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/bar-descriptor.xml @@ -0,0 +1,95 @@ + + + + + + + com.$AuthorSafe$.$ProjectName$ + + + $ProjectName$ + + + 1.0.0 + + + 1 + + + The $ProjectName$ application + + + + + + $Author$ + + + $AuthorID$ + + + true + none + false + + + + core.games + + armle-v7 + $ProjectName$ + + + armle-v7 + Qnx/Cascades + $ProjectName$.so + + + x86 + $ProjectName$ + + + + $ProjectName$ + + + + + + + assets + + + + + + + + + + run_native + + + + + + + card.previewer + $ProjectName$ + $ProjectName$ + + bb.action.VIEW + application/text + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/card.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/card.qml new file mode 100644 index 00000000..6e171623 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/card.qml @@ -0,0 +1,27 @@ +import bb.cascades $CascadesVersion$ + +NavigationPane { + peekEnabled: true + + Page { + Container { + Label { + // Localized text with the dynamic translation and locale updates support + text: qsTr("card received memo:") + Retranslate.onLocaleOrLanguageChanged + } + Label { + id: label + text: "---" + } + } + } + + function setMemo(new_memo) + { + label.text = new_memo; + } + + onCreationCompleted: { + card.memoChanged.connect(setMemo); + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/cardui.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/cardui.cpp new file mode 100644 index 00000000..b30fda79 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/cardui.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +#include "CardUI.hpp" + +using namespace bb::cascades; +using namespace bb::system; + +CardUI::CardUI(bb::system::InvokeManager* invokeManager) + : ApplicationUIBase(invokeManager) +{ + // Create scene document from main.qml asset, the parent is set + // to ensure the document gets destroyed properly at shut down. + QmlDocument *qml = QmlDocument::create("asset:///card.qml").parent(this); + + // Make C++ UI part available to the qml. + qml->setContextProperty("card", this); + + // Create root object for the UI + AbstractPane *root = qml->createRootObject(); + if (root) + { + // Connect to the "invoked" signal to receive invocations + connect(m_pInvokeManager, SIGNAL(invoked(const bb::system::InvokeRequest&)), this, SLOT(onInvoked(const bb::system::InvokeRequest&))); + + // Connect to the "cardPooled" signal to received notifications when the card is placed in the pool + connect(m_pInvokeManager, SIGNAL(cardPooled(const bb::system::CardDoneMessage&)), this, SLOT(cardPooled(const bb::system::CardDoneMessage&))); + + // Set created root object as the application scene + Application::instance()->setScene(root); + } +} + +void CardUI::cardPooled(const bb::system::CardDoneMessage& doneMessage) +{ + // Card is no longer being shown and has been pooled + // The card process is still running, but has been pooled so that future invocations are optimized. + // Therefore, when the card receives this signal, it must reset its state so that it is ready + // to be invoked cleanly again. For example, for a composer, any input should be discarded. + qDebug() << "cardPooled: " << doneMessage.reason(); + + // TODO: Clean-up and release any resource the card might have used. +} + +void CardUI::onInvoked(const bb::system::InvokeRequest& request) +{ + qDebug() << "onInvoked request:"; + + bb::system::InvokeSource source = request.source(); + QString memo = QString::fromUtf8(request.data()); + + qDebug() << "Source: (" << source.groupId() << "," << source.installId() << ")"; + qDebug() << "Target:" << request.target(); + qDebug() << "Action:" << request.action(); + qDebug() << "Mime:" << request.mimeType(); + qDebug() << "Url:" << request.uri(); + qDebug() << "Data:" << memo; + + emit memoChanged(memo); +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/cardui.hpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/cardui.hpp new file mode 100644 index 00000000..93631a6d --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/cardui.hpp @@ -0,0 +1,32 @@ +#ifndef __CARDUI_HPP__ +#define __CARDUI_HPP__ + +#include + +#include "ApplicationUIBase.hpp" + + +namespace bb { + namespace system { + class InvokeManager; + class InvokeRequest; + } +} + +class CardUI: public ApplicationUIBase +{ + Q_OBJECT + +public: + CardUI(bb::system::InvokeManager* invokeManager); + virtual ~CardUI() {} + +signals: + void memoChanged(const QString &memo); + +private slots: + void onInvoked(const bb::system::InvokeRequest& request); + void cardPooled(const bb::system::CardDoneMessage& doneMessage); +}; + +#endif /* __CARDUI_HPP__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/main.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/main.cpp new file mode 100644 index 00000000..53bbf4a4 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/main.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +#include + +#include "ApplicationUI.hpp" +#include "CardUI.hpp" + +using namespace bb::cascades; +using namespace bb::system; + +#if _DEBUG +/** + * Redirect all Cascades logs on standard console. + */ +static void WriteLogsToConsole(QtMsgType type, const char *message) +{ + Q_UNUSED(type); + std::fprintf(stdout, "%s\n", message); + std::fflush(stdout); +} +#endif /* _DEBUG */ + + +/** + * Cascades Application Entry Point + */ +Q_DECL_EXPORT int main(int argc, char **argv) +{ + Application app(argc, argv); + + InvokeManager invokeManager; + +#if _DEBUG + qInstallMsgHandler(WriteLogsToConsole); +#endif /* _DEBUG */ + + QObject *appui = 0; + if (invokeManager.startupMode() == ApplicationStartupMode::InvokeCard) + { + // Create the Card UI object + appui = new CardUI(&invokeManager); + } + else + { + // Create the Application UI object, this is where the main.qml file + // is loaded and the application scene is set. + appui = new ApplicationUI(&invokeManager); + } + + // Enter the application main event loop. + int ret = Application::exec(); + + invokeManager.closeChildCard(); + delete appui; + + return ret; +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/main.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/main.qml new file mode 100644 index 00000000..ab08138e --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/main.qml @@ -0,0 +1,21 @@ +import bb.cascades $CascadesVersion$ + +Page { + Container { + Label { + // Localized text with the dynamic translation and locale updates support + text: qsTr("Send memo to card") + Retranslate.onLocaleOrLanguageChanged + textStyle.base: SystemDefaults.TextStyles.BigText + } + TextField { + id: tf + text: "Hello ..." + } + Button { + text: "Send & reveal card" + onClicked: { + app.invokeCard(tf.text); + } + } + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/qmake.pro b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/qmake.pro new file mode 100644 index 00000000..2d56dbe1 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Card/qmake.pro @@ -0,0 +1,6 @@ +APP_NAME = $ProjectName$ + +CONFIG += qt warn_on cascades10 +LIBS += -lbb -lbbsystem + +include(config.pri) diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/applicationui.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/applicationui.cpp new file mode 100644 index 00000000..deed77a5 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/applicationui.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +#include "ApplicationUI.hpp" + +using namespace bb::cascades; +using namespace bb::system; + +ApplicationUI::ApplicationUI() + : QObject(), m_translator(new QTranslator(this)), m_localeHandler(new LocaleHandler(this)), m_invokeManager(new InvokeManager(this)) +{ + // prepare the localization + if (!QObject::connect(m_localeHandler, SIGNAL(systemLanguageChanged()), this, SLOT(onSystemLanguageChanged()))) + { + // This is an abnormal situation! Something went wrong! + // Add own code to recover here + qWarning() << "Recovering from a failed connect()"; + } + + // initial load + onSystemLanguageChanged(); + + // Create scene document from main.qml asset, the parent is set + // to ensure the document gets destroyed properly at shut down. + QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this); + + // Make app available to the qml. + qml->setContextProperty("app", this); + + // Create root object for the UI + AbstractPane *root = qml->createRootObject(); + + // Set created root object as the application scene + Application::instance()->setScene(root); +} + +void ApplicationUI::onSystemLanguageChanged() +{ + QCoreApplication::instance()->removeTranslator(m_translator); + // Initiate, load and install the application translation files. + QString locale_string = QLocale().name(); + QString file_name = QString("$ProjectName$_%1").arg(locale_string); + if (m_translator->load(file_name, "app/native/qm")) + { + QCoreApplication::instance()->installTranslator(m_translator); + } +} + +void ApplicationUI::resendNotification() +{ + InvokeRequest request; + request.setTarget("com.$AuthorSafe$.$ProjectName$Service"); + request.setAction("com.$AuthorSafe$.$ProjectName$Service.RESET"); + m_invokeManager->invoke(request); + Application::instance()->minimize(); +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/applicationui.hpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/applicationui.hpp new file mode 100644 index 00000000..eaadc1ef --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/applicationui.hpp @@ -0,0 +1,44 @@ +#ifndef __APPLICATIONUI_HPP__ +#define __APPLICATIONUI_HPP__ + +#include + +namespace bb +{ + namespace cascades + { + class LocaleHandler; + } + namespace system + { + class InvokeManager; + } +} + +class QTranslator; + +/*! + * @brief Application UI object + * + * Use this object to create and init app UI, to create context objects, to register the new meta types etc. + */ +class ApplicationUI: public QObject +{ + Q_OBJECT + +public: + ApplicationUI(); + virtual ~ApplicationUI() { } + + Q_INVOKABLE void resendNotification(); + +private slots: + void onSystemLanguageChanged(); + +private: + QTranslator* m_translator; + bb::cascades::LocaleHandler* m_localeHandler; + bb::system::InvokeManager* m_invokeManager; +}; + +#endif /* __APPLICATIONUI_HPP__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/bar-descriptor.xml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/bar-descriptor.xml new file mode 100644 index 00000000..66a2193a --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/bar-descriptor.xml @@ -0,0 +1,127 @@ + + + + + + + com.$AuthorSafe$.$ProjectName$ + + + $ProjectName$ + + + 1.0.0 + 10.2.0 + + + 1 + + + The $ProjectName$ application + + + + + + $Author$ + + + $AuthorID$ + + + true + none + false + + + + core.games + + armle-v7 + Qnx/Elf + $ProjectName$ + $ProjectName$Service + + + armle-v7 + Qnx/Cascades + $ProjectName$.so + $ProjectName$Service + + + x86 + Qnx/Elf + $ProjectName$ + $ProjectName$Service + + + + $ProjectName$ + + + + $ProjectName$ Service + Qnx/Elf + + _sys_run_headless + _sys_headless_nostop + + + + + + + assets + + + + + + + + + + run_native + + post_notification + + + + + + + application.headless + $ProjectName$ Service + $ProjectName$Service + + bb.action.system.STARTED + application/vnd.blackberry.system.event.STARTED + + + + com.$AuthorSafe$.$ProjectName$Service.RESET + * + + + + + + application + $ProjectName$ + + $ProjectName$ + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/main-service.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/main-service.cpp new file mode 100644 index 00000000..fef3e8f3 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/main-service.cpp @@ -0,0 +1,17 @@ +#include + +#include "Service.hpp" + +using namespace bb; + +int main(int argc, char **argv) +{ + Application app(argc, argv); + + // Create the Application UI object, this is where the main.qml file + // is loaded and the application scene is set. + Service srv; + + // Enter the application main event loop. + return Application::exec(); +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/main.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/main.qml new file mode 100644 index 00000000..2b03dcb3 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/main.qml @@ -0,0 +1,16 @@ +import bb.cascades $CascadesVersion$ + +Page { + Container { + Label { + // Localized text with the dynamic translation and locale updates support + text: qsTr("$ProjectName$ Service says Hello!") + Retranslate.onLocaleOrLanguageChanged + } + Button { + text: qsTr("Resend Notification") + Retranslate.onLocaleOrLanguageChanged + onClicked: { + app.resendNotification(); + } + } + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/qmake-service.pro b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/qmake-service.pro new file mode 100644 index 00000000..b9311957 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/qmake-service.pro @@ -0,0 +1,6 @@ +APP_NAME = $ProjectName$ + +CONFIG += qt warn_on +LIBS += -lbb -lbbsystem -lbbplatform + +include(config.pri) diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/qmake.pro b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/qmake.pro new file mode 100644 index 00000000..2d56dbe1 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/qmake.pro @@ -0,0 +1,6 @@ +APP_NAME = $ProjectName$ + +CONFIG += qt warn_on cascades10 +LIBS += -lbb -lbbsystem + +include(config.pri) diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/service.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/service.cpp new file mode 100644 index 00000000..96bd9dce --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/service.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +#include + +#include "Service.hpp" + +using namespace bb::platform; +using namespace bb::system; + +Service::Service() + : QObject(), m_notify(new Notification(this)), m_invokeManager(new InvokeManager(this)) +{ + m_invokeManager->connect(m_invokeManager, SIGNAL(invoked(const bb::system::InvokeRequest&)), this, SLOT(handleInvoke(const bb::system::InvokeRequest&))); + + NotificationDefaultApplicationSettings settings; + settings.setPreview(NotificationPriorityPolicy::Allow); + settings.apply(); + + m_notify->setTitle("$MasterProjectName$ Service"); + m_notify->setBody("$MasterProjectName$ service requires attention"); + + bb::system::InvokeRequest request; + request.setTarget("com.$AuthorSafe$.$ProjectName$"); + request.setAction("bb.action.START"); + m_notify->setInvokeRequest(request); + + onTimeout(); +} + +void Service::handleInvoke(const bb::system::InvokeRequest & request) +{ + if (request.action().compare("com.$AuthorSafe$.$ProjectName$.RESET") == 0) { + triggerNotification(); + } +} + +void Service::triggerNotification() +{ + // Timeout is to give time for UI to minimize + QTimer::singleShot(2000, this, SLOT(onTimeout())); +} + +void Service::onTimeout() +{ + Notification::clearEffectsForAll(); + Notification::deleteAllFromInbox(); + m_notify->notify(); +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/service.hpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/service.hpp new file mode 100644 index 00000000..9a7477f7 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/Headless/service.hpp @@ -0,0 +1,39 @@ +#ifndef __SERVICE_HPP__ +#define __SERVICE_HPP__ + +#include + +namespace bb +{ + class Application; + namespace platform + { + class Notification; + } + namespace system + { + class InvokeManager; + class InvokeRequest; + } +} + +class Service : public QObject +{ + Q_OBJECT + +public: + Service(); + virtual ~Service() {} + +private slots: + void handleInvoke(const bb::system::InvokeRequest &); + void onTimeout(); + +private: + void triggerNotification(); + + bb::platform::Notification * m_notify; + bb::system::InvokeManager * m_invokeManager; +}; + +#endif /* __SERVICE_HPP__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/ItemPage.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/ItemPage.qml new file mode 100644 index 00000000..e18080e2 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/ItemPage.qml @@ -0,0 +1,11 @@ +import bb.cascades $CascadesVersion$ + +Page { + property alias itemPageTitle: titlebar.title + titleBar: TitleBar { + id: titlebar + } + + Container { + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/data.xml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/data.xml new file mode 100644 index 00000000..816385f7 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/data.xml @@ -0,0 +1,19 @@ + +
+ + + + + +
+
+ + + + + + + + +
+
\ No newline at end of file diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/main.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/main.qml new file mode 100644 index 00000000..c12e7a11 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/main.qml @@ -0,0 +1,35 @@ +import bb.cascades $CascadesVersion$ + +NavigationPane { + id: nav + Page { + Container { + ListView { + dataModel: XmlDataModel { + source: "data.xml" + } + onTriggered: { + + if (indexPath.length > 1) { + var chosenItem = dataModel.data(indexPath); + var contentpage = itemPageDefinition.createObject(); + + contentpage.itemPageTitle = chosenItem.name + nav.push(contentpage); + } + } + accessibility.name: "Listing" + } + } + } + + attachedObjects: [ + ComponentDefinition { + id: itemPageDefinition + source: "ItemPage.qml" + } + ] + onPopTransitionEnded: { + page.destroy(); + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/qmake.pro b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/qmake.pro new file mode 100644 index 00000000..afb43f44 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/ListView/qmake.pro @@ -0,0 +1,6 @@ +APP_NAME = $ProjectName$ + +CONFIG += qt warn_on cascades10 +LIBS += -lbbdata + +include(config.pri) diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/NavigationPane/DetailsPage.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/NavigationPane/DetailsPage.qml new file mode 100644 index 00000000..62724fce --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/NavigationPane/DetailsPage.qml @@ -0,0 +1,10 @@ +import bb.cascades $CascadesVersion$ + +Page { + titleBar: TitleBar { + // Localized text with the dynamic translation and locale updates support + title: qsTr("Second Page") + Retranslate.onLocaleOrLanguageChanged + } + Container { + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/NavigationPane/main.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/NavigationPane/main.qml new file mode 100644 index 00000000..1cc4de5a --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/NavigationPane/main.qml @@ -0,0 +1,38 @@ +import bb.cascades $CascadesVersion$ + +NavigationPane { + id: navigationPane + + Page { + titleBar: TitleBar { + // Localized text with the dynamic translation and locale updates support + title: qsTr("Page 1") + Retranslate.onLocaleOrLanguageChanged + } + + Container { + } + + actions: ActionItem { + title: qsTr("Second page") + Retranslate.onLocaleOrLanguageChanged + ActionBar.placement: ActionBarPlacement.OnBar + + onTriggered: { + // A second Page is created and pushed when this action is triggered. + navigationPane.push(secondPageDefinition.createObject()); + } + } + } + + attachedObjects: [ + // Definition of the second Page, used to dynamically create the Page above. + ComponentDefinition { + id: secondPageDefinition + source: "DetailsPage.qml" + } + ] + + onPopTransitionEnded: { + // Destroy the popped Page once the back transition has ended. + page.destroy(); + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/README.txt b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/README.txt new file mode 100644 index 00000000..694fc617 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/README.txt @@ -0,0 +1,12 @@ + +This is a prototype of Qt4 application running on PlayBook and BB10 devices. + +Starting from NDK 2.1+ and continuing in NDK 10.0+ BlackBerry delivers compiled set of Qt libraries +and matching headers. Unfortunately those libraries don't load at all on the device. + +Please download custom build of Qt binaries from https://github.com/phofman/vs-plugin/releases +and extract it into the "QtLibs" folder inside the project. Otherwise deployment will fail. +That location can be changed directly inside bar-descriptor.xml. + +Yet still, for compilation purposes the ones delivered by BlackBerry are sufficient. + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/bar-descriptor.xml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/bar-descriptor.xml new file mode 100644 index 00000000..f393a5cb --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/bar-descriptor.xml @@ -0,0 +1,84 @@ + + + + + + + com.$AuthorSafe$.$ProjectName$ + + + $ProjectName$ + + + 1.0.0 + + + 1 + + + The $ProjectName$ application + + + + + + $Author$ + + + $AuthorID$ + + + none + false + + + + core.games + + armle-v7 + $ProjectName$ + lib/libQtCore.so.4 + lib/libQtGui.so.4 + lib/libQtOpenGL.so.4 + lib/platforms/libblackberry.so + + + armle-v7 + $ProjectName$ + lib/libQtCore.so.4 + lib/libQtGui.so.4 + lib/libQtOpenGL.so.4 + lib/platforms/libblackberry.so + + + x86 + $ProjectName$ + lib/libQtCore.so.4 + lib/libQtGui.so.4 + lib/libQtOpenGL.so.4 + lib/platforms/libblackberry.so + + + + + + + + + run_native + + + + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/main.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/main.cpp new file mode 100644 index 00000000..c8bb3a6d --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/QtPlayBook/main.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + + +/** + * Get int value from environment variable. + */ +static int GetEnvInt(const char *name, int defaultValue) +{ + const char *value = getenv(name); + return value != NULL ? atoi(value) : defaultValue; +} + +/** + * Application Entry Point. + */ +int main(int argc, char** argv) +{ + QCoreApplication::addLibraryPath("app/native/lib"); + QApplication app(argc, argv); + QWidget window; + + // get screen resolution: + int width = GetEnvInt("WIDTH", 1024); + int height = GetEnvInt("HEIGHT", 600); + + window.resize(width, height); + window.setStyleSheet("background-color:blue;"); + + QPushButton quitButton("Quit now!", &window); + QObject::connect(&quitButton, SIGNAL(clicked()), &app, SLOT(quit())); + quitButton.setStyleSheet("background-color:red;"); + quitButton.setGeometry((width - 200) / 2, (height - 50) / 2, 200, 50); + + window.show(); + return app.exec(); +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/main-helloworld.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/main-helloworld.qml new file mode 100644 index 00000000..5c1f847f --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/main-helloworld.qml @@ -0,0 +1,11 @@ +import bb.cascades $CascadesVersion$ + +Page { + Container { + Label { + // Localized text with the dynamic translation and locale updates support + text: qsTr("Hello World") + Retranslate.onLocaleOrLanguageChanged + textStyle.base: SystemDefaults.TextStyles.BigText + } + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/main-tabs.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/main-tabs.qml new file mode 100644 index 00000000..a68d7313 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Assets/main-tabs.qml @@ -0,0 +1,29 @@ +import bb.cascades $CascadesVersion$ + +TabbedPane { + showTabsOnActionBar: true + Tab { + //First tab + // Localized text with the dynamic translation and locale updates support + title: qsTr("Tab 1") + Retranslate.onLocaleOrLanguageChanged + Page { + Container { + Label { + text: qsTr("First tab") + Retranslate.onLocaleOrLanguageChanged + } + } + } + } + + Tab { + //Second tab + title: qsTr("Tab 2") + Retranslate.onLocaleOrLanguageChanged + Page { + Container { + Label { + text: qsTr("Second tab") + Retranslate.onLocaleOrLanguageChanged + } + } + } + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Translations/makefile-cascades b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Translations/makefile-cascades new file mode 100644 index 00000000..bcdaca0b --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Translations/makefile-cascades @@ -0,0 +1,12 @@ +QMAKE_TARGET = $ProjectName$ +LUPDATE = $(QNX_HOST)/usr/bin/lupdate +LRELEASE = $(QNX_HOST)/usr/bin/lrelease + +update: $(QMAKE_TARGET).pro FORCE + $(LUPDATE) $(QMAKE_TARGET).pro + +release: $(QMAKE_TARGET).pro $(QMAKE_TARGET).ts + $(LRELEASE) $(QMAKE_TARGET).pro + +FORCE: + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Translations/qmake-default.pro b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Translations/qmake-default.pro new file mode 100644 index 00000000..3ab99fb4 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Translations/qmake-default.pro @@ -0,0 +1 @@ +include (../$ProjectName$.pro) diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Utils/bbutil.c b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Utils/bbutil.c new file mode 100644 index 00000000..02277fbc --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Utils/bbutil.c @@ -0,0 +1,1051 @@ +/* + * Copyright (c) 2011-2013 BlackBerry Limited. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "$Name$.h" + +#ifdef USING_GL11 +#include +#include +#elif defined(USING_GL20) +#include +#else +#error bbutil must be compiled with either USING_GL11 or USING_GL20 flags +#endif + +#include +#include FT_FREETYPE_H + +#include "png.h" + +EGLDisplay egl_disp; +EGLSurface egl_surf; + +static EGLConfig egl_conf; +static EGLContext egl_ctx; + +static screen_context_t screen_ctx; +static screen_window_t screen_win; +static screen_display_t screen_disp; +static int nbuffers = 2; +static int initialized = 0; + +#ifdef USING_GL20 +static GLuint text_rendering_program; +static int text_program_initialized = 0; +static GLint positionLoc; +static GLint texcoordLoc; +static GLint textureLoc; +static GLint colorLoc; +#endif + +struct font_t +{ + unsigned int font_texture; + float pt; + float advance[128]; + float width[128]; + float height[128]; + float tex_x1[128]; + float tex_x2[128]; + float tex_y1[128]; + float tex_y2[128]; + float offset_x[128]; + float offset_y[128]; + int initialized; +}; + +static void bbutil_egl_perror(const char *msg) +{ + static const char *errmsg[] = { + "function succeeded", + "EGL is not initialized, or could not be initialized, for the specified display", + "cannot access a requested resource", + "failed to allocate resources for the requested operation", + "an unrecognized attribute or attribute value was passed in an attribute list", + "an EGLConfig argument does not name a valid EGLConfig", + "an EGLContext argument does not name a valid EGLContext", + "the current surface of the calling thread is no longer valid", + "an EGLDisplay argument does not name a valid EGLDisplay", + "arguments are inconsistent", + "an EGLNativePixmapType argument does not refer to a valid native pixmap", + "an EGLNativeWindowType argument does not refer to a valid native window", + "one or more argument values are invalid", + "an EGLSurface argument does not name a valid surface configured for rendering", + "a power management event has occurred", + "unknown error code" + }; + + int message_index = eglGetError() - EGL_SUCCESS; + + if (message_index < 0 || message_index > 14) + message_index = 15; + + fprintf(stderr, "%s: %s\n", msg, errmsg[message_index]); +} + +/** + * Use the PID to set the window group id. + */ +static const char *get_window_group_id() +{ + static char s_window_group_id[16] = ""; + + if (s_window_group_id[0] == '\0') { + snprintf(s_window_group_id, sizeof(s_window_group_id), "%d", getpid()); + } + + return s_window_group_id; +} + +int bbutil_init_egl(screen_context_t ctx) +{ + int usage; + int format = SCREEN_FORMAT_RGBX8888; + EGLint interval = 1; + int rc, num_configs; + + EGLint attrib_list[]= { EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, 0, + EGL_NONE}; + +#ifdef USING_GL11 + usage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION; + attrib_list[9] = EGL_OPENGL_ES_BIT; +#elif defined(USING_GL20) + usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION; + attrib_list[9] = EGL_OPENGL_ES2_BIT; + EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; +#else + fprintf(stderr, "bbutil should be compiled with either USING_GL11 or USING_GL20 -D flags\n"); + return EXIT_FAILURE; +#endif + + //Simple egl initialization + screen_ctx = ctx; + + egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (egl_disp == EGL_NO_DISPLAY) { + bbutil_egl_perror("eglGetDisplay"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = eglInitialize(egl_disp, NULL, NULL); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglInitialize"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = eglBindAPI(EGL_OPENGL_ES_API); + + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglBindApi"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + if(!eglChooseConfig(egl_disp, attrib_list, &egl_conf, 1, &num_configs)) { + bbutil_terminate(); + return EXIT_FAILURE; + } + +#ifdef USING_GL20 + egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, attributes); +#elif defined(USING_GL11) + egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, NULL); +#endif + + if (egl_ctx == EGL_NO_CONTEXT) { + bbutil_egl_perror("eglCreateContext"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = screen_create_window(&screen_win, screen_ctx); + if (rc) { + perror("screen_create_window"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = screen_create_window_group(screen_win, get_window_group_id()); + if (rc) { + perror("screen_create_window_group"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format); + if (rc) { + perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage); + if (rc) { + perror("screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp); + if (rc) { + perror("screen_get_window_property_pv"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + const char *env = getenv("WIDTH"); + + if (0 == env) { + perror("failed getenv for WIDTH"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + int width = atoi(env); + + env = getenv("HEIGHT"); + + if (0 == env) { + perror("failed getenv for HEIGHT"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + int height = atoi(env); + int size[2] = { width, height }; + + rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size); + if (rc) { + perror("screen_set_window_property_iv"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = screen_create_window_buffers(screen_win, nbuffers); + if (rc) { + perror("screen_create_window_buffers"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL); + if (egl_surf == EGL_NO_SURFACE) { + bbutil_egl_perror("eglCreateWindowSurface"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglMakeCurrent"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + rc = eglSwapInterval(egl_disp, interval); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglSwapInterval"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + initialized = 1; + + return EXIT_SUCCESS; +} + +void bbutil_terminate() +{ + //Typical EGL cleanup + if (egl_disp != EGL_NO_DISPLAY) { + eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (egl_surf != EGL_NO_SURFACE) { + eglDestroySurface(egl_disp, egl_surf); + egl_surf = EGL_NO_SURFACE; + } + if (egl_ctx != EGL_NO_CONTEXT) { + eglDestroyContext(egl_disp, egl_ctx); + egl_ctx = EGL_NO_CONTEXT; + } + if (screen_win != NULL) { + screen_destroy_window(screen_win); + screen_win = NULL; + } + eglTerminate(egl_disp); + egl_disp = EGL_NO_DISPLAY; + } + eglReleaseThread(); + + initialized = 0; +} + +void bbutil_swap() +{ + int rc = eglSwapBuffers(egl_disp, egl_surf); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglSwapBuffers"); + } +} + +/* Finds the next power of 2 */ +static inline int nextp2(int x) +{ + int val = 1; + while(val < x) val <<= 1; + return val; +} + +font_t* bbutil_load_font(const char* path, int point_size, int dpi) +{ + FT_Library library; + FT_Face face; + int c; + int i, j; + font_t* font; + + if (!initialized) { + fprintf(stderr, "EGL has not been initialized\n"); + return NULL; + } + + if (!path){ + fprintf(stderr, "Invalid path to font file\n"); + return NULL; + } + + if(FT_Init_FreeType(&library)) { + fprintf(stderr, "Error loading Freetype library\n"); + return NULL; + } + if (FT_New_Face(library, path,0,&face)) { + fprintf(stderr, "Error loading font %s\n", path); + return NULL; + } + + if(FT_Set_Char_Size ( face, point_size * 64, point_size * 64, dpi, dpi)) { + fprintf(stderr, "Error initializing character parameters\n"); + return NULL; + } + + font = (font_t*) malloc(sizeof(font_t)); + + if (!font) { + fprintf(stderr, "Unable to allocate memory for font structure\n"); + return NULL; + } + + font->initialized = 0; + font->pt = point_size; + + glGenTextures(1, &(font->font_texture)); + + //Let each glyph reside in 32x32 section of the font texture + int segment_size_x = 0, segment_size_y = 0; + int num_segments_x = 16; + int num_segments_y = 8; + + FT_GlyphSlot slot; + FT_Bitmap bmp; + int glyph_width, glyph_height; + + //First calculate the max width and height of a character in a passed font + for(c = 0; c < 128; c++) { + if(FT_Load_Char(face, c, FT_LOAD_RENDER)) { + fprintf(stderr, "FT_Load_Char failed\n"); + free(font); + return NULL; + } + + slot = face->glyph; + bmp = slot->bitmap; + + glyph_width = bmp.width; + glyph_height = bmp.rows; + + if (glyph_width > segment_size_x) { + segment_size_x = glyph_width; + } + + if (glyph_height > segment_size_y) { + segment_size_y = glyph_height; + } + } + + int font_tex_width = nextp2(num_segments_x * segment_size_x); + int font_tex_height = nextp2(num_segments_y * segment_size_y); + + int bitmap_offset_x = 0, bitmap_offset_y = 0; + + GLubyte* font_texture_data = (GLubyte*) calloc(2 * font_tex_width * font_tex_height, sizeof(GLubyte)); + + if (!font_texture_data) { + fprintf(stderr, "Failed to allocate memory for font texture\n"); + free(font); + return NULL; + } + + // Fill font texture bitmap with individual bmp data and record appropriate size, texture coordinates and offsets for every glyph + for(c = 0; c < 128; c++) { + if(FT_Load_Char(face, c, FT_LOAD_RENDER)) { + fprintf(stderr, "FT_Load_Char failed\n"); + free(font); + return NULL; + } + + slot = face->glyph; + bmp = slot->bitmap; + + glyph_width = bmp.width; + glyph_height = bmp.rows; + + div_t temp = div(c, num_segments_x); + + bitmap_offset_x = segment_size_x * temp.rem; + bitmap_offset_y = segment_size_y * temp.quot; + + for (j = 0; j < glyph_height; j++) { + for (i = 0; i < glyph_width; i++) { + font_texture_data[2 * ((bitmap_offset_x + i) + (j + bitmap_offset_y) * font_tex_width) + 0] = + font_texture_data[2 * ((bitmap_offset_x + i) + (j + bitmap_offset_y) * font_tex_width) + 1] = + (i >= bmp.width || j >= bmp.rows)? 0 : bmp.buffer[i + bmp.width * j]; + } + } + + font->advance[c] = (float)(slot->advance.x >> 6); + font->tex_x1[c] = (float)bitmap_offset_x / (float) font_tex_width; + font->tex_x2[c] = (float)(bitmap_offset_x + bmp.width) / (float)font_tex_width; + font->tex_y1[c] = (float)bitmap_offset_y / (float) font_tex_height; + font->tex_y2[c] = (float)(bitmap_offset_y + bmp.rows) / (float)font_tex_height; + font->width[c] = bmp.width; + font->height[c] = bmp.rows; + font->offset_x[c] = (float)slot->bitmap_left; + font->offset_y[c] = (float)((slot->metrics.horiBearingY-face->glyph->metrics.height) >> 6); + } + + glBindTexture(GL_TEXTURE_2D, font->font_texture); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, font_tex_width, font_tex_height, 0, GL_LUMINANCE_ALPHA , GL_UNSIGNED_BYTE, font_texture_data); + + free(font_texture_data); + + FT_Done_Face(face); + FT_Done_FreeType(library); + + font->initialized = 1; + return font; +} + +void bbutil_render_text(font_t* font, const char* msg, float x, float y, float r, float g, float b, float a) +{ + int i, c; + GLfloat *vertices; + GLfloat *texture_coords; + GLushort* indices; + + float pen_x = 0.0f; + + if (!font) { + fprintf(stderr, "Font must not be null\n"); + return; + } + + if (!font->initialized) { + fprintf(stderr, "Font has not been loaded\n"); + return; + } + + if (!msg) { + return; + } + + const int msg_len = strlen(msg); + + vertices = (GLfloat*) malloc(sizeof(GLfloat) * 8 * msg_len); + texture_coords = (GLfloat*) malloc(sizeof(GLfloat) * 8 * msg_len); + + indices = (GLushort*) malloc(sizeof(GLushort) * 6 * msg_len); + + for(i = 0; i < msg_len; ++i) { + c = msg[i]; + + vertices[8 * i + 0] = x + pen_x + font->offset_x[c]; + vertices[8 * i + 1] = y + font->offset_y[c]; + vertices[8 * i + 2] = vertices[8 * i + 0] + font->width[c]; + vertices[8 * i + 3] = vertices[8 * i + 1]; + vertices[8 * i + 4] = vertices[8 * i + 0]; + vertices[8 * i + 5] = vertices[8 * i + 1] + font->height[c]; + vertices[8 * i + 6] = vertices[8 * i + 2]; + vertices[8 * i + 7] = vertices[8 * i + 5]; + + texture_coords[8 * i + 0] = font->tex_x1[c]; + texture_coords[8 * i + 1] = font->tex_y2[c]; + texture_coords[8 * i + 2] = font->tex_x2[c]; + texture_coords[8 * i + 3] = font->tex_y2[c]; + texture_coords[8 * i + 4] = font->tex_x1[c]; + texture_coords[8 * i + 5] = font->tex_y1[c]; + texture_coords[8 * i + 6] = font->tex_x2[c]; + texture_coords[8 * i + 7] = font->tex_y1[c]; + + indices[i * 6 + 0] = 4 * i + 0; + indices[i * 6 + 1] = 4 * i + 1; + indices[i * 6 + 2] = 4 * i + 2; + indices[i * 6 + 3] = 4 * i + 2; + indices[i * 6 + 4] = 4 * i + 1; + indices[i * 6 + 5] = 4 * i + 3; + + //Assume we are only working with typewriter fonts + pen_x += font->advance[c]; + } +#ifdef USING_GL11 + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glColor4f(r, g, b, a); + + glVertexPointer(2, GL_FLOAT, 0, vertices); + glTexCoordPointer(2, GL_FLOAT, 0, texture_coords); + glBindTexture(GL_TEXTURE_2D, font->font_texture); + + glDrawElements(GL_TRIANGLES, 6 * msg_len, GL_UNSIGNED_SHORT, indices); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); +#elif defined USING_GL20 + if (!text_program_initialized) { + GLint status; + + // Create shaders if this hasn't been done already + const char* v_source = + "precision mediump float;" + "attribute vec2 a_position;" + "attribute vec2 a_texcoord;" + "varying vec2 v_texcoord;" + "void main()" + "{" + " gl_Position = vec4(a_position, 0.0, 1.0);" + " v_texcoord = a_texcoord;" + "}"; + + const char* f_source = + "precision lowp float;" + "varying vec2 v_texcoord;" + "uniform sampler2D u_font_texture;" + "uniform vec4 u_col;" + "void main()" + "{" + " vec4 temp = texture2D(u_font_texture, v_texcoord);" + " gl_FragColor = u_col * temp;" + "}"; + + // Compile the vertex shader + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + + if (!vs) { + fprintf(stderr, "Failed to create vertex shader: %d\n", glGetError()); + return; + } else { + glShaderSource(vs, 1, &v_source, 0); + glCompileShader(vs); + glGetShaderiv(vs, GL_COMPILE_STATUS, &status); + if (GL_FALSE == status) { + GLchar log[256]; + glGetShaderInfoLog(vs, 256, NULL, log); + + fprintf(stderr, "Failed to compile vertex shader: %s\n", log); + + glDeleteShader(vs); + } + } + + // Compile the fragment shader + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + + if (!fs) { + fprintf(stderr, "Failed to create fragment shader: %d\n", glGetError()); + return; + } else { + glShaderSource(fs, 1, &f_source, 0); + glCompileShader(fs); + glGetShaderiv(fs, GL_COMPILE_STATUS, &status); + if (GL_FALSE == status) { + GLchar log[256]; + glGetShaderInfoLog(fs, 256, NULL, log); + + fprintf(stderr, "Failed to compile fragment shader: %s\n", log); + + glDeleteShader(vs); + glDeleteShader(fs); + + return; + } + } + + // Create and link the program + text_rendering_program = glCreateProgram(); + if (text_rendering_program) + { + glAttachShader(text_rendering_program, vs); + glAttachShader(text_rendering_program, fs); + glLinkProgram(text_rendering_program); + + glGetProgramiv(text_rendering_program, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + GLchar log[256]; + glGetProgramInfoLog(fs, 256, NULL, log); + + fprintf(stderr, "Failed to link text rendering shader program: %s\n", log); + + glDeleteProgram(text_rendering_program); + text_rendering_program = 0; + + return; + } + } else { + fprintf(stderr, "Failed to create a shader program\n"); + + glDeleteShader(vs); + glDeleteShader(fs); + return; + } + + // We don't need the shaders anymore - the program is enough + glDeleteShader(fs); + glDeleteShader(vs); + + glUseProgram(text_rendering_program); + + // Store the locations of the shader variables we need later + positionLoc = glGetAttribLocation(text_rendering_program, "a_position"); + texcoordLoc = glGetAttribLocation(text_rendering_program, "a_texcoord"); + textureLoc = glGetUniformLocation(text_rendering_program, "u_font_texture"); + colorLoc = glGetUniformLocation(text_rendering_program, "u_col"); + + text_program_initialized = 1; + } + + glEnable(GL_BLEND); + + //Map text coordinates from (0...surface width, 0...surface height) to (-1...1, -1...1) + //this make our vertex shader very simple and also works irrespective of orientation changes + EGLint surface_width, surface_height; + + eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width); + eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height); + + for(i = 0; i < 4 * msg_len; ++i) { + vertices[2 * i + 0] = 2 * vertices[2 * i + 0] / surface_width - 1.0f; + vertices[2 * i + 1] = 2 * vertices[2 * i + 1] / surface_height - 1.0f; + } + + //Render text + glUseProgram(text_rendering_program); + + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, font->font_texture); + glUniform1i(textureLoc, 0); + + glUniform4f(colorLoc, r, g, b, a); + + glEnableVertexAttribArray(positionLoc); + glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices); + + glEnableVertexAttribArray(texcoordLoc); + glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, texture_coords); + + //Draw the string + glDrawElements(GL_TRIANGLES, 6 * msg_len, GL_UNSIGNED_SHORT, indices); + + glDisableVertexAttribArray(positionLoc); + glDisableVertexAttribArray(texcoordLoc); +#else + fprintf(stderr, "bbutil should be compiled with either USING_GL11 or USING_GL20 -D flags\n"); +#endif + + free(vertices); + free(texture_coords); + free(indices); +} + +void bbutil_destroy_font(font_t* font) +{ + if (!font) + { + return; + } + + glDeleteTextures(1, &(font->font_texture)); + + free(font); +} + +void bbutil_measure_text(font_t* font, const char* msg, float* width, float* height) +{ + int i, c; + + if (!msg) + { + return; + } + + const int msg_len =strlen(msg); + + if (width) + { + //Width of a text rectangle is a sum advances for every glyph in a string + *width = 0.0f; + + for(i = 0; i < msg_len; ++i) + { + c = msg[i]; + *width += font->advance[c]; + } + } + + if (height) + { + //Height of a text rectangle is a high of a tallest glyph in a string + *height = 0.0f; + + for(i = 0; i < msg_len; ++i) + { + c = msg[i]; + + if (*height < font->height[c]) + { + *height = font->height[c]; + } + } + } +} + +int bbutil_load_texture(const char* filename, int* width, int* height, float* tex_x, float* tex_y, unsigned int *tex) +{ + int i; + GLuint format; + //header for testing if it is a png + png_byte header[8]; + + if (!tex) { + return EXIT_FAILURE; + } + + //open file as binary + FILE *fp = fopen(filename, "rb"); + if (!fp) { + return EXIT_FAILURE; + } + + //read the header + fread(header, 1, 8, fp); + + //test if png + int is_png = !png_sig_cmp(header, 0, 8); + if (!is_png) { + fclose(fp); + return EXIT_FAILURE; + } + + //create png struct + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(fp); + return EXIT_FAILURE; + } + + //create png info struct + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(fp); + return EXIT_FAILURE; + } + + //create png info struct + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + fclose(fp); + return EXIT_FAILURE; + } + + //setup error handling (required without using custom error handlers above) + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); + return EXIT_FAILURE; + } + + //init png reading + png_init_io(png_ptr, fp); + + //let libpng know you already read the first 8 bytes + png_set_sig_bytes(png_ptr, 8); + + // read all the info up to the image data + png_read_info(png_ptr, info_ptr); + + //variables to pass to get info + int bit_depth, color_type; + png_uint_32 image_width, image_height; + + // get info about png + png_get_IHDR(png_ptr, info_ptr, &image_width, &image_height, &bit_depth, &color_type, NULL, NULL, NULL); + + switch (color_type) + { + case PNG_COLOR_TYPE_RGBA: + format = GL_RGBA; + break; + case PNG_COLOR_TYPE_RGB: + format = GL_RGB; + break; + default: + fprintf(stderr,"Unsupported PNG color type (%d) for texture: %s", (int)color_type, filename); + fclose(fp); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + return NULL; + } + + // Update the png info struct. + png_read_update_info(png_ptr, info_ptr); + + // Row size in bytes. + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + // Allocate the image_data as a big block, to be given to opengl + png_byte *image_data = (png_byte*) malloc(sizeof(png_byte) * rowbytes * image_height); + + if (!image_data) { + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); + return EXIT_FAILURE; + } + + //row_pointers is for pointing to image_data for reading the png with libpng + png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * image_height); + if (!row_pointers) { + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + free(image_data); + fclose(fp); + return EXIT_FAILURE; + } + + // set the individual row_pointers to point at the correct offsets of image_data + for (i = 0; i < image_height; i++) { + row_pointers[image_height - 1 - i] = image_data + i * rowbytes; + } + + //read the png into image_data through row_pointers + png_read_image(png_ptr, row_pointers); + + int tex_width, tex_height; + + tex_width = nextp2(image_width); + tex_height = nextp2(image_height); + + glGenTextures(1, tex); + glBindTexture(GL_TEXTURE_2D, (*tex)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + if ((tex_width != image_width) || (tex_height != image_height) ) { + glTexImage2D(GL_TEXTURE_2D, 0, format, tex_width, tex_height, 0, format, GL_UNSIGNED_BYTE, NULL); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_width, image_height, format, GL_UNSIGNED_BYTE, image_data); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, format, tex_width, tex_height, 0, format, GL_UNSIGNED_BYTE, image_data); + } + + GLint err = glGetError(); + + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + free(image_data); + free(row_pointers); + fclose(fp); + + if (err == 0) { + //Return physical with and height of texture if pointers are not null + if(width) { + *width = image_width; + } + if (height) { + *height = image_height; + } + //Return modified texture coordinates if pointers are not null + if(tex_x) { + *tex_x = ((float) image_width - 0.5f) / ((float)tex_width); + } + if(tex_y) { + *tex_y = ((float) image_height - 0.5f) / ((float)tex_height); + } + return EXIT_SUCCESS; + } else { + fprintf(stderr, "GL error %i \n", err); + return EXIT_FAILURE; + } +} + +int bbutil_calculate_dpi(screen_context_t ctx) +{ + int rc; + int screen_phys_size[2]; + + rc = screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size); + if (rc) { + perror("screen_get_display_property_iv"); + bbutil_terminate(); + return EXIT_FAILURE; + } + + //Simulator will return 0,0 for physical size of the screen, so use 170 as default dpi + if ((screen_phys_size[0] == 0) && (screen_phys_size[1] == 0)) { + return 170; + } else { + int screen_resolution[2]; + rc = screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); + if (rc) { + perror("screen_get_display_property_iv"); + bbutil_terminate(); + return EXIT_FAILURE; + } + double diagonal_pixels = sqrt(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1]); + double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]); + return (int)(diagonal_pixels / diagonal_inches + 0.5); + + } +} + +int bbutil_rotate_screen_surface(int angle) +{ + int rc, rotation, skip = 1, temp;; + EGLint interval = 1; + int size[2]; + + if ((angle != 0) && (angle != 90) && (angle != 180) && (angle != 270)) { + fprintf(stderr, "Invalid angle\n"); + return EXIT_FAILURE; + } + + rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &rotation); + if (rc) { + perror("screen_set_window_property_iv"); + return EXIT_FAILURE; + } + + rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size); + if (rc) { + perror("screen_set_window_property_iv"); + return EXIT_FAILURE; + } + + switch (angle - rotation) { + case -270: + case -90: + case 90: + case 270: + temp = size[0]; + size[0] = size[1]; + size[1] = temp; + skip = 0; + break; + } + + if (!skip) { + rc = eglMakeCurrent(egl_disp, NULL, NULL, NULL); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglMakeCurrent"); + return EXIT_FAILURE; + } + + rc = eglDestroySurface(egl_disp, egl_surf); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglMakeCurrent"); + return EXIT_FAILURE; + } + + rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SOURCE_SIZE, size); + if (rc) { + perror("screen_set_window_property_iv"); + return EXIT_FAILURE; + } + + rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size); + if (rc) { + perror("screen_set_window_property_iv"); + return EXIT_FAILURE; + } + egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL); + if (egl_surf == EGL_NO_SURFACE) { + bbutil_egl_perror("eglCreateWindowSurface"); + return EXIT_FAILURE; + } + + rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglMakeCurrent"); + return EXIT_FAILURE; + } + + rc = eglSwapInterval(egl_disp, interval); + if (rc != EGL_TRUE) { + bbutil_egl_perror("eglSwapInterval"); + return EXIT_FAILURE; + } + } + + rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle); + if (rc) { + perror("screen_set_window_property_iv"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Utils/bbutil.h b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Utils/bbutil.h new file mode 100644 index 00000000..1081f714 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/Utils/bbutil.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011-2013 BlackBerry Limited. + * + * 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. + */ + +#ifndef __$SafeNameUpper$_H__ +#define __$SafeNameUpper$_H__ + +#include +#include +#include + +extern EGLDisplay egl_disp; +extern EGLSurface egl_surf; + +typedef struct font_t font_t; + +#define BBUTIL_DEFAULT_FONT "/usr/fonts/font_repository/monotype/arial.ttf" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * Initializes EGL + * + * @param libscreen context that will be used for EGL setup + * @return EXIT_SUCCESS if initialization succeeded otherwise EXIT_FAILURE + */ +int bbutil_init_egl(screen_context_t ctx); + +/** + * Terminates EGL + */ +void bbutil_terminate(); + +/** + * Swaps default bbutil window surface to the screen + */ +void bbutil_swap(); + +/** + * Loads the font from the specified font file. + * NOTE: should be called after a successful return from bbutil_init() or bbutil_init_egl() call + * @param font_file string indicating the absolute path of the font file + * @param point_size used for glyph generation + * @param dpi used for glyph generation + * @return pointer to font_t structure on success or NULL on failure + */ +font_t* bbutil_load_font(const char* font_file, int point_size, int dpi); + +/** + * Destroys the passed font + * @param font to be destroyed + */ +void bbutil_destroy_font(font_t* font); + +/** + * Renders the specified message using current font starting from the specified + * bottom left coordinates. + * NOTE: must be called after a successful return from bbutil_init() or bbutil_init_egl() call + + * + * @param font to use for rendering + * @param msg the message to display + * @param x, y position of the bottom-left corner of text string in world coordinate space + * @param rgba color for the text to render with + */ +void bbutil_render_text(font_t* font, const char* msg, float x, float y, float r, float g, float b, float a); + +/** + * Returns the non-scaled width and height of a string + * NOTE: must be called after a successful return from bbutil_init() or bbutil_init_egl() call + + * + * @param font to use for measurement of a string size + * @param msg the message to get the size of + * @param return pointer for width of a string + * @param return pointer for height of a string + */ +void bbutil_measure_text(font_t* font, const char* msg, float* width, float* height); + +/** + * Creates and loads a texture from a png file + * NOTE: must be called after a successful return from bbutil_init() or bbutil_init_egl() call + + * + * @param filename path to texture png + * @param return width of texture + * @param return height of texture + * @param return gl texture handle + * @return EXIT_SUCCESS if texture loading succeeded otherwise EXIT_FAILURE + */ + +int bbutil_load_texture(const char* filename, int* width, int* height, float* tex_x, float* tex_y, unsigned int* tex); + +/** + * Returns dpi for a given screen + + * + * @param ctx path libscreen context that corresponds to display of interest + * @return dpi for a given screen + */ + +int bbutil_calculate_dpi(screen_context_t ctx); + +/** + * Rotates the screen to a given angle + + * + * @param angle to rotate screen surface to, must by 0, 90, 180, or 270 + * @return EXIT_SUCCESS if texture loading succeeded otherwise EXIT_FAILURE + */ + +int bbutil_rotate_screen_surface(int angle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __$SafeNameUpper$_H__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/applicationui.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/applicationui.cpp new file mode 100644 index 00000000..39d6fc17 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/applicationui.cpp @@ -0,0 +1,48 @@ +#include "ApplicationUI.hpp" + +#include +#include +#include +#include + +using namespace bb::cascades; + +ApplicationUI::ApplicationUI() + : QObject() +{ + // prepare the localization + m_pTranslator = new QTranslator(this); + m_pLocaleHandler = new LocaleHandler(this); + + bool res = QObject::connect(m_pLocaleHandler, SIGNAL(systemLanguageChanged()), this, SLOT(onSystemLanguageChanged())); + // This is only available in Debug builds + Q_ASSERT(res); + // Since the variable is not used in the app, this is added to avoid a + // compiler warning + Q_UNUSED(res); + + // initial load + onSystemLanguageChanged(); + + // Create scene document from main.qml asset, the parent is set + // to ensure the document gets destroyed properly at shut down. + QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this); + + // Create root object for the UI + AbstractPane *root = qml->createRootObject(); + + // Set created root object as the application scene + Application::instance()->setScene(root); +} + +void ApplicationUI::onSystemLanguageChanged() +{ + QCoreApplication::instance()->removeTranslator(m_pTranslator); + // Initiate, load and install the application translation files. + QString locale_string = QLocale().name(); + QString file_name = QString("$ProjectName$_%1").arg(locale_string); + if (m_pTranslator->load(file_name, "app/native/qm")) + { + QCoreApplication::instance()->installTranslator(m_pTranslator); + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/applicationui.hpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/applicationui.hpp new file mode 100644 index 00000000..f8e0d287 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/applicationui.hpp @@ -0,0 +1,36 @@ +#ifndef __APPLICATIONUI_HPP__ +#define __APPLICATIONUI_HPP__ + +#include + +namespace bb +{ + namespace cascades + { + class LocaleHandler; + } +} + +class QTranslator; + +/*! + * @brief Application UI object + * + * Use this object to create and init app UI, to create context objects, to register the new meta types etc. + */ +class ApplicationUI : public QObject +{ + Q_OBJECT +public: + ApplicationUI(); + virtual ~ApplicationUI() {} + +private slots: + void onSystemLanguageChanged(); + +private: + QTranslator* m_pTranslator; + bb::cascades::LocaleHandler* m_pLocaleHandler; +}; + +#endif /* __APPLICATIONUI_HPP__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/bar-descriptor-cascades.xml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/bar-descriptor-cascades.xml new file mode 100644 index 00000000..697d1a02 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/bar-descriptor-cascades.xml @@ -0,0 +1,78 @@ + + + + + + + com.$AuthorSafe$.$ProjectName$ + + + $ProjectName$ + + + 1.0.0 + + + 1 + + + The $ProjectName$ application + + + + + + $Author$ + + + $AuthorID$ + + + none + false + + + + core.games + + armle-v7 + $ProjectName$ + + + armle-v7 + Qnx/Cascades + $ProjectName$.so + + + x86 + $ProjectName$ + + + + + + + assets + + + + + + + + + + run_native + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/bar-descriptor.xml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/bar-descriptor.xml new file mode 100644 index 00000000..c111a4e0 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/bar-descriptor.xml @@ -0,0 +1,69 @@ + + + + + + + com.$AuthorSafe$.$ProjectName$ + + + $ProjectName$ + + + 1.0.0 + + + 1 + + + The $ProjectName$ application + + + + + + $Author$ + + + $AuthorID$ + + + none + false + + + + core.games + + armle-v7 + $ProjectName$ + + + armle-v7 + $ProjectName$ + + + x86 + $ProjectName$ + + + + + + + + + run_native + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-cascades.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-cascades.cpp new file mode 100644 index 00000000..93711f63 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-cascades.cpp @@ -0,0 +1,38 @@ +#include +#include + +#include "ApplicationUI.hpp" + +using namespace bb::cascades; + +#if _DEBUG +/** + * Redirect all Cascades logs on standard console. + */ +static void WriteLogsToConsole(QtMsgType type, const char *message) +{ + Q_UNUSED(type); + std::fprintf(stdout, "%s\n", message); + std::fflush(stdout); +} +#endif /* _DEBUG */ + + +/** + * Application Entry Point. + */ +Q_DECL_EXPORT int main(int argc, char **argv) +{ + Application app(argc, argv); + +#if _DEBUG + qInstallMsgHandler(WriteLogsToConsole); +#endif /* _DEBUG */ + + // Create the Application UI object, this is where the main.qml file + // is loaded and the application scene is set. + ApplicationUI appui; + + // Enter the application main event loop. + return Application::exec(); +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-empty.c b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-empty.c new file mode 100644 index 00000000..e531d215 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-empty.c @@ -0,0 +1,8 @@ + +/** + * Application Entry Point. + */ +int main(int argc, char** argv) +{ + return 0; +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-opengl1.c b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-opengl1.c new file mode 100644 index 00000000..3fe1b287 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-opengl1.c @@ -0,0 +1,229 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bbutil.h" + +static GLfloat vertices[8]; +static GLfloat colors[16]; + +static void handleScreenEvent(bps_event_t *event) +{ + screen_event_t screen_event = screen_event_get_event(event); + + int screen_val; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val); + + switch (screen_val) + { + case SCREEN_EVENT_MTOUCH_TOUCH: + case SCREEN_EVENT_MTOUCH_MOVE: + case SCREEN_EVENT_MTOUCH_RELEASE: + break; + } +} + +static int initialize() +{ + //Initialize vertex and color data + vertices[0] = -0.25f; + vertices[1] = -0.25f; + + vertices[2] = 0.25f; + vertices[3] = -0.25f; + + vertices[4] = -0.25f; + vertices[5] = 0.25f; + + vertices[6] = 0.25f; + vertices[7] = 0.25f; + + colors[0] = 1.0f; + colors[1] = 0.0f; + colors[2] = 1.0f; + colors[3] = 1.0f; + + colors[4] = 1.0f; + colors[5] = 1.0f; + colors[6] = 0.0f; + colors[7] = 1.0f; + + colors[8] = 0.0f; + colors[9] = 1.0f; + colors[10] = 1.0f; + colors[11] = 1.0f; + + colors[12] = 0.0f; + colors[13] = 1.0f; + colors[14] = 1.0f; + colors[15] = 1.0f; + + //Query width and height of the window surface created by utility code + EGLint surface_width, surface_height; + + eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width); + eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height); + + EGLint err = eglGetError(); + if (err != 0x3000) + { + fprintf(stderr, "Unable to query EGL surface dimensions\n"); + return EXIT_FAILURE; + } + + glShadeModel(GL_SMOOTH); + + //set clear color to white + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + + glViewport(0, 0, surface_width, surface_height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glOrthof(0.0f, (float) (surface_width) / (float) (surface_height), 0.0f, 1.0f, -1.0f, 1.0f); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glTranslatef((float) (surface_width) / (float) (surface_height) / 2, 0.5f, 0.0f); + + return EXIT_SUCCESS; +} + +static void render() +{ + //Typical render pass + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vertices); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_FLOAT, 0, colors); + + glRotatef(0.5f, 0.0f, 1.0f, 0.0f); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + //Use utility code to update the screen + bbutil_swap(); +} + +/** + * Application Entry Point. + */ +int main(int argc, char *argv[]) +{ + int exit_application = 0; + static screen_context_t screen_cxt; + + //Create a screen context that will be used to create an EGL surface to to receive libscreen events + screen_create_context(&screen_cxt, 0); + + //Initialize BPS library + bps_initialize(); + + //Use utility code to initialize EGL for rendering with GL ES 1.1 + if (EXIT_SUCCESS != bbutil_init_egl(screen_cxt)) + { + fprintf(stderr, "bbutil_init_egl failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + return 0; + } + + //Initialize application logic + if (EXIT_SUCCESS != initialize()) + { + fprintf(stderr, "initialize failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + return 0; + } + + //Signal BPS library that navigator and screen events will be requested + if (BPS_SUCCESS != screen_request_events(screen_cxt)) + { + fprintf(stderr, "screen_request_events failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + return 0; + } + + if (BPS_SUCCESS != navigator_request_events(0)) + { + fprintf(stderr, "navigator_request_events failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + return 0; + } + + //Signal BPS library that navigator orientation is not to be locked + if (BPS_SUCCESS != navigator_rotation_lock(false)) + { + fprintf(stderr, "navigator_rotation_lock failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + return 0; + } + + while (!exit_application) + { + //Request and process all available BPS events + bps_event_t *event = NULL; + + for(;;) + { + if (BPS_SUCCESS != bps_get_event(&event, 0)) + { + fprintf(stderr, "bps_get_event failed\n"); + break; + } + + if (event) + { + int domain = bps_event_get_domain(event); + + if (domain == screen_get_domain()) + { + handleScreenEvent(event); + } + if ((domain == navigator_get_domain()) && (NAVIGATOR_EXIT == bps_event_get_code(event))) + { + exit_application = 1; + } + } + else + { + break; + } + } + render(); + } + + //Stop requesting events from libscreen + screen_stop_events(screen_cxt); + + //Shut down BPS library for this process + bps_shutdown(); + + //Use utility code to terminate EGL setup + bbutil_terminate(); + + //Destroy libscreen context + screen_destroy_context(screen_cxt); + return 0; +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-opengl2.c b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-opengl2.c new file mode 100644 index 00000000..b139952d --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-opengl2.c @@ -0,0 +1,381 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "bbutil.h" + +static GLfloat vertices[8]; +static GLfloat colors[16]; + +static GLuint program; + +static GLuint transformLoc; +static GLuint positionLoc; +static GLuint colorLoc; + +static GLfloat matrix[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; + +static GLuint vertexID; +static GLuint colorID; + +static screen_context_t screen_cxt; + + +static void handleScreenEvent(bps_event_t *event) +{ + screen_event_t screen_event = screen_event_get_event(event); + + int screen_val; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val); + + switch (screen_val) + { + case SCREEN_EVENT_MTOUCH_TOUCH: + case SCREEN_EVENT_MTOUCH_MOVE: + case SCREEN_EVENT_MTOUCH_RELEASE: + break; + } +} + +static int initialize() +{ + //Initialize vertex and color data + vertices[0] = -0.25f; + vertices[1] = -0.25f; + + vertices[2] = 0.25f; + vertices[3] = -0.25f; + + vertices[4] = -0.25f; + vertices[5] = 0.25f; + + vertices[6] = 0.25f; + vertices[7] = 0.25f; + + colors[0] = 1.0f; + colors[1] = 0.0f; + colors[2] = 1.0f; + colors[3] = 1.0f; + + colors[4] = 1.0f; + colors[5] = 1.0f; + colors[6] = 0.0f; + colors[7] = 1.0f; + + colors[8] = 0.0f; + colors[9] = 1.0f; + colors[10] = 1.0f; + colors[11] = 1.0f; + + colors[12] = 0.0f; + colors[13] = 1.0f; + colors[14] = 1.0f; + colors[15] = 1.0f; + + //Query width and height of the window surface created by utility code + EGLint surface_width, surface_height; + + eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width); + eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height); + + // Create shaders + const char* vSource = + "precision mediump float;" + "uniform mat4 u_projection;" + "uniform mat4 u_transform;" + "attribute vec4 a_position;" + "attribute vec4 a_color;" + "varying vec4 v_color;" + "void main()" + "{" + " gl_Position = u_projection * u_transform * a_position;" + " v_color = a_color;" + "}"; + + const char* fSource = + "varying lowp vec4 v_color;" + "void main()" + "{" + " gl_FragColor = v_color;" + "}"; + + GLint status; + + // Compile the vertex shader + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + if (!vs) + { + fprintf(stderr, "Failed to create vertex shader: %d\n", glGetError()); + return EXIT_FAILURE; + } + else + { + glShaderSource(vs, 1, &vSource, 0); + glCompileShader(vs); + glGetShaderiv(vs, GL_COMPILE_STATUS, &status); + if (GL_FALSE == status) + { + GLchar log[256]; + glGetShaderInfoLog(vs, 256, NULL, log); + + fprintf(stderr, "Failed to compile vertex shader: %s\n", log); + + glDeleteShader(vs); + } + } + + // Compile the fragment shader + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + if (!fs) + { + fprintf(stderr, "Failed to create fragment shader: %d\n", glGetError()); + return EXIT_FAILURE; + } + else + { + glShaderSource(fs, 1, &fSource, 0); + glCompileShader(fs); + glGetShaderiv(fs, GL_COMPILE_STATUS, &status); + if (GL_FALSE == status) + { + GLchar log[256]; + glGetShaderInfoLog(fs, 256, NULL, log); + + fprintf(stderr, "Failed to compile fragment shader: %s\n", log); + + glDeleteShader(vs); + glDeleteShader(fs); + + return EXIT_FAILURE; + } + } + + // Create and link the program + program = glCreateProgram(); + if (program) + { + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + + glGetProgramiv(program, GL_LINK_STATUS, &status); + if (status == GL_FALSE) + { + GLchar log[256]; + glGetProgramInfoLog(fs, 256, NULL, log); + + fprintf(stderr, "Failed to link shader program: %s\n", log); + + glDeleteProgram(program); + program = 0; + + return EXIT_FAILURE; + } + } + else + { + fprintf(stderr, "Failed to create a shader program\n"); + + glDeleteShader(vs); + glDeleteShader(fs); + return EXIT_FAILURE; + } + + glUseProgram(program); + + // Set up the orthographic projection - equivalent to glOrtho in GLES1 + GLuint projectionLoc = glGetUniformLocation(program, "u_projection"); + { + GLfloat left = 0.0f; + GLfloat right = (float)(surface_width) / (float)(surface_height); + GLfloat bottom = 0.0f; + GLfloat top = 1.0f; + GLfloat zNear = -1.0f; + GLfloat zFar = 1.0f; + GLfloat ortho[16] = { 2.0 / (right-left), 0, 0, 0, + 0, 2.0 / (top-bottom), 0, 0, + 0, 0, -2.0 / (zFar - zNear), 0, + -(right+left)/(right-left), -(top+bottom)/(top-bottom), -(zFar+zNear)/(zFar-zNear), 1}; + glUniformMatrix4fv(projectionLoc, 1, false, ortho); + } + + // Store the locations of the shader variables we need later + transformLoc = glGetUniformLocation(program, "u_transform"); + positionLoc = glGetAttribLocation(program, "a_position"); + colorLoc = glGetAttribLocation(program, "a_color"); + + // We don't need the shaders anymore - the program is enough + glDeleteShader(fs); + glDeleteShader(vs); + + // Generate vertex and color buffers and fill with data + glGenBuffers(1, &vertexID); + glBindBuffer(GL_ARRAY_BUFFER, vertexID); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glGenBuffers(1, &colorID); + glBindBuffer(GL_ARRAY_BUFFER, colorID); + glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW); + + // Perform the same translation as the GLES1 version + matrix[12] = (float)(surface_width) / (float)(surface_height) / 2; + matrix[13] = 0.5; + glUniformMatrix4fv(transformLoc, 1, false, matrix); + + return EXIT_SUCCESS; +} + +static void render() +{ + // Increment the angle by 0.5 degrees + static float angle = 0.0f; + angle += 0.5f * M_PI / 180.0f; + + //Typical render pass + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Enable and bind the vertex information + glEnableVertexAttribArray(positionLoc); + glBindBuffer(GL_ARRAY_BUFFER, vertexID); + glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0); + + // Enable and bind the color information + glEnableVertexAttribArray(colorLoc); + glBindBuffer(GL_ARRAY_BUFFER, colorID); + glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); + + // Effectively apply a rotation of angle about the y-axis. + matrix[0] = cos(angle); + matrix[2] = -sin(angle); + matrix[8] = sin(angle); + matrix[10] = cos(angle); + glUniformMatrix4fv(transformLoc, 1, false, matrix); + + // Same draw call as in GLES1. + glDrawArrays(GL_TRIANGLE_STRIP, 0 , 4); + + // Disable attribute arrays + glDisableVertexAttribArray(positionLoc); + glDisableVertexAttribArray(colorLoc); + + bbutil_swap(); +} + +/** + * Application Entry Point. + */ +int main(int argc, char *argv[]) +{ + int exit_application = 0; + + //Create a screen context that will be used to create an EGL surface to to receive libscreen events + screen_create_context(&screen_cxt, 0); + + //Initialize BPS library + bps_initialize(); + + //Use utility code to initialize EGL for rendering with GL ES 2.0 + if (EXIT_SUCCESS != bbutil_init_egl(screen_cxt)) + { + fprintf(stderr, "bbutil_init_egl failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + return 0; + } + + //Initialize application logic + if (EXIT_SUCCESS != initialize()) + { + fprintf(stderr, "initialize failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + bps_shutdown(); + return 0; + } + + //Signal BPS library that navigator and screen events will be requested + if (BPS_SUCCESS != screen_request_events(screen_cxt)) + { + fprintf(stderr, "screen_request_events failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + bps_shutdown(); + return 0; + } + + if (BPS_SUCCESS != navigator_request_events(0)) + { + fprintf(stderr, "navigator_request_events failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + bps_shutdown(); + return 0; + } + + //Signal BPS library that navigator orientation is not to be locked + if (BPS_SUCCESS != navigator_rotation_lock(false)) + { + fprintf(stderr, "navigator_rotation_lock failed\n"); + bbutil_terminate(); + screen_destroy_context(screen_cxt); + bps_shutdown(); + return 0; + } + + while (!exit_application) + { + //Request and process all available BPS events + bps_event_t *event = NULL; + + for(;;) { + if (BPS_SUCCESS != bps_get_event(&event, 0)) + { + fprintf(stderr, "bps_get_event failed\n"); + break; + } + + if (event) + { + int domain = bps_event_get_domain(event); + + if (domain == screen_get_domain()) + { + handleScreenEvent(event); + } + if ((domain == navigator_get_domain()) && (NAVIGATOR_EXIT == bps_event_get_code(event))) + { + exit_application = 1; + } + } + else + { + break; + } + } + render(); + } + + //Stop requesting events from libscreen + screen_stop_events(screen_cxt); + + //Shut down BPS library for this process + bps_shutdown(); + + //Use utility code to terminate EGL setup + bbutil_terminate(); + + //Destroy libscreen context + screen_destroy_context(screen_cxt); + return 0; +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-screen.c b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-screen.c new file mode 100644 index 00000000..f855921c --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/main-screen.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include + +static bool shutdown = false; + + +static void handle_screen_event(bps_event_t *event) +{ + int screen_val; + + screen_event_t screen_event = screen_event_get_event(event); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val); + + switch (screen_val) + { + case SCREEN_EVENT_MTOUCH_TOUCH: + fprintf(stderr,"Touch event"); + break; + case SCREEN_EVENT_MTOUCH_MOVE: + fprintf(stderr,"Move event"); + break; + case SCREEN_EVENT_MTOUCH_RELEASE: + fprintf(stderr,"Release event"); + break; + default: + break; + } + fprintf(stderr,"\n"); +} + +static void handle_navigator_event(bps_event_t *event) +{ + switch (bps_event_get_code(event)) + { + case NAVIGATOR_SWIPE_DOWN: + fprintf(stderr,"Swipe down event"); + break; + case NAVIGATOR_EXIT: + fprintf(stderr,"Exit event"); + shutdown = true; + break; + default: + break; + } + fprintf(stderr,"\n"); +} + +static void handle_event() +{ + int domain; + + bps_event_t *event = NULL; + if (BPS_SUCCESS != bps_get_event(&event, -1)) + { + fprintf(stderr, "bps_get_event() failed\n"); + return; + } + + if (event) + { + domain = bps_event_get_domain(event); + if (domain == navigator_get_domain()) + { + handle_navigator_event(event); + } + if (domain == screen_get_domain()) + { + handle_screen_event(event); + } + } +} + +/** + * Application Entry Point. + */ +int main(int argc, char **argv) +{ + const int usage = SCREEN_USAGE_NATIVE; + + screen_context_t screen_ctx; + screen_window_t screen_win; + screen_buffer_t screen_buf = NULL; + int rect[4] = { 0, 0, 0, 0 }; + char window_group_id[16] = ""; + + /* Use the PID to set the window group id */ + snprintf(window_group_id, sizeof(window_group_id), "%d", getpid()); + + /* Setup the window */ + screen_create_context(&screen_ctx, 0); + screen_create_window(&screen_win, screen_ctx); + screen_create_window_group(screen_win, window_group_id); + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage); + screen_create_window_buffers(screen_win, 1); + + screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf); + screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2); + + /* Fill the screen buffer with blue */ + int attribs[] = { SCREEN_BLIT_COLOR, 0xff0000ff, SCREEN_BLIT_END }; + screen_fill(screen_ctx, screen_buf, attribs); + screen_post_window(screen_win, screen_buf, 1, rect, 0); + + /* Signal bps library that navigator and screen events will be requested */ + bps_initialize(); + screen_request_events(screen_ctx); + navigator_request_events(0); + + while (!shutdown) + { + /* Handle user input */ + handle_event(); + } + + /* Clean up */ + screen_stop_events(screen_ctx); + bps_shutdown(); + screen_destroy_window(screen_win); + screen_destroy_context(screen_ctx); + return 0; +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/makefile-cascades b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/makefile-cascades new file mode 100644 index 00000000..2a8fd6f7 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/makefile-cascades @@ -0,0 +1,6 @@ +QMAKE_TARGET = $ProjectName$ +PROJECT_DIR := $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) +I18N_DIR := $(PROJECT_DIR)/translations + +include mk/cs-base.mk + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/makefile-empty b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/makefile-empty new file mode 100644 index 00000000..ba99aa4c --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/makefile-empty @@ -0,0 +1,2 @@ +# Empty makefile + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/precompiled-cascades.h b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/precompiled-cascades.h new file mode 100644 index 00000000..86d0e5d1 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/precompiled-cascades.h @@ -0,0 +1,5 @@ +// This file is used to store precompiled headers. + +#include +#include +#include diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/precompiled-empty.h b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/precompiled-empty.h new file mode 100644 index 00000000..a61668b6 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/precompiled-empty.h @@ -0,0 +1 @@ +// This file is used to store precompiled headers. diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qclass.cpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qclass.cpp new file mode 100644 index 00000000..fb30b844 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qclass.cpp @@ -0,0 +1,11 @@ +#include "$Name$.hpp" + +$SafeName$::$SafeName$(QObject *parentOrNull) + : QObject(parentOrNull) +{ +} + +$SafeName$::~$SafeName$() +{ +} + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qclass.hpp b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qclass.hpp new file mode 100644 index 00000000..d3b55717 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qclass.hpp @@ -0,0 +1,15 @@ +#ifndef __$SafeNameUpper$_HPP__ +#define __$SafeNameUpper$_HPP__ + +#include + +class $SafeName$ : public QObject +{ + Q_OBJECT + +public: + $SafeName$(QObject *parentOrNull); + virtual ~$SafeName$(); +}; + +#endif /* __$SafeNameUpper$_HPP__ */ diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qcontrol.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qcontrol.qml new file mode 100644 index 00000000..0a3bc8d7 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qcontrol.qml @@ -0,0 +1,5 @@ +import bb.cascades $CascadesVersion$ + +Container { + +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qdialog.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qdialog.qml new file mode 100644 index 00000000..217e88d2 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qdialog.qml @@ -0,0 +1,7 @@ +import bb.cascades $CascadesVersion$ + +Dialog { + Container { + + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qmake-config.pri b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qmake-config.pri new file mode 100644 index 00000000..15d4307f --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qmake-config.pri @@ -0,0 +1,3 @@ +# +# This file will be automatically generated, when the project is built. +# \ No newline at end of file diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qmake-default.pro b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qmake-default.pro new file mode 100644 index 00000000..f4159315 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qmake-default.pro @@ -0,0 +1,5 @@ +APP_NAME = $ProjectName$ + +CONFIG += qt warn_on cascades10 + +include(config.pri) diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qpage.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qpage.qml new file mode 100644 index 00000000..fd3706cf --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qpage.qml @@ -0,0 +1,7 @@ +import bb.cascades $CascadesVersion$ + +Page { + Container { + + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qpane.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qpane.qml new file mode 100644 index 00000000..4f7cbaa4 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qpane.qml @@ -0,0 +1,35 @@ +import bb.cascades $CascadesVersion$ + +NavigationPane { + id: navigationPane + + Page { + Container { + + } + + actions: ActionItem { + title: qsTr("Second page") + ActionBar.placement: ActionBarPlacement.OnBar + + onTriggered: { + navigationPane.push(secondPageDefinition.createObject()); + } + } + } + + attachedObjects: [ + ComponentDefinition { + id: secondPageDefinition + Page { + Container { + + } + } + } + ] + + onPopTransitionEnded: { + page.destroy(); + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qsheet.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qsheet.qml new file mode 100644 index 00000000..bd2f4f46 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qsheet.qml @@ -0,0 +1,9 @@ +import bb.cascades $CascadesVersion$ + +Sheet { + Page { + Container { + + } + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qtab.qml b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qtab.qml new file mode 100644 index 00000000..28146a83 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/Shared/qtab.qml @@ -0,0 +1,25 @@ +import bb.cascades $CascadesVersion$ + +TabbedPane { + id: tabbedPane + + Tab { + title: "Tab 1" + + content: Page { + Label { + text: "This is tab 1." + } + } + } + + Tab { + title: "Tab 2" + + content: Page { + Label { + text: "This is tab 2." + } + } + } +} diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/cascades-default.vcxproj b/src_vs2012/Package/Templates/VCWizards/BlackBerry/cascades-default.vcxproj new file mode 100644 index 00000000..db3c7afc --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/cascades-default.vcxproj @@ -0,0 +1,54 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + Cascades + armle-v7 + Device-Debug + + + qcc + Cascades + armle-v7 + Device-Release + + + + + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-default.vcxproj b/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-default.vcxproj new file mode 100644 index 00000000..76db3fbd --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-default.vcxproj @@ -0,0 +1,50 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + + + qcc + armle-v7 + + + + + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-libshared-default.vcxproj b/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-libshared-default.vcxproj new file mode 100644 index 00000000..0adb2481 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-libshared-default.vcxproj @@ -0,0 +1,52 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + DynamicLibrary + + + qcc + armle-v7 + DynamicLibrary + + + + + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-libstatic-default.vcxproj b/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-libstatic-default.vcxproj new file mode 100644 index 00000000..c8e94134 --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/native-libstatic-default.vcxproj @@ -0,0 +1,52 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + StaticLibrary + + + qcc + armle-v7 + StaticLibrary + + + + + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + diff --git a/src_vs2012/Package/Templates/VCWizards/BlackBerry/opengl-default.vcxproj b/src_vs2012/Package/Templates/VCWizards/BlackBerry/opengl-default.vcxproj new file mode 100644 index 00000000..76db3fbd --- /dev/null +++ b/src_vs2012/Package/Templates/VCWizards/BlackBerry/opengl-default.vcxproj @@ -0,0 +1,50 @@ + + + + + + Debug + BlackBerry + + + Release + BlackBerry + + + + + + + + + + qcc + armle-v7 + + + qcc + armle-v7 + + + + + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + diff --git a/src_vs2012/Package/ToolWindows/TargetNavigatorControl.xaml b/src_vs2012/Package/ToolWindows/TargetNavigatorControl.xaml new file mode 100644 index 00000000..dda3a965 --- /dev/null +++ b/src_vs2012/Package/ToolWindows/TargetNavigatorControl.xaml @@ -0,0 +1,294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +