i plan to call c++ dll from autohotkey
but i couldn't make it work.
if anyone help me much appreciate
this is what i done and tried
and it return null
hModule := DllCall("LoadLibrary", "Str", "Captcha.dll", "Ptr")
CaptchaProc := DllCall("GetProcAddress", "Ptr", hModule, "AStr",
"CaptchaProc", "Ptr")
test := DllCall(CaptchaProc, "Str", "test.png", "Str*", out)
MsgBox, %out%
MsgBox, %test%
this is exposure part in captcha.dll
void CaptchaProc(char* path, char* output) {
Mat frame = imread(path), blob;
thanks!
Related
Hello im trying to revert a custom error in YUL inline-assembly
function mint(uint256 amountToMint) external onlyOwner() {
assembly {
// check if exceed maxSupply
let maxSupplySlot := sload(maxSupply.slot)
let res := lt(add(amountToMint, mload(counter.slot)), add(maxSupplySlot, 1))
let ptrError := mload(0x40)
mstore(ptrError, 14)
mstore(add(ptrError, 0x20), 0x4d6178537570706c795265616368) // => "MaxSupplyReach"
if iszero(res) { revert(ptrError, 0x40) }
// populate mapping balanceOf
let ptr := mload(0x40)
mstore(ptr, caller())
mstore(add(ptr, 0x20), balanceOf.slot)
let slot := keccak256(ptr, 0x40)
sstore(slot, amountToMint)
// increment counter
let counterSlot := sload(counter.slot)
let resCounter := add(counterSlot, amountToMint)
sstore(counter.slot, resCounter)
}
}
dont know if i do it correctly my output is like that.
0x000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000004d6178537570706c795265616368
my foundry error when i revert with revert(0,0) it pass but dont pass with custom error
thank's for ur help :)
not sure if you have noticed, but your result is actually what you wanted. It is a hex string, which converted to ASCII yields:
0x000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000004d6178537570706c795265616368
14MaxSupplyReach
with 14 being the string length you stored.
What is the best option to parse a binary structure with Perl6 .
in Perl5 we have the pack/unpack methods on Perl6 they seems experimental
is it possible to use Perl6 grammar to parse binary data let's say i have a file which have records on the following binary format :
struct record {
short int ut_type;
char ut_line[UT_LINESIZE];
char ut_id[4];
char ut_user[UT_NAMESIZE];
char ut_host[UT_HOSTSIZE];
}
is it possible to parse this file with Perl6 grammar ?
What is the best option to parse a binary structure with Perl6?
Especially given that you know about P5's pack/unpack, the new P5pack module is plausibly the appropriate solution. (I haven't tested it. It's new. Aiui it doesn't implement everything and it doesn't mimic P5's pack slavishly. But it's Liz.)
If the new pure P6 implementation of P5's pack interface linked above does not do what you need done, another obvious solution is using the original P5 functions, executed by a regular perl 5 binary, in your P6 code. The following is incomplete / untested but I mean something roughly like:
use Inline::Perl5 ; my \P5 = Inline::Perl5.new ;
my $mem = Buf ... ;
my $hex = P5.call('unpack', 'H*', $mem) ;
(Or, conversely, write the mainline as P5 code, adding P6 code via Inline::Perl6.)
In the current version of P6, which is 6.c, grammars can only process text.
2 years ago P6er "skids" wrote:
"There are enough people wanting binary grammars that I think it will come to be" (written in 2016).
At that time they also put together the following related links:
skid's then new idea for a packing foo { template bar { ... } } construct plus their much older "very old, low level types thoughts".
ShimmerFairy's "thoughts on possible binary grammars in P6 (incomplete)"
Juerd's "RFC: A more Perl6-esque "unpack"".
smls's "Binary Parsing in Perl 6".
masak's "A first approach to pack/unpack in Perl 6".
jnthn's "talk on Grammar::Generative" (video).
I totally agree with raiph's answer and comments, and just want to add a bit.
I think about two types of parsing, one where you can figure it out based on what you find internally, and one where you are using an external schema that describes how the data are arranged. Binary data could be arranged either way msgpack is an example of the former for binary data.
The example you are using, unpacking a binary struct is an example of the later.
It looks like NativeCall CStructs are almost up to doing what you want directly. Perhaps it can already do it and I'm just not aware, but it seems to be lacking the ability to express an embedded sized array. (Is that working yet?)
Without that, your first job is to figure out the structure you're trying to unpack. There are several ways to do this. The first is the easiest, but perhaps most error-prone -- just look at the struct. (I'm going to make up some fake defines so I have real numbers to work with):
record.h:
#define UT_LINESIZE 80
#define UT_IDSIZE 4
#define UT_NAMESIZE 50
#define UT_HOSTSIZE 20
struct record {
short int ut_type;
char ut_line[UT_LINESIZE];
char ut_id[UT_IDSIZE];
char ut_user[UT_NAMESIZE];
char ut_host[UT_HOSTSIZE];
};
Looking at that, I can capture the offset and size of each field:
constant \type-size := nativesizeof(int16);
constant \line-size := 80;
constant \id-size := 4;
constant \user-size := 50;
constant \host-size := 20;
constant \record-size := type-size + line-size + id-size + user-size + host-size;
constant \type-offset := 0;
constant \line-offset := type-offset + type-size;
constant \id-offset := line-offset + line-size;
constant \user-offset := id-offset + id-size;
constant \host-offset := user-offset + id-size;
Some caveats here -- you have to understand your format enough to take into account any alignment or padding. Your example here works more easily than some others might.
That gives us enough information to figure out which bytes in the binary structure map to each field.
Next you need to convert each chunk of bytes into the right Perl type. NativeCall's nativecast routine can do that for you. It can easily turn a chunk of bytes into many Perl data types.
I'm going to make the assumption that your fields are C strings, always correctly terminated by NULs, and are suitable for decoding as UTF8. You can tweak this for other particular cases.
use NativeCall;
class record {
has Int $.ut-type;
has Str $.ut-line;
has Str $.ut-id;
has Str $.ut-user;
has Str $.ut-host;
}
sub unpack-buf(Mu:U $type, Blob $buf, $offset, $size) {
nativecast($type, CArray[uint8].new($buf[$offset ..^ $offset+$size]))
}
sub unpack-record($buf) {
record.new(
ut-type => unpack-buf(int16, $buf, type-offset, type-size),
ut-line => unpack-buf(Str, $buf, line-offset, line-size),
ut-id => unpack-buf(Str, $buf, id-offset, id-size),
ut-user => unpack-buf(Str, $buf, user-offset, user-size),
ut-host => unpack-buf(Str, $buf, host-offset, host-size)
)
}
Then you can seek/read the binary data out of your data file to grab individual records, or just walk through all of it:
my #data = gather {
given 'data'.IO.open(:bin) {
while .read(record-size) -> $buf {
take unpack-record($buf)
}
.close
}
}
Because we've manually copied things from the C struct definition, any changes to that have to be updated, and alignment/padding may always bite us.
Another option is to directly read the C header file and use sizeof() and offsetof() to hand us all the numbers. That will naturally take into account alignment/padding. You can even use TCC from within your Perl code to directly access the header file. Instead of all the constant lines above, you can use this to pull everything right out of the C .h file.
my $tcc = TCC.new('');
$tcc.compile: q:to/END/;
#include <stddef.h>
#include "record.h"
size_t record_size() { return sizeof(struct record); }
size_t type_offset() { return offsetof(struct record, ut_type); }
size_t type_size() { return sizeof(short int); }
size_t line_offset() { return offsetof(struct record, ut_line); }
size_t line_size() { return UT_LINESIZE; }
size_t id_offset() { return offsetof(struct record, ut_id); }
size_t id_size() { return UT_IDSIZE; }
size_t user_offset() { return offsetof(struct record, ut_user); }
size_t user_size() { return UT_NAMESIZE; }
size_t host_offset() { return offsetof(struct record, ut_host); }
size_t host_size() { return UT_HOSTSIZE; }
END
$tcc.relocate;
my &record-size := $tcc.bind('record_size', :(--> size_t));
my &type-offset := $tcc.bind('type_offset', :(--> size_t));
my &type-size := $tcc.bind('type_size', :(--> size_t));
my &line-offset := $tcc.bind('line_offset', :(--> size_t));
my &line-size := $tcc.bind('line_size', :(--> size_t));
my &id-offset := $tcc.bind('id_offset', :(--> size_t));
my &id-size := $tcc.bind('id_size', :(--> size_t));
my &user-offset := $tcc.bind('user_offset', :(--> size_t));
my &user-size := $tcc.bind('user_size', :(--> size_t));
my &host-offset := $tcc.bind('host_offset', :(--> size_t));
my &host-size := $tcc.bind('host_size', :(--> size_t));
I override the function library kernel32.dll in Pascal and OpenProcess function returns 0. Function GetLastError() returns 87 error, that means
ERROR_INVALID_PARAMETER
87 (0x57)
The parameter is incorrect.
What could be wrong?
Program UODll;
const search_window = 'Ultima Online - xxx (The Abyss)';
function FindWindow(C1, C2: PChar): Longint; external 'FindWindowA#user32.dll stdcall';
function GetWindowThreadProcessId(hWnd: Longint; opt: Word): Word; external 'GetWindowThreadProcessId#user32.dll stdcall';
function OpenProcess(dwDesiredAccess: Word; inherit: Byte; pid: Word): Longint; external 'OpenProcess#kernel32.dll stdcall';
function GetProcessId(proc: Longint): Word; external 'GetProcessId#kernel32.dll stdcall';
function GetLastError(): Word; external 'GetLastError#kernel32.dll stdcall';
var
res, err: Word;
wnd, proc: Longint;
Begin
wnd := Findwindow('', search_window);
if (wnd > 0) then
begin
res := GetWindowThreadProcessId(wnd, res);
proc := OpenProcess($0400,0,res);
err := GetLastError();
writeln(IntToStr(proc));
writeln(IntToStr(err));
end;
End.
Im trying to use LongWord and Cardinal, but i have the same error.. Who can help me?)
P.S. its not delphi.. i dont know what is this :) Programm calls UOScript
OpenProcess has declaration
HANDLE WINAPI OpenProcess(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwProcessId
);
dwDesiredAccess and pid are double words that are
typedef unsigned long DWORD;
i.e. 32bit on x86, according to this answer.
But Delphi/Pascal Word type is 16bit.
Also, BOOL is defined as
typedef int BOOL;
So, you should use Integer for inherit instead of Byte
So, your function declaration is incorrect.
Seems you should use Cardinal or LongWord instead of Word in your declarations.
If you use Delphi, you can import Windows module that has all Win API functions defined.
I'm a newbie to both [Microsoft Windows] installers and Inno Setup but I need to know if Inno Setup (or an equivalent) can be used automate the input to a GUI-based windows program, during install, e.g. by clicking on a menu and selecting a sub-item, for instance?
I'm aware of AutoIt and AutoHotkey, as well as NSIS, however Inno Setup comes highly recommended as a software packager/installer, and I also like the idea of learning a little Pascal programming, into the bargain ;)
Any ideas or thoughts are most welcome :-)
I agree with #Deanna, the SendInput function is the best for simulating user input you can get. In the following script I've shown how to simulate mouse clicks on the absolute screen position (in pixels). As an example I'm trying to show Inno Setup's about box through the Help / About Inno Setup menu item (if you would have the same screen settings as me and have the Inno Setup IDE maximized, it may even hit that menu item. So here's just the mouse part (and only limited functionality you can get). Take it rather as a proof, that it's possible to simulate user input from Inno Setup:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
OutputDir=userdocs:Inno Setup Examples Output
[code]
const
SM_CXSCREEN = 0;
SM_CYSCREEN = 1;
INPUT_MOUSE = 0;
MOUSEEVENTF_MOVE = $0001;
MOUSEEVENTF_LEFTDOWN = $0002;
MOUSEEVENTF_LEFTUP = $0004;
MOUSEEVENTF_RIGHTDOWN = $0008;
MOUSEEVENTF_RIGHTUP = $0010;
MOUSEEVENTF_MIDDLEDOWN = $0020;
MOUSEEVENTF_MIDDLEUP = $0040;
MOUSEEVENTF_VIRTUALDESK = $4000;
MOUSEEVENTF_ABSOLUTE = $8000;
type
TMouseInput = record
Itype: DWORD;
dx: Longint;
dy: Longint;
mouseData: DWORD;
dwFlags: DWORD;
time: DWORD;
dwExtraInfo: DWORD;
end;
function GetSystemMetrics(nIndex: Integer): Integer;
external 'GetSystemMetrics#user32.dll stdcall';
function SendMouseInput(nInputs: UINT; pInputs: TMouseInput;
cbSize: Integer): UINT;
external 'SendInput#user32.dll stdcall';
function SendMouseClick(Button: TMouseButton; X, Y: Integer): Boolean;
var
Flags: DWORD;
Input: TMouseInput;
ScreenWidth: Integer;
ScreenHeight: Integer;
begin
Result := False;
Flags := MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_VIRTUALDESK or MOUSEEVENTF_MOVE;
ScreenWidth := GetSystemMetrics(SM_CXSCREEN);
ScreenHeight := GetSystemMetrics(SM_CYSCREEN);
Input.Itype := INPUT_MOUSE;
Input.dx := Round((X * 65536) / ScreenWidth);
Input.dy := Round((Y * 65536) / ScreenHeight);
case Button of
mbLeft: Input.dwFlags := Flags or MOUSEEVENTF_LEFTDOWN;
mbRight: Input.dwFlags := Flags or MOUSEEVENTF_RIGHTDOWN;
mbMiddle: Input.dwFlags := Flags or MOUSEEVENTF_MIDDLEDOWN;
end;
Result := SendMouseInput(1, Input, SizeOf(Input)) = 1;
if Result then
begin
Input.Itype := INPUT_MOUSE;
Input.dx := Round((X * 65536) / ScreenWidth);
Input.dy := Round((Y * 65536) / ScreenHeight);
case Button of
mbLeft: Input.dwFlags := Flags or MOUSEEVENTF_LEFTUP;
mbRight: Input.dwFlags := Flags or MOUSEEVENTF_RIGHTUP;
mbMiddle: Input.dwFlags := Flags or MOUSEEVENTF_MIDDLEUP;
end;
Result := SendMouseInput(1, Input, SizeOf(Input)) = 1;
end;
end;
procedure InitializeWizard;
begin
if MsgBox('Are you sure you want to let the installer click ' +
'somewhere on your screen ? TLama warned you :-)', mbConfirmation,
MB_YESNO) = IDYES then
begin
if not SendMouseClick(mbLeft, 242, 31) then
MsgBox(SysErrorMessage(DLLGetLastError), mbError, mb_Ok);
if not SendMouseClick(mbLeft, 382, 263) then
MsgBox(SysErrorMessage(DLLGetLastError), mbError, mb_Ok);
end;
end;
The best bet for this is to use the SendInput() API from a DLL that you then call from Inno Setup.
This will allow full control of everything you can do manually in that application.
I'm using the excellent Inno Setup installer and I notice that some Applications (often from Microsoft) get installed with their launch icon already highly visible ('pinned?') in the start menu (in Windows 7). Am I totally reliant on the most-recently-used algorithm for my icon to be 'large' in the start menu, or is there a way of promoting my application from the installer please?
It is possible to pin programs, but not officially. Based on a code posted in this thread (which uses the same way as described in the article linked by #Mark Redman) I wrote the following:
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
const
// these constants are not defined in Windows
SHELL32_STRING_ID_PIN_TO_TASKBAR = 5386;
SHELL32_STRING_ID_PIN_TO_STARTMENU = 5381;
SHELL32_STRING_ID_UNPIN_FROM_TASKBAR = 5387;
SHELL32_STRING_ID_UNPIN_FROM_STARTMENU = 5382;
type
HINSTANCE = THandle;
HMODULE = HINSTANCE;
TPinDest = (
pdTaskbar,
pdStartMenu
);
function LoadLibrary(lpFileName: string): HMODULE;
external 'LoadLibrary{#AW}#kernel32.dll stdcall';
function FreeLibrary(hModule: HMODULE): BOOL;
external 'FreeLibrary#kernel32.dll stdcall';
function LoadString(hInstance: HINSTANCE; uID: UINT;
lpBuffer: string; nBufferMax: Integer): Integer;
external 'LoadString{#AW}#user32.dll stdcall';
function TryGetVerbName(ID: UINT; out VerbName: string): Boolean;
var
Buffer: string;
BufLen: Integer;
Handle: HMODULE;
begin
Result := False;
Handle := LoadLibrary(ExpandConstant('{sys}\Shell32.dll'));
if Handle <> 0 then
try
SetLength(Buffer, 255);
BufLen := LoadString(Handle, ID, Buffer, Length(Buffer));
if BufLen <> 0 then
begin
Result := True;
VerbName := Copy(Buffer, 1, BufLen);
end;
finally
FreeLibrary(Handle);
end;
end;
function ExecVerb(const FileName, VerbName: string): Boolean;
var
I: Integer;
Shell: Variant;
Folder: Variant;
FolderItem: Variant;
begin
Result := False;
Shell := CreateOleObject('Shell.Application');
Folder := Shell.NameSpace(ExtractFilePath(FileName));
FolderItem := Folder.ParseName(ExtractFileName(FileName));
for I := 1 to FolderItem.Verbs.Count do
begin
if FolderItem.Verbs.Item(I).Name = VerbName then
begin
FolderItem.Verbs.Item(I).DoIt;
Result := True;
Exit;
end;
end;
end;
function PinAppTo(const FileName: string; PinDest: TPinDest): Boolean;
var
ResStrID: UINT;
VerbName: string;
begin
case PinDest of
pdTaskbar: ResStrID := SHELL32_STRING_ID_PIN_TO_TASKBAR;
pdStartMenu: ResStrID := SHELL32_STRING_ID_PIN_TO_STARTMENU;
end;
Result := TryGetVerbName(ResStrID, VerbName) and ExecVerb(FileName, VerbName);
end;
function UnpinAppFrom(const FileName: string; PinDest: TPinDest): Boolean;
var
ResStrID: UINT;
VerbName: string;
begin
case PinDest of
pdTaskbar: ResStrID := SHELL32_STRING_ID_UNPIN_FROM_TASKBAR;
pdStartMenu: ResStrID := SHELL32_STRING_ID_UNPIN_FROM_STARTMENU;
end;
Result := TryGetVerbName(ResStrID, VerbName) and ExecVerb(FileName, VerbName);
end;
The above code first reads the caption of the menu item for pinning or unpinning applications from the string table of the Shell32.dll library. Then connects to the Windows Shell, and for the target app. path creates the Folder object, then obtains the FolderItem object and on this object iterates all the available verbs and checks if their name matches to the one read from the Shell32.dll library string table. If so, it invokes the verb item action by calling the DoIt method and exits the iteration.
Here is a possible usage of the above code, for pinning:
if PinAppTo(ExpandConstant('{sys}\calc.exe'), pdTaskbar) then
MsgBox('Calc has been pinned to the taskbar.', mbInformation, MB_OK);
if PinAppTo(ExpandConstant('{sys}\calc.exe'), pdStartMenu) then
MsgBox('Calc has been pinned to the start menu.', mbInformation, MB_OK);
And for unpinning:
if UnpinAppFrom(ExpandConstant('{sys}\calc.exe'), pdTaskbar) then
MsgBox('Calc is not pinned to the taskbar anymore.', mbInformation, MB_OK);
if UnpinAppFrom(ExpandConstant('{sys}\calc.exe'), pdStartMenu) then
MsgBox('Calc is not pinned to the start menu anymore.', mbInformation, MB_OK);
Please note that even though this code works on Windows 7 (and taskbar pinning also on Windows 8.1 where I've tested it), it is really hacky way, since there is no official way to programatically pin programs to taskbar, nor start menu. That's what the users should do by their own choice.
There's a reason there's no programmatic way to pin things to the taskbar/start menu. In my experience, I have seen the start menu highlight newly-created shortcuts, and that's designed to handle exactly this situation. When you see a newly-installed program show up on the start menu, it's probably because of that algorithm and not because the installer placed it there.
That said, if a new shortcut does not appear highlighted, it may be because the installer extracts a pre-existing shortcut and preserves an old timestamp on it, rather than using the API function to create a shortcut in the start menu.
Have a look at: http://blogs.technet.com/deploymentguys/archive/2009/04/08/pin-items-to-the-start-menu-or-windows-7-taskbar-via-script.aspx