In C++ Builder 10.3.1 I am using Indy TCP client-server components (TIdTCPClient & TIdTCPServer) to create an example of encrypted communication with OpenSSL. I'm using this sample code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
C1->Connect();
C1->Socket->Write(4);
int res = C1->Socket->ReadInt32();
C1->Disconnect();
ShowMessage(res);
}
void __fastcall TForm1::S1Execute(TIdContext *AContext)
{
int x = AContext->Connection->Socket->ReadInt32();
AContext->Connection->Socket->Write(x * x);
AContext->Connection->Disconnect();
}
Without OpenSSL everything works fine, but after adding IdSSLIOHandlerSocketOpenSSL1 and IdServerIOHandlerSSLOpenSSL1 components and assigning them to TCP client-server components (IOHandler property) I get the error "Could not load SSL library". In that case I used OpenSSL 1.0.2 binaries (ssleay32.dll and libeay32.dll) from https://indy.fulgan.com/SSL/.
But, I managed to find older OpenSSL libraries that were successfully loaded. Still, then I get the following error:
Error connecting with SSL. EOF was observed that violates the protocol.
How to make this work?
EDIT: After setting PassThrough to false both on client & server side I get:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
EDIT: Here is my Form's full code and DFM:
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdSSLIOHandlerSocketOpenSSL1->PassThrough = false;
C1->Connect();
C1->Socket->Write(5);
int res = C1->Socket->ReadInt32();
C1->Disconnect();
ShowMessage(res);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::S1Execute(TIdContext *AContext)
{
int x = AContext->Connection->Socket->ReadInt32();
AContext->Connection->Socket->Write(x * x);
AContext->Connection->Disconnect();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::S1Connect(TIdContext *AContext)
{
static_cast<TIdSSLIOHandlerSocketOpenSSL*>(AContext->Connection->Socket)->PassThrough = false;
}
//---------------------------------------------------------------------------
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdCustomTCPServer.hpp>
#include <IdIOHandler.hpp>
#include <IdIOHandlerSocket.hpp>
#include <IdIOHandlerStack.hpp>
#include <IdServerIOHandler.hpp>
#include <IdSSL.hpp>
#include <IdSSLOpenSSL.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <IdTCPServer.hpp>
#include <IdContext.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TIdTCPClient *C1;
TIdTCPServer *S1;
TIdServerIOHandlerSSLOpenSSL *IdServerIOHandlerSSLOpenSSL1;
TIdSSLIOHandlerSocketOpenSSL *IdSSLIOHandlerSocketOpenSSL1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall S1Execute(TIdContext *AContext);
void __fastcall S1Connect(TIdContext *AContext);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.dfm
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 299
ClientWidth = 635
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 24
Top = 208
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object C1: TIdTCPClient
IOHandler = IdSSLIOHandlerSocketOpenSSL1
ConnectTimeout = 0
Host = '127.0.0.1'
IPVersion = Id_IPv4
Port = 5577
ReadTimeout = -1
Left = 168
Top = 96
end
object S1: TIdTCPServer
Active = True
Bindings = <
item
IP = '0.0.0.0'
Port = 5577
end>
DefaultPort = 0
IOHandler = IdServerIOHandlerSSLOpenSSL1
OnConnect = S1Connect
OnExecute = S1Execute
Left = 240
Top = 96
end
object IdServerIOHandlerSSLOpenSSL1: TIdServerIOHandlerSSLOpenSSL
SSLOptions.Mode = sslmUnassigned
SSLOptions.VerifyMode = []
SSLOptions.VerifyDepth = 0
Left = 464
Top = 40
end
object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL
Destination = '127.0.0.1:5577'
Host = '127.0.0.1'
MaxLineAction = maException
Port = 5577
DefaultPort = 0
SSLOptions.Mode = sslmUnassigned
SSLOptions.VerifyMode = []
SSLOptions.VerifyDepth = 0
Left = 320
Top = 184
end
end
after adding IdSSLIOHandlerSocketOpenSSL1 and IdServerIOHandlerSSLOpenSSL1 components and assigning them to TCP client-server components (IOHandler property) I get the error "Could not load SSL library".
Make sure that you have up-to-date OpenSSL 1.0.2 DLLs (Indy does not yet support OpenSSL 1.1.x) in your app's folder, or in a folder that you specify with the IdOpenSSLSetLibPath() function in IdSSLOpenSSLHeaders.hpp at program startup.
If you are still having the error, you can use Indy's WhichFailedToLoad() function in IdSSLOpenSSLHeaders.hpp to find out why the DLLs are not loading - either because the DLLs themselves cannot be found or loaded into memory, or because they are missing required exported functions that Indy uses.
In that case I used OpenSSL 1.0.2 binaries (ssleay32.dll and libeay32.dll) from https://indy.fulgan.com/SSL/.
Those DLLs are known to work fine with Indy.
then I get the following error:
Error connecting with SSL. EOF was observed that violates the protocol.
That error means the server closed the TCP connection on its end while the client was still performing the SSL/TLS handshake. That can happen, for instance, if an exception is raised on the server side. By default, TIdTCPServer handles an uncaught exception by closing the socket.
It is a common mistake not to set the TIdSSLIOHandlerSocketOpenSSL::PassThrough property to false on the server side. It needs to be set manually, as TIdTCPServer does not set it automatically, to allow users to decide which port(s) should use SSL/TLS. PassThrough needs to be set to true on both ends of the connecton.
On the client side, you can set PassThrough before calling Connect() (ie, for implicit SSL) or after (ie, for STARTTLS-like commands).
On the server side, you can set PassThrough in the OnConnect event (ie, for implicit SSL) or in the OnExecute event (ie, for STARTTLS-like commands).
In your example, try this:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdSSLIOHandlerSocketOpenSSL1->PassThrough = false;
C1->Connect();
C1->Socket->Write(4);
int res = C1->Socket->ReadInt32();
C1->Disconnect();
ShowMessage(res);
}
void __fastcall TForm1::S1Connect(TIdContext *AContext)
{
static_cast<TIdSSLIOHandlerSocketOpenSSL*>(AContext->Connection->Socket)->PassThrough = false;
}
void __fastcall TForm1::S1Execute(TIdContext *AContext)
{
int x = AContext->Connection->Socket->ReadInt32();
AContext->Connection->Socket->Write(x * x);
AContext->Connection->Disconnect();
}
And, needless to say, make sure the IOHandlers on both sides are configured similarly to use compatible SSL/TLS protocol versions, certificates, etc.
Make sure you use the 32 bits OpenSSL DLLs (i386-win32) if your program is 32 bits.
Related
How would someone detect when a user enters tablet mode on a Windows 10 device with Delphi code?
Can someone show a code example for this?
I don't want to detect if the user has a tablet or not. I simply want to see whether they're in tablet mode or not. What would be the best way to do this?
You can use UIViewSettings.UserInteractionMode API. Please refer to #Raymond blog: "How can I detect whether my PC is in tablet mode?", there are UWP and desktop ways in C++ you can refer to.
More detailed information you can check this thread.
But you need find out how to do in Delphi. There are some related issues hope they are helpful for you:
delphi - call external WinAPI function
Can we call Native Windows API from Delphi?
I deleted the previous variant (based on [SO]: How can I detect when Windows 10 enters tablet mode in a Windows Forms application? (#CheeseLover's answer) (pointed out by #Remko's comment)) because it's a totally different scenario (doesn't have anything to do with Win running on desktop).
I spent some time on [MS.DevBlogs]: Raymond - How can I detect whether my PC is in tablet mode? (pointed out in #RitaHan-MSFT's answer (+1)), and clearly, that's the way to go.
I don't know how to "translate" the code into Delphi, as many years passed since I wrote significant amounts of code in it (but I'm sure it's possible), so I did the next best thing: wrote a C++ .dll (containing a modified / improved version of Raymond's code) that is called from Delphi.
Note: VStudio is required to build the .dll, I used 2015 Community Edition, which is free and can be downloaded from [VStudio]: Visual Studio 2015 and other Products (you need an MS account though).
dll.cpp:
#include <wrl/client.h>
#include <windows.ui.viewmanagement.h>
#include <UIViewSettingsInterop.h>
#include <wrl/wrappers/corewrappers.h>
namespace WRL = Microsoft::WRL;
namespace VM = ABI::Windows::UI::ViewManagement;
class Backend {
public:
static Backend &instance() {
static Backend m_instance;
return m_instance;
}
WRL::ComPtr<IUIViewSettingsInterop> interop() { return m_interop; }
private:
Backend() {
HRESULT res = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
m_comInit = (res == S_OK) || (res == S_FALSE);
if (m_comInit || (res == RPC_E_CHANGED_MODE)) {
res = Windows::Foundation::GetActivationFactory(WRL::Wrappers::HStringReference(
RuntimeClass_Windows_UI_ViewManagement_UIViewSettings).Get(), &m_interop);
}
}
Backend(const Backend &other) = delete;
Backend &operator =(const Backend &other) = delete;
~Backend() {
if (m_interop) { m_interop.Reset(); }
if (m_comInit) { CoUninitialize(); }
}
bool m_comInit = false;
WRL::ComPtr<IUIViewSettingsInterop> m_interop = nullptr;
};
/*!
Gets Tablet mode value.
\param hwnd Window handle to get the mode for
\returns:
1 - Tablet mode ON
0 - Tablet mode OFF
-X - Error
*/
extern "C" __declspec(dllexport) int GetTabletMode(HWND hwnd) {
WRL::ComPtr<IUIViewSettingsInterop> interop = Backend::instance().interop();
if (!interop) { return -3; }
WRL::ComPtr<VM::IUIViewSettings> viewSettings;
HRESULT res = interop->GetForWindow(hwnd != NULL ? hwnd : GetConsoleWindow(), IID_PPV_ARGS(&viewSettings));
if (!viewSettings) { return -2; }
VM::UserInteractionMode currentMode;
res = viewSettings->get_UserInteractionMode(¤tMode);
int ret = -1;
switch (currentMode) {
case VM::UserInteractionMode_Mouse: ret = 0; break;
case VM::UserInteractionMode_Touch: ret = 1; break;
default: ret = -1;
}
viewSettings.Reset();
return ret;
}
Below is the Delphi relevant code (only the unit, as the rest can easily be manufactured, and there's no point placing it all here).
Unit0.pas:
unit Unit0;
interface
uses
Forms, Dialogs, Controls, StdCtrls, Classes;
type
TForm0 = class(TForm)
CheckButton: TButton;
procedure CheckButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form0: TForm0;
function GetTabletMode(hwnd: THandle): Integer cdecl; external 'TabletUtils.dll';
implementation
{$R *.dfm}
procedure TForm0.CheckButtonClick(Sender: TObject);
var
TabletModeStr: String;
begin
case GetTabletMode(Self.Handle) of
0 : TabletModeStr := 'OFF';
1 : TabletModeStr := 'ON';
else TabletModeStr := 'ERROR';
end;
MessageDlg('Tablet Mode: ' + TabletModeStr, mtInformation, [mbOK], 0);
end;
end.
Output:
[cfati#CFATI-5510-0:e:\Work\Dev\StackOverflow\q056321591]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***
[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x86
[prompt]> dir /b
App0.cfg
App0.dof
App0.dpr
App0.exe
App0.res
dll.cpp
other
Unit0.dcu
Unit0.ddp
Unit0.dfm
Unit0.pas
[prompt]> cl /nologo /DDLL /DNDEBUG /DUSRDLL /D_WINDOWS /MT dll.cpp /link /NOLOGO /DLL /OUT:TabletUtils.dll ole32.lib runtimeobject.lib
dll.cpp
Creating library TabletUtils.lib and object TabletUtils.exp
[prompt]> dir /b
App0.cfg
App0.dof
App0.dpr
App0.exe
App0.res
dll.cpp
dll.obj
other
TabletUtils.dll
TabletUtils.exp
TabletUtils.lib
Unit0.dcu
Unit0.ddp
Unit0.dfm
Unit0.pas
[prompt]> App0.exe
[prompt]>
In the screenshot below, I ran the application:
On my laptop (Win 10) with Desktop mode (right side)
On a Win 10 VM with Tablet mode (left side). Note that I had to copy:
App0.exe
TabletUtils.dll
I am getting a strange error when creating the DirectX 12 command queue.
Other DX12 applications are able to launch successfully on the same machine.
My computer uses the D3D_FEATURE_LEVEL_11_0 if block.
The graphics card used for testing is NVIDIA GT 740, with 361.75 drivers
This is the code in use (minimized):
#include <Windows.h>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <comdef.h>
#include <D3d12sdklayers.h>
#include <string>
#pragma comment(lib,"d3d12.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"d3dcompiler.lib")
using namespace std;
LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(nCmdShow);
UNREFERENCED_PARAMETER(lpCmdLine);
wchar_t* WindowClass = L"Papergate";
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
wc.lpszClassName = WindowClass;
if (!RegisterClassEx(&wc))
{
return 1;
}
HWND hwnd = CreateWindowEx(NULL, wc.lpszClassName, WindowClass,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
if (!hwnd)
{
UnregisterClass(WindowClass, hInstance);
return 1;
}
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
ID3D12Device* device;
HRESULT result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_12_1,
__uuidof(ID3D12Device), (void**)&device);
if (FAILED(result))
{
result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_12_0,
__uuidof(ID3D12Device), (void**)&device);
if (FAILED(result))
{
result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0,
__uuidof(ID3D12Device), (void**)&device);
if (FAILED(result)) {
_com_error error(result);
MessageBox(hwnd, error.ErrorMessage(),
(wstring(L"Error: ") + to_wstring(__LINE__)).c_str(),
MB_OK);
return 2;
}
}
}
ID3D12Debug* debugInterface;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface))))
{
debugInterface->EnableDebugLayer();
}
D3D12_COMMAND_QUEUE_DESC commandQueueDesc;
commandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
commandQueueDesc.NodeMask = 0;
commandQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
commandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
ID3D12CommandQueue* commandQueue;
result = device->CreateCommandQueue(&commandQueueDesc, __uuidof(ID3D12CommandQueue), (void**)&commandQueue);
if (FAILED(result)) {
_com_error error(result);
MessageBox(hwnd, error.ErrorMessage(),
(wstring(L"Error: ") + to_wstring(__LINE__)).c_str(), MB_OK);
result = device->GetDeviceRemovedReason();
error = _com_error(result);
MessageBox(hwnd, error.ErrorMessage(),
(wstring(L"Error: ") + to_wstring(__LINE__)).c_str(), MB_OK);
debugInterface->Release(); device->Release(); return 2;
}
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while (GetMessage(&msg, NULL, 0, 0) && msg.message != WM_QUIT)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
commandQueue->Release();
device->Release();
UnregisterClass(WindowClass, hInstance);
return 0;
}
I am getting the following errors on lines 97 and 102, respectively:
The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.
Second error:
The GPU will not respond to more commands, most likely because some other application submitted invalid commands.
The calling application should re-create the device and continue.
This seems quite likely to be a driver bug of some kind. Check to see if there are updated drivers for your hardware. You should try using the Direct3D12 Game templates in this VSIX and see if they hit the same kind of issue (for more details on the templates see this blog post).
Your cascade pattern of calling D3D12CreateDevice for various feature levels is unusual and is not necessary. If your application can run on Direct3D Feature Level 11.0 or greater, then just use D3D_FEATURE_LEVEL_11_0 once. You should pass whatever your minimum supported feature level is to this function.
If the Direct3D 12 device does support a higher feature level, you can discover that by using CheckFeatureSupport either by checking for the individual features or by using D3D12_FEATURE_FEATURE_LEVELS:
// Create the DX12 API device object.
DX::ThrowIfFailed(D3D12CreateDevice(
adapter.Get(),
m_d3dMinFeatureLevel,
IID_PPV_ARGS(&m_d3dDevice)
));
// Determine maximum supported feature level for this device
static const D3D_FEATURE_LEVEL s_featureLevels[] =
{
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
};
D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels =
{
_countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0
};
HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,
&featLevels, sizeof(featLevels));
if (SUCCEEDED(hr))
{
m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel;
}
else
{
m_d3dFeatureLevel = m_d3dMinFeatureLevel;
}
Keep in mind that D3D_FEATURE_LEVEL_12_0 and D3D_FEATURE_LEVEL_12_1 are essentially just D3D_FEATURE_LEVEL_11_1 with a few optional features made mandatory. If your app is already checking for them at 11.x then there's no reason to 'require' 12.0 or 12.1. See MSDN.
For the vast majority of Direct3D 12 games & applications, D3D_FEATURE_LEVEL_11_0 or D3D_FEATURE_LEVEL_11_1 are good choices. Keep in mind that while AMD/ATI supported Feature Level 11.1 pretty early, NVIDIA DirectX 11 parts only supported 11.0 with some optional features for some time.
Using C++ Builder 10 Seattle (CX10).
I have a .chm with map IDs for certain topics. I can load the topics into an external window like this:
#include "Vcl.HTMLHelpViewer.hpp"
#pragma link "Vcl.HTMLHelpViewer"
// In the main form constructor:
Application->HelpFile = ExtractFilePath(Application->ExeName) + "MyHelp.chm";
// In button click event handler:
Application->HelpContext(10001);
This is great for many situations, but sometimes I want to embed the context-specific help within my TForm, such as on a TPanel. I found pieces of information about using WinAPI functions FindWindow and SetParent. So I tried this:
HWND t_hwnd = FindWindow(NULL, "My Help File");
if (t_hwnd)
{
// HelpPanel is a TPanel with no properties adjusted from default
::SetParent(t_hwnd, HelpPanel->Handle);
}
Which compiles, links, runs and doesn't crash... but the subsequent call to Application->HelpContext(10001) still displays the topic in the external window, and not in the HelpPanel.
I am guessing that the easy-to-use Application->HelpContext call isn't what I need for redirecting to a VCL control, but I don't know where to look next.
Following up on the comments, here is where I am: I found out the ilink32 error (see my comment, below) was because I need to load HHCTRL.ocx in order to make a call to HtmlHelpA. So here is my test project code, a form with a TRadioGroup and TPanel. Only one radio button attempts to place the topic on the TPanel; the rest use Application->HelpContext. All of this compiles, links and runs, but the call to place the help on TPanel doesn't do anything visible.
Really hoping somebody can help... thanks.
// MainFrm.dfm
object MainForm: TMainForm
Left = 0
Top = 0
Caption = 'MainForm'
ClientHeight = 486
ClientWidth = 686
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object FunctionsRadioGroup: TRadioGroup
Left = 8
Top = 8
Width = 185
Height = 105
Caption = 'EDITS Language Functions'
Items.Strings = (
'LOOKUP'
'RLOOKUP'
'ILOOKUP'
'STRCPY')
TabOrder = 0
OnClick = FunctionsRadioGroupClick
end
object HelpPanel: TPanel
Left = 199
Top = 8
Width = 490
Height = 477
Caption = 'HelpPanel'
TabOrder = 1
end
end
// MainFrm.h
#ifndef MainFrmH
#define MainFrmH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
typedef HWND (WINAPI *FPHH) (HWND, LPCSTR, UINT, DWORD);
// Map IDs in my CHM
#define LANG_FUNC_LOOKUP 10001
#define LANG_FUNC_RLOOKUP 10002
#define LANG_FUNC_STRCPY 10004
#define LANG_FUNC_ILOOKUP 10003
class TMainForm : public TForm
{
__published: // IDE-managed Components
TRadioGroup *FunctionsRadioGroup;
TPanel *HelpPanel;
void __fastcall FunctionsRadioGroupClick(TObject *Sender);
private: // User declarations
HINSTANCE FHHCTRL_OCX_INST;
FPHH htmlHelp;
bool __fastcall load_HHCTRL_OCX();
public: // User declarations
__fastcall TMainForm(TComponent* Owner);
__fastcall ~TMainForm();
void __fastcall DoShowEmbeddedHelp(TPanel* ThePanel, NativeInt TheTopicID);
};
//---------------------------------------------------------------------------
extern PACKAGE TMainForm *MainForm;
//---------------------------------------------------------------------------
#endif
// MainFrm.cpp
#include <vcl.h>
#pragma hdrstop
#include "MainFrm.h"
#include <Vcl.HTMLHelpViewer.hpp>
#include <HtmlHelp.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Vcl.HTMLHelpViewer"
//#pragma link "htmlhelp.lib"
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
Application->HelpFile = ExtractFilePath(Application->ExeName) +
"MyHelpFile.chm";
FHHCTRL_OCX_INST = 0;
} // ctor
//---------------------------------------------------------------------------
__fastcall TMainForm::~TMainForm()
{
if (FHHCTRL_OCX_INST > 0)
{
FreeLibrary(FHHCTRL_OCX_INST);
}
}// dtor
//---------------------------------------------------------------------------
void __fastcall TMainForm::FunctionsRadioGroupClick(TObject *Sender)
{
TRadioGroup* t_radio = dynamic_cast<TRadioGroup*>(Sender);
if (t_radio)
{
switch (t_radio->ItemIndex)
{
case 0:
//Application->HelpContext(LANG_FUNC_LOOKUP);
DoShowEmbeddedHelp(HelpPanel, LANG_FUNC_LOOKUP);
break;
case 1:
Application->HelpContext(LANG_FUNC_RLOOKUP);
break;
case 2:
Application->HelpContext(LANG_FUNC_ILOOKUP);
break;
case 3:
Application->HelpContext(LANG_FUNC_STRCPY);
break;
}
}
}
//---------------------------------------------------------------------------
bool __fastcall TMainForm::load_HHCTRL_OCX()
{
bool t_is_loaded = (FHHCTRL_OCX_INST > 0);
if (!t_is_loaded)
{
FHHCTRL_OCX_INST = LoadLibrary("HHCTRL.OCX");
if (FHHCTRL_OCX_INST > 0)
{
(FARPROC&) htmlHelp = GetProcAddress(FHHCTRL_OCX_INST, "HtmlHelpA");
if (htmlHelp)
{
t_is_loaded = true;
}
}
}
return t_is_loaded;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::DoShowEmbeddedHelp(TPanel* ThePanel, NativeInt TheTopicID)
{
HH_WINTYPE wintypedef;
AnsiString t_helpfile = ExtractFilePath(Application->ExeName) + "MyHelpFile.chm";
AnsiString TheWinName = "HelpPanel";
if (!FileExists(t_helpfile))
{
MessageDlg(AnsiString("Help file not found: ") + t_helpfile,
mtError, TMsgDlgButtons() << mbOK, 0);
return;
}
// Zero the structure
memset(&wintypedef, 0, sizeof(HH_WINTYPE));
// Prepare the properties
wintypedef.cbStruct = sizeof(wintypedef);
wintypedef.fUniCodeStrings = false;
wintypedef.pszType = TheWinName.c_str();
wintypedef.fsValidMembers =
HHWIN_PARAM_PROPERTIES |
HHWIN_PARAM_STYLES |
HHWIN_PARAM_EXSTYLES |
HHWIN_PARAM_RECT |
HHWIN_PARAM_NAV_WIDTH |
HHWIN_PARAM_SHOWSTATE |
HHWIN_PARAM_TB_FLAGS |
HHWIN_PARAM_EXPANSION;
wintypedef.fsWinProperties =
HHWIN_PROP_NOTITLEBAR |
HHWIN_PROP_NO_TOOLBAR |
HHWIN_PROP_NODEF_STYLES |
HHWIN_PROP_NODEF_EXSTYLES |
HHWIN_PROP_TRI_PANE;
wintypedef.pszCaption = "";
wintypedef.dwStyles = WS_VISIBLE | WS_CHILDWINDOW;
wintypedef.dwExStyles = WS_EX_LEFT;
wintypedef.rcWindowPos =
Rect(0, 0, ThePanel->ClientWidth, ThePanel->ClientHeight);
wintypedef.nShowState = SW_SHOW;
wintypedef.fsToolBarFlags = HHWIN_BUTTON_PRINT | HHWIN_BUTTON_BACK ;
wintypedef.fNotExpanded = true;
if (load_HHCTRL_OCX())
{
if ((int)htmlHelp(0, NULL, HH_SET_WIN_TYPE, (DWORD)&wintypedef) < 0)
{
ShowMessage("Help failed on topic");
}
else
{
/* NOTE: This was close, but wrong.
int HelpWinHandle =
(int)htmlHelp(ThePanel->Handle, "HelpPanel", HH_HELP_CONTEXT, TheTopicID);
*/
AnsiString t_fn = t_helpfile + AnsiString(">HelpPanel");
int HelpWinHandle =
(int)htmlHelp(ThePanel->Handle, t_fn.c_str(), HH_HELP_CONTEXT, TheTopicID);
}
}
} // DoShowEmbeddedHelp
//---------------------------------------------------------------------------
This is deep going into HTMLHelp API (written in C++ 20 years ago by Ralph Walden). You maybe warned ...
I have experience in help authoring and I'm not a C++ programmer. So, the HTMLHelp Viewer hh.exe is a wrapper for Internet Explorer API showing the CHM's HTML topics in the content pane on the right.
You know "Application->HelpContext(10001);" is calling the Help Viewer with the specified topicId "10001" always. Embedded help is less in use and today not what the users want. A second help window is easier of course.
Some ideas and a trick e.g. to shrink the viewer done by the help author (creator of the CHM file) you'll see at:
Microsoft HTML Help - Get the topic page URL from the topic ID
Further information - sorry Delphi - you'll find at:
How to control/remove borders of embedded chm help file in delphi windows/vcl application?
HTH
All right, I finally figured it out.
In the code I posted for function TMainForm::DoShowEmbeddedHelp, I did not properly prepare the second parameter to HtmlHelpA. It SHOULD be this:
AnsiString t_fn = t_helpfile + AnsiString(">HelpPanel");
HelpWinHandle =
(int)htmlHelp(ThePanel->Handle, t_fn.c_str(), HH_HELP_CONTEXT, TheTopicID);
Now I am getting the result I wanted.
Is there any support of OpenCV graphics library is available for Windows Phone 8 and Windows 8. I made a search on Google but didn't find any resource related with OpenCV to connect with Windows Phone 8 / Windows 8. If any of you know more about this please help me, and provide some link to reach the library.
This is the latest information what I get from OpenCV team.
OpenCV development team is working on port for Windows RT. Here is current development branch for WinRT(https://github.com/asmorkalov/opencv/tree/winrt). You can build it for ARM using Visual Studio Express for Windows 8 and Platform SDK.
Open Visual Studio development console.
Setup environment for cross compilation by command "C:\Program Files(x86)\Microsoft
Visual Studio 11.0\VC\bin\x86_arm\vcvarsx86_arm.bat"
cd <opencv_source_dir>/platforms/winrt/
run scripts/cmake_winrt.cmd
run ninja
Alternatively you can use nmake instead ninja. You need to edit cmake_winrt.cmd and change project generator fro -GNinja to -G "NMake Makefiles". Only algorithmic part of the library is supported now, no tbb, no UI, no video IO.
Please check the below given URL from more details.
http://answers.opencv.org/question/9847/opencv-for-windows-8-tablet/?answer=9851#post-id-9851
By windows-8, I guess you mean winRT ? AFAIK, there is no official port to winRT. You need to compile it by yourself as a Win8 Store DLL for instance, so that you can reference it from a Win8 Store Application.
Just start by opencv-core, then add the lib you need, one by one, because all the components will not be able to compile (for instance, opencv-highgui is highly dependant on Windows API which is not fully compatible with Win8 Store Apps).
You'll also need to code by yourself some Win32 methods used by OpenCV and not accessible from Win8 App like GetSystemInfo(), GetTempPathA(), GetTempFileNameA() and all methods related to thread local storage (TLS).
I've been able to use a small subset of OpenCV in WinRT by compiling opencv_core, opencv_imgproc and zlib, as 3 seperate static libs. I've added one another, called opencv_winrt, that contains only the two following files:
opencv_winrt.h
#pragma once
#include "combaseapi.h"
void WINAPI GetSystemInfo(
_Out_ LPSYSTEM_INFO lpSystemInfo
);
DWORD WINAPI GetTempPathA(
_In_ DWORD nBufferLength,
_Out_ char* lpBuffer
);
UINT WINAPI GetTempFileNameA(
_In_ const char* lpPathName,
_In_ const char* lpPrefixString,
_In_ UINT uUnique,
_Out_ char* lpTempFileName
);
DWORD WINAPI TlsAlloc();
BOOL WINAPI TlsFree(
_In_ DWORD dwTlsIndex
);
LPVOID WINAPI TlsGetValue(
_In_ DWORD dwTlsIndex
);
BOOL WINAPI TlsSetValue(
_In_ DWORD dwTlsIndex,
_In_opt_ LPVOID lpTlsValue
);
void WINAPI TlsShutdown();
# define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
opencv_winrt.cpp
#include "opencv_winrt.h"
#include <vector>
#include <set>
#include <mutex>
#include "assert.h"
void WINAPI GetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
{
GetNativeSystemInfo(lpSystemInfo);
}
DWORD WINAPI GetTempPathA(DWORD nBufferLength, char* lpBuffer)
{
return 0;
}
UINT WINAPI GetTempFileNameA(const char* lpPathName, const char* lpPrefixString, UINT uUnique, char* lpTempFileName)
{
return 0;
}
// Thread local storage.
typedef std::vector<void*> ThreadLocalData;
static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
static std::set<ThreadLocalData*> allThreadData;
static DWORD nextTlsIndex = 0;
static std::vector<DWORD> freeTlsIndices;
static std::mutex tlsAllocationLock;
DWORD WINAPI TlsAlloc()
{
std::lock_guard<std::mutex> lock(tlsAllocationLock);
// Can we reuse a previously freed TLS slot?
if (!freeTlsIndices.empty())
{
DWORD result = freeTlsIndices.back();
freeTlsIndices.pop_back();
return result;
}
// Allocate a new TLS slot.
return nextTlsIndex++;
}
_Use_decl_annotations_ BOOL WINAPI TlsFree(DWORD dwTlsIndex)
{
std::lock_guard<std::mutex> lock(tlsAllocationLock);
assert(dwTlsIndex < nextTlsIndex);
assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), dwTlsIndex) == freeTlsIndices.end());
// Store this slot for reuse by TlsAlloc.
try
{
freeTlsIndices.push_back(dwTlsIndex);
}
catch (...)
{
return false;
}
// Zero the value for all threads that might be using this now freed slot.
for each (auto threadData in allThreadData)
{
if (threadData->size() > dwTlsIndex)
{
threadData->at(dwTlsIndex) = nullptr;
}
}
return true;
}
_Use_decl_annotations_ LPVOID WINAPI TlsGetValue(DWORD dwTlsIndex)
{
ThreadLocalData* threadData = currentThreadData;
if (threadData && threadData->size() > dwTlsIndex)
{
// Return the value of an allocated TLS slot.
return threadData->at(dwTlsIndex);
}
else
{
// Default value for unallocated slots.
return nullptr;
}
}
_Use_decl_annotations_ BOOL WINAPI TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
{
ThreadLocalData* threadData = currentThreadData;
if (!threadData)
{
// First time allocation of TLS data for this thread.
try
{
threadData = new ThreadLocalData(dwTlsIndex + 1, nullptr);
std::lock_guard<std::mutex> lock(tlsAllocationLock);
allThreadData.insert(threadData);
currentThreadData = threadData;
}
catch (...)
{
if (threadData)
delete threadData;
return false;
}
}
else if (threadData->size() <= dwTlsIndex)
{
// This thread already has a TLS data block, but it must be expanded to fit the specified slot.
try
{
std::lock_guard<std::mutex> lock(tlsAllocationLock);
threadData->resize(dwTlsIndex + 1, nullptr);
}
catch (...)
{
return false;
}
}
// Store the new value for this slot.
threadData->at(dwTlsIndex) = lpTlsValue;
return true;
}
// Called at thread exit to clean up TLS allocations.
void WINAPI TlsShutdown()
{
ThreadLocalData* threadData = currentThreadData;
if (threadData)
{
{
std::lock_guard<std::mutex> lock(tlsAllocationLock);
allThreadData.erase(threadData);
}
currentThreadData = nullptr;
delete threadData;
}
}
And I modify the file cvconfig.h: I've commented out every #define, except PACKAGE* and VERSION, and I added #include "opencv_winrt.h" at the end.
Just a hint - there is a C# wrapper for OpenCV called EmguCV (http://www.emgu.com/wiki/index.php/Main_Page), by looking at the forum posts I see that there is some activity towards using it on Windows 8 but it's hard to tell if it's now working since the posts claiming issues are quite old. I'd suggest you just give it a try and see if this C# wrapper is able to run on Windows Phone 8, I think it should definitely run on Windows 8.
I am trying to use Libnet11 function:
int libnet_write_raw_ipv6 (libnet_t *l, u_int8_t *packet, u_int32_t size)
to inject IPv6 packet on network layer.
I had created IPv6 packet and captured it
with Wireshark. Wireshark reported:
malformed packet(wireshark says that next
header value in IPv6 is wrong and payload
size is too big in my opinion)
I hope, someone could help me with minimal code example,
showing how to manually build IPv6 packet (with ICMPv6
extension header) with libnet11 (libnet_write_raw_ipv6()).
I assume that the minimal code might look like this:
packet_len = 40 + 16; // 40B ~ IPv6 packet, 16B ~ ICMPv6 header
u_char *buf = NULL;
struct ip6_hdr *ip6 = NULL;
struct icmp6_hdr *icmp6 = NULL;
l = libnet_init();
if ( (buf = malloc(packet_len)) == NULL ) {
// error
}
// create IPv6 header
ip6 = (struct ip6_hdr *) buf;
ip6->ip6_flow = 0;
ip6->ip6_vfc = 6 << 4;
ip6->ip6_plen = 16; // ICMPv6 packet size
ip6->ip6_nxt = IPPROTO_ICMPV6; // 0x3a
ip6->ip6_hlim = 64;
memcpy(&(ip6->ip6_src), &src_addr, sizeof(struct in6_addr));
memcpy(&(ip6->ip6_dst), &dst_addr, sizeof(struct in6_addr));
// create ICMPv6 header
icmp6 = (struct icmp6_hdr *) (buf + 40); // 40B ~ IPv6 packet size
icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
icmp6->icmp6_code = 0;
icmp6->icmp6_cksum= 0;
icmp6->icmp6_data32[0] = 0;
libnet_do_checksum(l, (u_int8_t *)buf, IPPROTO_ICMPV6, packet_len);
written = libnet_write_raw_ipv6(l, buf, packet_len);
if ( written != packet_len )
perror("Failed to send packet");
libnet_destroy(l);
free(buf);
I tried to find code examples but with no success.
Thank you in advance.
Martin
If you're using C++, then I'd recommend you libtins, a packet crafting a sniffing library. This short snippet does exactly what you want:
#include <tins/tins.h>
using namespace Tins;
void test(const IPv6Address &dst, const IPv6Address &src) {
PacketSender sender;
IPv6 ipv6 = IPv6(dst, src) / ICMPv6();
ipv6.hop_limit(64);
sender.send(ipv6);
}
int main() {
// now use it
test("f0ef:1234::1", "f000::1");
}
You can create it with raw sockets though. I also had to do something similar but couldn't find anything as a reference.
To do it with raw sockets, this link gives you a nice explanation