Virtual Memory Handling - memory

I'm working on a PE Loader, just like windows loader
my target is an executable not DLL,i tried first loadlibrary but faced reallocation problems,got some code to fix it, but it didn't work with all targets (some exe's needs to be loaded at the same BaseAdress to work probably
so i got to the point, i've to implement my loader to ensure the BaseAddress issue and no need for reallocation
I'm forcing my application to load at a high addr(0x10000000),while using VirtualAlloc to allocate memory for headers & sections for the target app
i use VirtualQuery to see the state of the address i want to allocate, if not free i use UnMapViewOfFile if Page type MEM_MAPPED else VirtualFree(MEM_RELEASE)
The problem is that if the memory pages are MEM_MAPPED & MEM_COMMIT (always page file backed pages) all methods fails with error code 0x57 ERROR_INVALID_PARAMETER
looking for solutions/ideas here's the code :
MylpAddr = (DWORD)lpAddr ;
MemInfo.RegionSize = 0 ;
NtUnmapViewOfSection= (NTUNMAPVIEWOFSECTION)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnmapViewOfSection");
NtProtectVirtualMemory= (NTPROTECTVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtProtectVirtualMemory");
NtUnlockVirtualMemory= (NTUNLOCKVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnlockVirtualMemory");
GetSystemInfo(&siSysInfo);
szPage = siSysInfo.dwPageSize ;
i = VirtualQuery( (LPCVOID)MylpAddr , &MemInfo , 0x20 ) ;
if (!i) return NULL ;
if ( !(MemInfo.State & MEM_FREE) )
{
if ( MemInfo.Type & MEM_MAPPED )
{
hProc = GetCurrentProcess() ;
szPage = MemInfo.RegionSize ;
i = NtUnlockVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , LOCK_VM_IN_WORKING_SET | LOCK_VM_IN_RAM );
i = NtProtectVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , PAGE_READWRITE , &OldProt ) ;
i = NtUnmapViewOfSection( hProc , (LPVOID)MemInfo.AllocationBase );
i = UnmapViewOfFile( (LPVOID)MemInfo.AllocationBase );
if (!i) i =1 ;
}
else
{
j = VirtualUnlock(MemInfo.BaseAddress , MemInfo.RegionSize);
i = VirtualFree( (LPVOID)MemInfo.AllocationBase , NULL , MEM_RELEASE ) ;
}
if (!i) return NULL ;
}
MylpAddr = (DWORD)VirtualAlloc( lpAddr , dwSize , AllocType , ProtFlags );

Sorry for bringing up such an old question, I just thought it might help someone.
As far as I know, to fork a process you must have used CreateProcess function. Therefore you need to use VirtualQueryEx and VirtualAllocEx instead of VirtualQuery and VirtualAlloc. Also replace hProc value with a handle to your created process. I also noticed that you have explicitly used 0x20 as dwLength that you probably need to change it with dwSize.In summary:
PROCESS_INFORMATION piProcessInformation;
ZeroMemory(&piProcessInformation,sizeof(PROCESS_INFORMATION));
if(CreateProcess(NULL,processName,NULL,NULL,false,CREATE_SUSPENDED,NULL,NULL,&suStartUpInformation,&piProcessInformation))
{
cContext.ContextFlags = CONTEXT_FULL;
GetThreadContext(piProcessInformation.hThread,&cContext);
i = VirtualQueryEx(piProcessInformation.hProcess, (LPCVOID)MylpAddr , &MemInfo , dwSize ) ;
if (!i) return NULL ;
if ( !(MemInfo.State & MEM_FREE) )
{
if ( MemInfo.Type & MEM_MAPPED )
{
// hProc = GetCurrentProcess() ; No need to this line
szPage = MemInfo.RegionSize ;
i = NtUnlockVirtualMemory(piProcessInformation.hProcess , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , LOCK_VM_IN_WORKING_SET | LOCK_VM_IN_RAM );
i = NtProtectVirtualMemory(piProcessInformation.hProcess , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , PAGE_READWRITE , &OldProt ) ;
i = NtUnmapViewOfSection( piProcessInformation.hProcess , (LPVOID)MemInfo.AllocationBase );
i = UnmapViewOfFile( (LPVOID)MemInfo.AllocationBase );
if (!i) i =1 ;
}
else
{
j = VirtualUnlock(MemInfo.BaseAddress , MemInfo.RegionSize);
i = VirtualFreeEx(piProcessInformation.hProcess, (LPVOID)MemInfo.AllocationBase , NULL , MEM_RELEASE ) ;
}
if (!i) return NULL ;
}
MylpAddr = (DWORD)VirtualAllocEx(piProcessInformation.hProcess, lpAddr , dwSize , AllocType , ProtFlags );
}

Related

Getting the max and min price of current chart

After performing
ChartNavigate(0, CHART_END, -5142);
I want to get the max and min price of that particular chart.
I tried
ChartGetDouble(0,CHART_PRICE_MAX,0,top)
ChartGetDouble(0,CHART_PRICE_MIN,0,top)
WindowPriceMax
WindowPriceMin
None of them gives me the price after the ChartNavigate.
What is the right way to do this?
New-MQL4.56789 features may surprise, nevertheless:
Step 0: always catch Chart_OkFLAG
bool Chart_OkFLAG;
double Chart_min,
Chart_MAX;
int Chart_ToBeMODIFIED = ChartID();
int Chart_ToBeMODIFIED_SubWinID = 0;
int Chart_nBarsRelativeSHIFT = 0;
Chart_OkFLAG = ChartNavigate( Chart_ToBeMODIFIED,
< CHART_BEGIN |
CHART_END |
CHART_CURRENT_POS >,
Chart_nBarsRelativeSHIFT
);
If OK: you won the first round, the GUI command has been accepted for being syntactically & context-wise correct. That does not mean, it was executed by the GUI processor. It was just let in, to the tail of the GUI-command-QUEUE.
Step 1: Enforce it's execution ( wise to think about deferring such processing to some safe place, after mission-critical elements have been fulfilled )
if ( Chart_OkFLAG ){
WindowRedraw(); // ol'-MQL4
ChartRedraw( Chart_ToBeMODIFIED ); // new-MQL4
Chart_min = ChartPriceMin( Chart_ToBeMODIFIED,
Chart_ToBeMODIFIED_SubWinID
);
Chart_MAX = ChartPriceMAX( Chart_ToBeMODIFIED,
Chart_ToBeMODIFIED_SubWinID
);
}
else{
// ERROR HANDLING onChartNavigate(T)ERROR
}
ALWAYS: do not hesitate to inline error handlers, even where MQL4 language seems straightforward ( you never know, when that effort pays off by avoiding hours of bug tracking )
double ChartPriceMin( const long Chart_ID = 0,
const int Chart_SubWindow_ID = 0
) {
double result = EMPTY_VALUE;
ResetLastError();
if ( !ChartGetDouble( Chart_ID,
CHART_PRICE_MIN,
Chart_SubWindow_ID,
result
)
){
PrintFormat( "ERROR: Code(%d) in [%s]",
GetLastError(),
__FUNCTION__,
);
}
return( result );
}
double ChartPriceMAX( const long Chart_ID = 0,
const int Chart_SubWindow_ID = 0
) {
double result = EMPTY_VALUE;
ResetLastError();
if ( !ChartGetDouble( Chart_ID,
CHART_PRICE_MAX,
Chart_SubWindow_ID,
result
)
){
PrintFormat( "ERROR: Code(%d) in [%s]",
GetLastError(),
__FUNCTION__,
);
}
return( result );
}

Why [ MetaTrader 4 ] can't write/open a file in windows 10 with the FileWrite() function?

I tried implementing the solutions from this post
Cannot open file on Ubuntu
But to no avail. I keep getting a 5002 error. (failed to open file) after FileWrite()
Even when I try out the example script on https://docs.mql4.com/files/filewrite
I get the same error. I tried running MetaTrader Terminal 4 in administrator mode but to no avail either.Does anyone know a solution to this?
#property version "1.00"
#property strict
//--- show the window of input parameters when launching the script
#property script_show_inputs
//--- parameters for receiving data from the terminal
input string InpSymbolName = "EURUSD"; // Сurrency pair
input ENUM_TIMEFRAMES InpSymbolPeriod = PERIOD_H1; // Time frame
input int InpFastEMAPeriod = 12; // Fast EMA period
input int InpSlowEMAPeriod = 26; // Slow EMA period
input int InpSignalPeriod = 9; // Difference averaging period
input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Price type
//--- parameters for writing data to file
input string InpFileName = "MACD.csv"; // File name
input string InpDirectoryName = "Data"; // Folder name
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
bool sign_buff[]; // signal array (true - buy, false - sell)
datetime time_buff[]; // array of signals' appear time
int sign_size=0; // signal array size
double macd_buff[]; // array of indicator values
datetime date_buff[]; // array of indicator dates
int macd_size=0; // size of indicator arrays
//--- set indexing as time series
ArraySetAsSeries( sign_buff, true );
ArraySetAsSeries( time_buff, true );
ArraySetAsSeries( macd_buff, true );
ArraySetAsSeries( date_buff, true );
//--- reset last error code
ResetLastError();
//--- copying the time from last 1000 bars
int copied = CopyTime( NULL, 0, 0, 1000, date_buff );
if ( copied <= 0 )
{ PrintFormat( "Failed to copy time values. Error code = %d", GetLastError() );`
return;
}
//--- prepare macd_buff array
ArrayResize( macd_buff, copied );
//--- copy the values of main line of the iMACD indicator
for ( int i = 0; i< copied; i++ )
{ macd_buff[i] = iMACD( InpSymbolName, InpSymbolPeriod, InpFastEMAPeriod, InpSlowEMAPeriod, InpSignalPeriod, InpAppliedPrice, MODE_MAIN, i );
}
//--- get size
macd_size = ArraySize( macd_buff );
//--- analyze the data and save the indicator signals to the arrays
ArrayResize( sign_buff, macd_size - 1 );
ArrayResize( time_buff, macd_size - 1 );
for ( int i = 1; i < macd_size; i++ )
{
//--- buy signal
if ( macd_buff[i-1] < 0
&& macd_buff[i] >= 0 )
{
sign_buff[sign_size] = true;
time_buff[sign_size] = date_buff[i];
sign_size++;
}
//--- sell signal
if ( macd_buff[i-1] > 0
&& macd_buff[i] <= 0 )
{
sign_buff[sign_size] = false;
time_buff[sign_size] = date_buff[i];
sign_size++;
}
}
//--- open the file for writing the indicator values (if the file is absent, it will be created automatically)
ResetLastError();
int file_handle = FileOpen( InpDirectoryName // aDirNAME
+ "//" // aFileSystemTreeBranchSEPARATOR
+ InpFileName, // aFileNAME
FILE_READ|FILE_WRITE|FILE_CSV // fileIoMODE_FLAGs
);
if ( file_handle != INVALID_HANDLE )
{
PrintFormat( "%s file is available for writing", InpFileName );
PrintFormat( "File path: %s\\Files\\", TerminalInfoString( TERMINAL_DATA_PATH ) );
//--- first, write the number of signals
FileWrite( file_handle, sign_size );
//--- write the time and values of signals to the file
for ( int i = 0; i < sign_size; i++ )
FileWrite( file_handle, time_buff[i], sign_buff[i] );
//--- close the file
FileClose( file_handle );
PrintFormat( "Data is written, %s file is closed", InpFileName );
}
else
PrintFormat( "Failed to open %s file, Error code = %d", InpFileName, GetLastError() );
}
Alt. A)
the algo does not check for a positive presence of an InpDirectoryName node in the filesystem.
Alt. B)
in case the Alt. A) passes, there ought be used a compatible delimiter in aFilePATH + aFileNAME string, i.e. == "\\", ( aFileSystemTreeBranchSEPARATOR ref.: Help for details )
thena fileIO shall take place in \Terminal\Common\Files ( in case a FILE_COMMON bitmask flag was added (used) in the int open_flags parameter),
otherwise,the operations will take place in a (sub)-directory of a MetaTrader Terminal 4 local folder== MQL4\Files ( for a live ExpertAdvisor or Custom Indicator or Script mode of operations )or== MQL4\Tester\Files ( in case of using ExpertAdvisor or Custom Indicatorinside a back-testing framework of MT4 Strategy Tester).

How to repair an Error 4059 on calling the OrderModify() function | MQL4?

My EA comes up with an error code of 4059which meansthat the OrderModify() function is apparently not allowed in (back) testing.
Is there any way in which this could be allowed at all?
All I'm wanting to do is change the position to breakeven, when it gets 100 pips "to the good"
PrintFormat( "TKT[%.2d]OP:[%7.5f]SL:[%7.5f]CurrentPrice:[%7.5f]Stoplevel:[%.3d]FreezeLevel:[%.3d]",
aTicket,
anOpenPrice,
aCurrentSL,
anAskPrice,
stopLevel,
freezeLevel
);
SellMod = OrderModify( aTicket,
NormalizeDouble( anOpenPrice, Digits ),
NormalizeDouble( aNewSLPrice, Digits ),
NormalizeDouble( aNewTpPrice, Digits ),
0,
sellcolor
);
SendMail( "Notification of Order Modification for Ticket#"
+ IntegerToString( OrderTicket(), 10 ),
"Good news! Order Ticket#"
+ IntegerToString( OrderTicket(), 10 )
+ "has been changed to breakeven"
);
if ( !SellMod )
{ PrintFormat( "Order modification for ticket %10d has failed modify the order under the Error Code# %5d. Check MQL4 Documentation",
aTicket,
GetLastError()
);
result = false;
}
4059 ERR_FUNC_NOT_ALLOWED_IN_TESTINGis clear, not the source of it though
Function is not allowed in testing mode[ HIDDEN REMAINS _WHERE_ + _WHY_ IT IS REPORTED] :)
So,
modify a few details on Error-Detection
so as to get back to the riding saddle and to get the things back under your full control:
.
..
...
// ======================================== .ASSUME NOTHING ; the best
// advice
// ever :)
// // ALWAYS (pre-clear)
GetLastError(); /* _ _ _ _ _ _ _ _ _ _ _ AND ERR_SYSREG, 0 ; CLEAR SYSREG
; (
; prevents
; from reading
; a value from
; some "old"
; error-code
; on a "next"
; GetLastError
; call
; )
*/
OrderModify(...); // CALL _OrderModify
gotLastERROR = // MOV VAR, ERR_SYSREG ; CATCH ERR
GetLastError(); // _ _ _ _ _ _ _ _ _ _ _ AND ERR_SYSREG, 0 ; CLEAR SYSREG
// ---------------------------------------- ( a main-effect )
// ( VAR has this _FUN call error-code )
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ( a side-effect )
// ( ERR_SYSREG is clear AGAIN )
...
..
.
With a similarly systematic approach to Error-Detection you will soon realise the root cause of the observed problem and any Error-Handling will only start to have sense.
Most probably, the error originates a few SLOC-s lower, under your OrderModify() call, where SendMail() call appears, in spite of the fact, that HELP explicitly says:
NoteSending can be prohibited in settings, email address can be omitted as well. For the error information call GetLastError().
SendMail() function does not work in the Strategy Tester.
OrderModify() does NOT generate error 4059.
That error comes from SendMail(). Documentation states that:
https://docs.mql4.com/common/sendmail

First Try to SMPP Protocol (Bind Command)

i have a try to implement SMPP client , a first test is do bind after i have live socket connection.
but server show HEX Error message when receive the stream.
SMPP Unit
interface
uses Classes;
Type
// c octet strings
TSystemID = string[16];
TPassword = string[9];
TSystemType = string[13];
TAddr = string[21];
TAddr_Range = string[41];
TSvc_Type = string[6];
TDate_time = string[17];
TMsgID = string[65];
pPDU_HDR = ^TPDU_HDR;
TPDU_HDR = packed record
command_len : LongWord ;
command_id : LongWord ;
command_status :LongWord ;
command_number:LongWord ;
end;
pSMPP_BIND = ^TSMPP_BIND ;
TSMPP_BIND = packed record
SystemID : TSystemID ;
Password : TPassword ;
SystemType : TSystemType ;
Ver : Byte;
Addr_TON : Byte ;
Addr_NPI : Byte ;
Addr_Range : TAddr_Range ;
end;
const
{ max short message length }
DCS7_MAX_LEN = 160;
DCS8_MAX_LEN = 140;
DCSUCS2_MAX_LEN = DCS8_MAX_LEN div 2;
{ command ids }
cmdNull = $00000000;
cmdBindReceiver = $00000001;
cmdBindTransmitter = $00000002;
cmdQuery = $00000003;
cmdReplace = $00000007;
cmdCancel = $00000008;
cmdBindTransceiver = $00000009;
cmdOutbind = $0000000B;
cmdUnbind = $00000006;
cmdSubmitSM = $00000004;
cmdDeliverSM = $00000005;
cmdEnquireLink = $00000015;
cmdSubmitMultiply = $00000021;
cmdAlertNotification = $00000102;
cmdData = $00000103;
cmdGenericNack = $80000000;
cmdResponseBase = $80000000;
cmdBindReceiverResponse = $80000001;
cmdBindTransmitterResponse = $80000002;
cmdQueryResponse = $80000003;
cmdReplaceResponse = $80000007;
cmdCancelResponse = $80000008;
cmdBindTransceiverResponse = $80000009;
cmdUnbindResponse = $80000006;
cmdSubmitSMResponse = $80000004;
cmdDeliverSMResponse = $80000005;
cmdEnquireLinkResponse = $80000015;
cmdSubmitMultiplyResponse = $80000021;
cmdDataResponse = $80000103;
{ ESM_CLASS }
ESM_CLASS_DELIVERY_RECEIPT = $04;
ESM_CLASS_UDHI = $40;
implementation
end.
ON My Form btnSendBindClick
procedure TFrmMain.btnSendBindClick(Sender: TObject);
var hdr : TPDU_HDR ;
bind_pkt : TSMPP_BIND ;
mm : TMemoryStream ;
HdrPtr : pPDU_HDR ;
BindPtr : pSMPP_BIND ;
sysid : AnsiString ;
pass : AnsiString ;
systype : AnsiString ;
add_rn : AnsiString ;
begin
sysid := 'sysid';
pass := 'pass';
systype := 'sys_type';
add_rn := '';
hdr.command_id := htonl(cmdBindTransceiver) ;
hdr.command_status := htonl(cmdNull) ;
hdr.command_number := htonl(cmdBindTransmitter) ;
hdr.command_len := htonl(SizeOf(hdr)+SizeOf(bind_pkt));
bind_pkt.SystemID := pansiChar(sysid);
bind_pkt.Password := pansiChar(pass);
bind_pkt.SystemType := pansiChar(systype);
bind_pkt.Ver := 0 ;
bind_pkt.Addr_TON := 1 ;
bind_pkt.Addr_NPI := 1 ;
bind_pkt.Addr_Range := pansiChar(add_rn);
HdrPtr := #HdrPtr ;
BindPtr := #bind_pkt ;
mm := TMemoryStream.Create ;
mm.Write(HdrPtr^,SizeOf(hdr));
mm.Position := mm.Size;
mm.Write(BindPtr^,SizeOf(bind_pkt));
mm.Position := 0 ;
clnt.Socket.SendStream(mm);
end;
I think i need to encode data stream to something, but i am not sure .
I worked with SMPP in 1999/2000 last time, but at that time, specs. 3.4 said that fields like SystemID, Password etc..., i.e. declared as Var. Max nn, are of type C-OctetString.
So if the spec did not change, you completelly missed it: you cannot use records and similiar data structures, but you have to create an octet stream containing sequence of ASCIIZ strings with no padding, e.g. (using Delphi syntax): ...'SystemId'#0'Password'#0'SystemType'#0.... And if I remember it correctly, you should change endians for integer fields as well.

Returning tables of objects from C++, adopt policy

Using luabind, I create a table of objects from C++
luabind::object create_table(lua_State *L)
{
luabind::object result = luabind::newtable(L);
int index = 1;
for ( ... ) {
lua_Object *o = new lua_Object( ... );
result[ index ++ ] = o;
}
return result;
}
I register the function as
module(L)
[
def("create_table", &create_table)
]
and lua_Object as
class_<lua_Object> reg("Object");
reg
.def(constructor<float,float>())
;
module(L) [ reg ];
How can I tell luabind to take ownership of the objects stored in the table ( new lua_Object( ... ) )? What would be a work around?
Thanks -
Replace
result[ index ++ ] = o
with
result[ index ++ ] = luabind::object(L, o, luabind::adopt(luabind::result));
On a side note, don't you have to register create_table with raw(_1) policy?

Resources