//+-------------+
//|zMsgSnd.mq4  |
//+-------------+
#property copyright ""
#property link      ""
#include <stdlib.mqh>
//#include <WinUser32.mqh>

string sSlotNamePrefix="\\\\.\\mailslot\\";
string sSlotName="InternalMsg01";
string sFullSlotName = "x";

#define GENERIC_WRITE  0x40000000
#define OPEN_EXISTING  3
#define FILE_ATTRIBUTE_NORMAL 0x80
#define FILE_SHARE_READ 0x00000001

//Integer Arrays are used where there is a DLL requirement for a variable passed by reference (pointer)
//MT does NOT like strings or single integer variables for these items!
//Change at your own risk.
//Some of these structures may not be absolutely necessary for C or MT,
//but were done this way to be compatible with Excel/VBA
int iaSecurity[3];           //security attributes
int iaOverlapped[5];         //overlapped
int iaActualBytesWritten[2]; //bytes written
int iaBuffer[64];            //send buffer = 4 bytes/int * 64 = 256
int iMaxBufferSize = 256;    //this must match the 64*4
int iBufferSize = 0;         //actual size in bytes sent to write

int iSlotHandle = -1;  //generated by create file after the receiver initializes it
int iRet = 0;
int iLoop = 0;
int iTemplate = 0;
int iError = 0;
string sSymbol = "x";
string sSndMsg = "x";

#import "kernel32.dll"
int CreateFileA( string name, int desiredAccess, int SharedMode,
       int& security[], int creation, int flags, int templateFile );  //had to use the alias
int WriteFile( int fileHandle, int& buffer[], int bytes, int& numOfBytes[], int& overlapped[] );
int CloseHandle( int fileHandle );
int GetError();
#import

//+------------------------------------------------------------------+
int start() {
   //no security
   iaSecurity[0]=12;  //length
   iaSecurity[1]=0;   //sec code
   iaSecurity[2]=-1;  //inheritance
   //no overlapped
   iaOverlapped[0]=0; //Internal
   iaOverlapped[1]=0; //InternalHigh
   iaOverlapped[2]=0; //offset
   iaOverlapped[3]=0; //OffsetHigh
   iaOverlapped[4]=0; //hEvent
   
   sSymbol = Symbol();
   sFullSlotName = sSlotNamePrefix + sSlotName;
   Print("slot name: ",sFullSlotName );
   //

   //look for a slot opended by receiver
   for(iLoop=0;iLoop<=10;iLoop++){   
      iSlotHandle = CreateFileA(sFullSlotName, GENERIC_WRITE, FILE_SHARE_READ, iaSecurity, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, iTemplate);
      Print("cf), lop:", iLoop, ", slothndl:", iSlotHandle );
      if ( iSlotHandle > 0 ) break;
      Sleep(5000);
   }   
   if ( iSlotHandle < 0 ){
      Print( "create ms failed after x attempts" );
      iError = GetLastError();
      Print("err after cf: ", iError,",  desc: ",  ErrorDescription(iError) );
      return;
   } 
   //
   iaActualBytesWritten[0]=0;  //this is used
   iaActualBytesWritten[1]=0;  //this is not - but may be needed for array dimensioning(?)
   sSndMsg = "Processing," + sSymbol;
   fctCopyToBuffer( sSndMsg );
   //ret=0=failed
   iRet = WriteFile(iSlotHandle, iaBuffer, iBufferSize, iaActualBytesWritten, iaOverlapped);
   if(iRet == 0) {
      Print( "wrt failed" );
      iError = GetLastError();
      Print("err after wrt: ", iError,",  desc: ",  ErrorDescription(iError) );
      iRet = CloseHandle( iSlotHandle );
      return;
   }
   Print("good wrt: sz0: ", iaActualBytesWritten[0]);
   
   Sleep(5000);
   
   string sX = "How about we process this message,Close, 123.45xxx";
   sX =  "x" + sX + sX + sX + sX + "y" + sX + "zqwe";
   sSndMsg = sX;
   fctCopyToBuffer( sSndMsg );
   iaActualBytesWritten[0]=0;
   //ret=0=failed
   iRet = WriteFile(iSlotHandle, iaBuffer, iBufferSize, iaActualBytesWritten, iaOverlapped);
   if(iRet == 0) {
      Print( "wrt2 failed" );
      iError = GetLastError();
      Print("err after wrt2: ", iError,",  desc: ",  ErrorDescription(iError) );
      iRet = CloseHandle( iSlotHandle );
      return;
   }
   Print("good wrt2: sz0: ", iaActualBytesWritten[0]);
   
   /////////////////////////
   iRet = CloseHandle( iSlotHandle );
   return;
}
///
void fctCopyToBuffer(string psMessage) {
   int iLoopMax = ArraySize(iaBuffer);
   for (int i = 0; i < iLoopMax; i++)
      iaBuffer[i] = 0;
   int iLenThisMsg = StringLen(psMessage);
   if(iLenThisMsg > (iLoopMax*4)) {
      Print("err msg too long: " , iLenThisMsg, ", max is: ", (iLoopMax*4));
      iBufferSize = 0;
      return;
   }
   for (i = 0; i < iLenThisMsg; i++) {
      int iOff = i % 4;
      int iShift = 0;
      if ( iOff == 1 )
         iShift = 8;
      else if ( iOff == 2 )
         iShift = 16;
      else if ( iOff == 3 )
         iShift = 24;
      iaBuffer[i/4] |= StringGetChar( psMessage, i ) << iShift;
   }
   iBufferSize = iLenThisMsg;
   return;
}
//+------------------------------------------------------------------+