Primo Posted December 25, 2017 Report Posted December 25, 2017 Hello, my program try to used FSUIPC write data to P3D, show this Exception: System.ArgumentOutOfRangeException: Requested range extends past the end of the array. at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object destination, Int32 startIndex, Int32 length) at System.Runtime.InteropServices.Marshal.Copy(IntPtr source, Byte[] destination, Int32 startIndex, Int32 length) at FsuipcSDK.Fsuipc.FSUIPC_Process(Int32& dwResult) in D:\Sandbox\Control Loading\ControlLoadingGUI_PrimoDev\AXAviationControlLoading\AXAviationControlLoading\Simulator\FsuipcSDK.cs:line 566 at AXAviationControlLoading.WriteDataSimulator.ReadWriteFsuipc(Int32 dwOffset, Int32 dwSize, Int32 type, Int32& dwResult) in D:\Sandbox\Control Loading\ControlLoadingGUI_PrimoDev\AXAviationControlLoading\AXAviationControlLoading\Simulator\WriteDataSimulator.cs:line 233 at AXAviationControlLoading.WriteDataSimulator.fsuipc_write(Double[] ControlSurface) in D:\Sandbox\Control Loading\ControlLoadingGUI_PrimoDev\AXAviationControlLoading\AXAviationControlLoading\Simulator\WriteDataSimulator.cs:line 256 at AXAviationControlLoading.WriteDataSimulator.input(Double[] ControlSurface) in D:\Sandbox\Control Loading\ControlLoadingGUI_PrimoDev\AXAviationControlLoading\AXAviationControlLoading\Simulator\WriteDataSimulator.cs:line 200 at AXAviationControlLoading.MainProgram.input(Double[] ControlSurface) in D:\Sandbox\Control Loading\ControlLoadingGUI_PrimoDev\AXAviationControlLoading\AXAviationControlLoading\Simulator\MainProgram.cs:line 189 at AXAviationControlLoading.MainWindow.UDPXpcValueListen() in D:\Sandbox\Control Loading\ControlLoadingGUI_PrimoDev\AXAviationControlLoading\AXAviationControlLoading\Main\MainWindow.xaml.cs:line 1108 private void UDPXpcValueListen() { string filePath = AppDomain.CurrentDomain.BaseDirectory + "/UDPXpcValue_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt"; UDPXpcValueListen_Active = true; UDPListenXpcValueClient = new UdpClient(RemoteIpPort_XpcRV); ReceiveXpcValueRemoteIpAndPort = new IPEndPoint(IPAddress.Any, RemoteIpPort_XpcRV); try { while (true) { UDPReceiveXpcValueBytes = Encoding.Default.GetString(UDPListenXpcValueClient.Receive(ref ReceiveXpcValueRemoteIpAndPort)); string[] TempArray = StringFiltering(UDPReceiveXpcValueBytes, "#").ToArray(); string[] Value = StringFiltering(TempArray[4], "_").ToArray(); double DemandColumnPosition = double.Parse(Value[0]); double DemandWheelPosition = double.Parse(Value[1]); double DemandRudderPosition = double.Parse(Value[2]); double ActualColumnPosition = double.Parse(Value[3]); double ActualWheelPosition = double.Parse(Value[4]); double ActualRudderPosition = double.Parse(Value[5]); double ActualColumnForce = double.Parse(Value[6]); double ActualWheelForce = double.Parse(Value[7]); double ActualRudderForce = double.Parse(Value[8]); int WheelAlarm = int.Parse(Value[9]); int ColumnAlarm = int.Parse(Value[10]); XPCValueTimer.Stop(); XPCValueTimer.Start(); Console.WriteLine("{0} :{1}\t{2}", ReceiveXpcValueRemoteIpAndPort.Address.ToString(), ReceiveXpcValueRemoteIpAndPort.Port.ToString(), UDPReceiveXpcValueBytes); WriteFile(UDPReceiveXpcValueBytes + DateTime.Now.ToString("\tyyyy/MM/dd HH:mm:ss.ffffff"), filePath); Force[0] = ActualColumnForce.ToString(); Force[1] = ActualWheelForce.ToString(); Force[2] = ActualRudderForce.ToString(); double[] ControlSurface = { ActualColumnPosition, ActualWheelPosition, ActualRudderPosition }; if (AutopilotStatus == "1") { if (Math.Abs(ActualColumnForce) > 30 || Math.Abs(ActualWheelForce) > 30 || Math.Abs(ActualRudderForce) > 30) mainprogram.input(0); } else { WriteFile(ControlSurface[0] + "\t" + ControlSurface[1] + "\t" + ControlSurface[2], filePath); if (ControlSurface != null) mainprogram.input(ControlSurface); //Thread.Sleep(100); } UIControl receiveDatafromTarget = delegate () { InfomationZone.ElevatorHardwareTextBox.Text = Convert.ToString(ActualColumnPosition) + "° / " + Convert.ToString(ActualColumnForce) + "%"; InfomationZone.AileronHardwareTextBox.Text = Convert.ToString(ActualWheelPosition) + "° / " + Convert.ToString(ActualWheelForce) + "%"; InfomationZone.RudderHardwareTextBox.Text = Convert.ToString(ActualRudderPosition) + "° / " + Convert.ToString(ActualRudderForce) + "%"; InfomationZone.AlarmTextBox.Text = "AL" + ColumnAlarm.ToString("X3") + "(C) / " + "AL" + WheelAlarm.ToString("X3") + "(W)"; //InfomationZone.ErrorCodeTextBox.Text = ErrorCode(number); if (WheelAlarm != 0 || ColumnAlarm != 0) SystemControl.ClearAlarmbutton.IsEnabled = true; else Command[3] = "0"; Socket.SourceIpTB_Xpc_S.Text = ReceiveXpcValueRemoteIpAndPort.Address.ToString(); Socket.SourcePortTB_Xpc_S_V.Text = ReceiveXpcValueRemoteIpAndPort.Port.ToString(); }; this.Dispatcher.Invoke(receiveDatafromTarget); }; } catch (Exception e) { Console.WriteLine(e.ToString()); WriteFile(e.ToString() + DateTime.Now.ToString("\tyyyy/MM/dd HH:mm:ss.ffffff"), filePath); } finally { UDPListenXpcValueClient.Close(); } } Anyone can help me?
Thomas Richter Posted December 25, 2017 Report Posted December 25, 2017 Hi, the code you show has nothing to do with FSUIPC at all. The problem is related, as it says, to the data type or structure you use for the requested information. Btw - for using DotNET languages like C# there is the perfect Library by Paul Henty that will make you an easy life ! Thomas
Primo Posted December 26, 2017 Author Report Posted December 26, 2017 15 hours ago, Thomas Richter said: Hi, the code you show has nothing to do with FSUIPC at all. The problem is related, as it says, to the data type or structure you use for the requested information. Btw - for using DotNET languages like C# there is the perfect Library by Paul Henty that will make you an easy life ! Thomas Hi, Thomas this code try to write data to P3D. class WriteDataSimulator { enum StatusFlag : int { Initialised, Engaged, Disengaged, Stopped }; FsuipcSDK.Fsuipc fsuipc_Write = new FsuipcSDK.Fsuipc(); // Our main fsuipc object! bool result = false; // Return boolean for FSUIPC method calls int dwFSReq = 0; // Any version of FS is OK int dwResult = -1; // Variable to hold returned results //int dwOffset = 0x02BC; // 02BC = indicated airspeed //int dwSize = 4; // 4 bytes for indicated airspeed int token = -1; /* ******************************************************************************************************/ /* */ /* FSUIPC Offsets */ /* */ /* */ /********************************************************************************************************/ // Control surface int ElevatorReadOffset = 0x0BB2; int AileronReadOffset = 0x0BB6; int RudderReadOffset = 0x0BBA; // AutoPilot Status int AutoPilotStatusReadOffset = 0x07BC; /* ******************************************************************************************************/ /* */ /* FSUIPC Values */ /* */ /* */ /********************************************************************************************************/ // Control surface Values double ElevatorValue; //int64 (2 bytes) double AileronValue; //int64 (2 bytes) double RudderValue; //int64 (2 bytes) // AutoPilot Status int AutoPilotStatusValue; //int64 (4 bytes) // Values convert to degree static double ElevatorReadMax = 1180057599; // ProSim static double ElevatorReadMin = -1179926526; // ProSim //static double ElevatorReadMax = 1481654271; // PMDG //static double ElevatorReadMin = -1481523198; // PMDG static double ElevatorTrueDegreeMax = 24.3; // +24.3(true degree) Boeing 737-800 static double ElevatorTrueDegreeMin = -18.1; // -18.1(true degree) Boeing 737-800 double ElevatorOutputMax = ElevatorReadMax / ElevatorTrueDegreeMax; double ElevatorOutputMin = ElevatorReadMin / ElevatorTrueDegreeMin; static double AileronReadMax = 1073758207; static double AileronReadMin = -1073627134; static double AileronTrueDegreeMax = 20; // +20(true degree) Boeing 737-800 static double AileronTrueDegreeMin = -15; // -15(true degree) Boeing 737-800 double AileronOutputMax = AileronReadMax / AileronTrueDegreeMax; double AileronOutputMin = AileronReadMin / AileronTrueDegreeMin; static double RudderReadMax = 1073627135; static double RudderReadMin = -1073496062; static double RudderTrueDegreeMax = 29; // +29(true degree) Boeing 737-800 static double RudderTrueDegreeMin = -29; // -29(true degree) Boeing 737-800 double RudderOutputMax = RudderReadMax / RudderTrueDegreeMax; double RudderOutputMin = RudderReadMin / RudderTrueDegreeMin; // Show infomation public string InitialisingStatus; public string InitialisedStatus; public string ConnectingStatus; public string ConnectedStatus; public string DisconnectingStatus; public string DisconnectedStatus; public string StopStatus; /// <summary> /// 0 --Initialised; 1 --Engaged; 2 --Disengaged; 3 --Stopped; /// -1 --Failed Initialised; -2 --Failed Engaged; /// -3 --Failed Disengaged; -4 --Failed Stopped; /// </summary> private int[] status = new int[4] { -255, -255, -255, -255 }; public int[] simulatorStatusOutput = new int[4] { -255, -255, -255, -255 }; /* ******************************************************************************************************/ /* */ /* State Machine */ /* */ /* */ /********************************************************************************************************/ public void stateMachine(int code) { switch (code) { case (int)StatusFlag.Initialised: Initialise(); break; case (int)StatusFlag.Engaged: Connect(); break; case (int)StatusFlag.Disengaged: Disconnect(); break; case (int)StatusFlag.Stopped: Stop(); break; default: break; } } /* ******************************************************************************************************/ /* */ /* State Machine Functions */ /* */ /* */ /********************************************************************************************************/ private void Initialise() { // only Initialization fsuipc fsuipc_Write.FSUIPC_Initialization(); this.status[0] = (int)StatusFlag.Initialised; } private void Connect() { if (fsuipc_Write.FSUIPC_Open(dwFSReq, ref dwResult)) this.status[1] = (int)StatusFlag.Engaged; else this.status[1] = -2; } private void Disconnect() { fsuipc_Write.FSUIPC_Close(); this.status[2] = (int)StatusFlag.Disengaged; stateMachine((int)StatusFlag.Stopped); } private void Stop() { this.status[3] = (int)StatusFlag.Stopped; } /* ******************************************************************************************************/ /* */ /* Inputs and Outputs */ /* */ /* */ /********************************************************************************************************/ public void output() { InitialisingStatus = "Through plug-ins FSUIPC initializing the P3D!"; if (this.status[0] == 0) { InitialisedStatus = "Through plug-ins FSUIPC initialized the P3D!"; this.simulatorStatusOutput[0] = this.status[0]; ConnectingStatus = "Through plug-ins FSUIPC connecting the P3D!"; if (this.status[1] == 1) { ConnectedStatus = "Through plug-ins FSUIPC connected the P3D!"; this.simulatorStatusOutput[1] = this.status[1]; DisconnectingStatus = "Through plug-ins FSUIPC canceling connect the P3D!"; if (this.status[2] == 2) { DisconnectedStatus = "Through plug-ins FSUIPC canceled connect the P3D!"; this.simulatorStatusOutput[2] = this.status[2]; if (this.status[3] == 3) { StopStatus = "Stop using plug-in FSUIPC communicate with P3D!"; this.status[0] = -255; this.status[1] = -255; this.status[2] = -255; this.status[3] = -255; } } else { DisconnectedStatus = "Failed to through plug-ins FSUIPC cancel connect the P3D!"; this.simulatorStatusOutput[2] = -3; } } else { ConnectedStatus = "Failed to through plug-ins FSUIPC connect the P3D!"; this.simulatorStatusOutput[1] = this.status[1]; } } else { InitialisedStatus = "Failed to through plug-ins FSUIPC initialized the P3D!"; this.simulatorStatusOutput[0] = -1; } } public void input(double[] ControlSurface) { fsuipc_write(ControlSurface); } public void input(int AutoPilot) { fsuipc_write(AutoPilot); } /* ******************************************************************************************************/ /* */ /* Local Functions */ /* */ /* */ /********************************************************************************************************/ /// <summary> /// Process read or write /// </summary> /// <param name="dwOffset">The memory offset where the referenced value is located</param> /// <param name="dwSize">The number of bytes comprising of the referenced value</param> /// <param name="type">select read or write</param> /// <param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> private void ReadWriteFsuipc(int dwOffset, int dwSize, int type, ref int dwResult) { switch (type) { case 1: // Read result = fsuipc_Write.FSUIPC_Read(dwOffset, dwSize, ref token, ref dwResult); result = fsuipc_Write.FSUIPC_Process(ref dwResult); result = fsuipc_Write.FSUIPC_Get(ref token, ref dwResult); break; case 2: // write result = fsuipc_Write.FSUIPC_Write(dwOffset, dwSize, ref token, ref dwResult); result = fsuipc_Write.FSUIPC_Process(ref dwResult); break; default: break; } //Thread.Sleep(1); } /// <summary> /// To write the value of the controller into the simulator /// </summary> private void fsuipc_write(double[] ControlSurface) { //Thread.Sleep(10); // Elevator(Column). if (ControlSurface[0] >= 0) ReadWriteFsuipc(ElevatorReadOffset, (int)Math.Round(ControlSurface[0] * ElevatorOutputMax, 0), 2, ref dwResult); else ReadWriteFsuipc(ElevatorReadOffset, (int)Math.Round(ControlSurface[0] * ElevatorOutputMin, 0), 2, ref dwResult); //Thread.Sleep(10); // Aileron(Wheel). if (ControlSurface[1] >= 0) ReadWriteFsuipc(AileronReadOffset, (int)Math.Round(ControlSurface[1] * AileronOutputMax, 0), 2, ref dwResult); else ReadWriteFsuipc(AileronReadOffset, (int)Math.Round(ControlSurface[1] * AileronOutputMin, 0), 2, ref dwResult); //Thread.Sleep(10); // Rudder. if (ControlSurface[2] >= 0) ReadWriteFsuipc(RudderReadOffset, (int)Math.Round(ControlSurface[2] * RudderOutputMax, 0), 2, ref dwResult); else ReadWriteFsuipc(RudderReadOffset, (int)Math.Round(ControlSurface[2] * RudderOutputMin, 0), 2, ref dwResult); } private void fsuipc_write(int AutoPilot) { ReadWriteFsuipc(AutoPilotStatusReadOffset, AutoPilot, 2, ref dwResult); } }
Thomas Richter Posted December 26, 2017 Report Posted December 26, 2017 Hi, 22 hours ago, Primo said: System.ArgumentOutOfRangeException: Requested range extends past the end of the array. I don't see anything wrong in that code snip. Do you check on Initialize the FS version maybe and your array is too small as it needs to be increased for P3Dv4 if you work with P3Dv4? 1 = FS98 2 = FS2000 3 = CFS2 4 = CFS1 5 = reserved 6 = FS2002 7 = FS2004 “A Century of Flight” 8 = FSX 9 = ESP 10=P3D11=(???) 12=P3Dv4 Thomas
Primo Posted December 26, 2017 Author Report Posted December 26, 2017 25 minutes ago, Thomas Richter said: Hi, I don't see anything wrong in that code snip. Do you check on Initialize the FS version maybe and your array is too small as it needs to be increased for P3Dv4 if you work with P3Dv4? 1 = FS98 2 = FS2000 3 = CFS2 4 = CFS1 5 = reserved 6 = FS2002 7 = FS2004 “A Century of Flight” 8 = FSX 9 = ESP 10=P3D11=(???) 12=P3Dv4 Thomas Thomas, Thanks for your help! Yes, I'm work with P3Dv4, and FSUIPC version 5.103103. /** * FSUIPC Developer Kit: Library for C#.NET programmers * Version 1.11 (03/05/2004) by Scott McCrory <scott@mccrory.us> and Bob Scott <w6kd@yahoo.com> * * Original Copyright (?) 2000 Chris Brett. All rights reserved. * e-mail: chris@formulate.clara.net * * Rewritten for Visual Basic .NET By Bob Scott * e-mail w6kd@amsat.org * * Rewritten for C#.NET by Scott McCrory and revised by Bob Scott * e-mail scott@mccrory.us * * Function library for FSUIPC based on C code supplied by Pete Dowson * * BASIC USAGE GOES LIKE THIS: * 0. Instantiate the FsuipcSdk.Fsuipc class (i.e. Fsuipc f = new Fsuipc();). * 1. Call f.FSUIPC_Initialization() at beginning of program (optional). * 2. Call f.FSUIPC_Open() to connect with FSUIPC if it's available. * 3. Call f.FSUIPC_Read and/or f.FSUIPC_Write one or more times to build * the list of actions to be performed by the next step. * 4. Call f.FSUIPC_Process() to actually get/set the data from/to FS. * 5. For reads, call f.FSUIPC_Get to retrieve data read from FSUIPC. * 6. Repeat steps 3, 4, and 5 as necessary. * 7. At program termination, call f.FSUIPC_Close(). * **/ using System; using System.Runtime.InteropServices; namespace FsuipcSDK { public class Fsuipc { // Constants public const int SMTO_ABORTIFHUNG = 0x2; public const int SMTO_BLOCK = 0x1; public const int SMTO_NORMAL = 0x0; public const int PAGE_READWRITE = 0x4; public const int NO_ERROR = 0; public const int ERROR_ALREADY_EXISTS = 0x183; public const int SECTION_MAP_WRITE = 0x2; public const int FILE_MAP_WRITE = SECTION_MAP_WRITE; // FSUIPC SPECIFICS // Supported Sims public const int SIM_ANY = 0; public const int SIM_FS98 = 1; public const int SIM_FS2K = 2; public const int SIM_CFS2 = 3; public const int SIM_CFS1 = 4; public const int SIM_FLY = 5; public const int SIM_FS2K2 = 6; public const int SIM_FS2K4 = 7; public const int SIM_FSX = 8; public const int SIM_ESP = 9; // Error numbers public const int FSUIPC_ERR_OK = 0; public const int FSUIPC_ERR_OPEN = 1; // Attempt to Open when already Open public const int FSUIPC_ERR_NOFS = 2; // Cannot link to FSUIPC or WideClient public const int FSUIPC_ERR_REGMSG = 3; // Failed to Register common message with Windows public const int FSUIPC_ERR_ATOM = 4; // Failed to create Atom for mapping filename public const int FSUIPC_ERR_MAP = 5; // Failed to create a file mapping object public const int FSUIPC_ERR_VIEW = 6; // Failed to open a view to the file map public const int FSUIPC_ERR_VERSION = 7; // Incorrect version of FSUIPC, or not FSUIPC public const int FSUIPC_ERR_WRONGFS = 8; // Sim is not version requested public const int FSUIPC_ERR_NOTOPEN = 9; // Call cannot execute, link not Open public const int FSUIPC_ERR_NODATA = 10; // Call cannot execute: no requests accumulated public const int FSUIPC_ERR_TIMEOUT = 11; // IPC timed out all retries public const int FSUIPC_ERR_SENDMSG = 12; // IPC sendmessage failed all retries public const int FSUIPC_ERR_DATA = 13; // IPC request contains bad data public const int FSUIPC_ERR_RUNNING = 14; // Maybe running on WideClient, but FS not running on Server, or wrong FSUIPC public const int FSUIPC_ERR_SIZE = 15; public const int FSUIPC_ERR_BUFOVERFLOW = 16; public const int IPC_BUFFER_SIZE = 65568; public const int LEN_RD_HDR = 16; // Length of an IPC Read Header (4x 4-byte Integers) public const int LEN_WR_HDR = 12; // Length of an IPC Write Header (3x 4-byte Integers) public const int LIB_VERSION = 2000; // 2.000 public const int MAX_SIZE = 0x7F00; // Largest data (kept below 32k to avoid // any possible 16-bit sign problems public const int MAX_REQ_SIZE = 1024; // Maximum single request block size public const string FS6IPC_MSGNAME1 = "FSASMLIB:IPC"; public const string FS6IPC_MSGNAME2 = "EFISFSCOM:IPC"; public const int FS6IPC_MESSAGE_SUCCESS = 1; public const int FS6IPC_MESSAGE_FAILURE = 0; // IPC message types public const int FS6IPC_READSTATEDATA_ID = 1; public const int FS6IPC_WRITESTATEDATA_ID = 2; public const int FS6IPC_SPECIALREQUEST_ID = 0xABAC; // Instance variables for the UIPC communication byte[] IPC = new byte[IPC_BUFFER_SIZE]; // IPC Data Buffer bool[] IPCdr = new bool[IPC_BUFFER_SIZE]; // Data waiting flags int IPCAlloc; // Data Buffer Allocation Index int FSUIPC_Version; int FSUIPC_FS_Version; int FSUIPC_Lib_Version = 0; int m_hWnd; // FS window handle int m_msg; // ID of registered window message int m_atom; // global atom containing name of file-mapping object int m_hMap; // handle of file-mapping object int m_pView; // pointer to view of file-mapping object int m_pNext; // pointer into FSUIPC data buffer area // External Win32 libraries public const string KER_DLL = "kernel32.dll"; // Import library for Kernel on Win32 public const string USR_DLL = "user32.dll"; // Import library for User on Win32 // We'll need to access some Windows API functions located in kernel32.dll [DllImport(KER_DLL)] public static extern void RtlZeroMemory(IntPtr dDestination, int length); [DllImport(KER_DLL)] public static extern void RtlMoveMemory(IntPtr pDest, IntPtr pSrc, int ByteLen); [DllImport(KER_DLL)] public static extern void Sleep(int dwMilliseconds); [DllImport(KER_DLL)] public static extern int GetCurrentProcessId(); [DllImport(KER_DLL)] public static extern int GlobalAddAtomA(string lpstring); [DllImport(KER_DLL)] public static extern int CreateFileMappingA(uint hFile, int lpFileMappigAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName); [DllImport(KER_DLL)] public static extern int GetLastError(); [DllImport(KER_DLL)] public static extern int MapViewOfFile(int hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap); [DllImport(KER_DLL)] public static extern int MapViewOfFileEx(int hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap, IntPtr lpBaseAddress); [DllImport(KER_DLL)] public static extern int GlobalDeleteAtom(int nAtom); [DllImport(KER_DLL)] public static extern int UnmapViewOfFile(IntPtr lpBaseAddress); [DllImport(KER_DLL)] public static extern int CloseHandle(int hObject); // We'll also need to access some Windows API functions located in user32.dll [DllImport(USR_DLL)] public static extern int SendMessageTimeoutA(int hwnd, int msg, int wparam, int lparam, int fuFlags, int uTimeout, int lpdwResult); [DllImport(USR_DLL)] public static extern int FindWindowExA(int hWnd1, int hWnd2, string lpsz1, string lpsz2); [DllImport(USR_DLL)] public static extern int RegisterWindowMessageA(string lpstring); // Our main object contructor public Fsuipc() { FSUIPC_Close(); FSUIPC_Initialization(); } // --- Misc toggle functions --------------------------------------------------- ///<summary>Toggles a byte between 0 and 1</summary> ///<param name="arg1">The byte to toggle</param> ///<return>The toggled byte</return> public byte toggle(byte arg1) { if (arg1 == 0) { return 1; } else { return 0; } } ///<summary>Toggles a short between 0 and 1</summary> ///<param name="arg1">The short to toggle</param> ///<return>The toggled short</return> public short toggle(short arg1) { if (arg1 == 0) { return 1; } else { return 0; } } ///<summary>Toggles an int between 0 and 1</summary> ///<param name="arg1">The int to toggle</param> ///<return>The toggled int</return> public int toggle(int arg1) { if (arg1 == 0) { return 1; } else { return 0; } } // --- Initialize the Client --------------------------------------------------- ///<summary>Initializes the FSUIPC Client</summary> public void FSUIPC_Initialization() { for (int idx = 0; idx < IPC_BUFFER_SIZE; idx++) { IPC[idx] = 0; IPCdr[idx] = false; } IPCAlloc = 0; m_hWnd = 0; m_msg = 0; m_atom = 0; m_hMap = 0; m_pView = 0; m_pNext = 0; } // --- Opens/Start the Client -------------------------------------------------------- ///<summary>Opens an FSUIPC client connection</summary> ///<param name="dwFSReq">An int describing what FS version requested</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Open(int dwFSReq, ref int dwResult) { string szName = ""; //string szTemp = ""; bool fWideFS = false; int nTry = -1; int i = -1; // initialize vars nTry = 0; fWideFS = false; i = 0; FSUIPC_Version = 0; FSUIPC_FS_Version = 0; // abort if already started if (m_pView != 0) { dwResult = FSUIPC_ERR_OPEN; return false; } // Connect via FSUIPC, which is known to be FSUIPC's own // and isn't subject to user modification m_hWnd = FindWindowExA(0, 0, "UIPCMAIN", null); if (m_hWnd == 0) { // if there's no UIPCMAIN, we may be using WideClient // which only simulates FS98 m_hWnd = FindWindowExA(0, 0, "FS98MAIN", null); fWideFS = true; if (m_hWnd == 0) { dwResult = FSUIPC_ERR_NOFS; return false; } } // register the window message m_msg = RegisterWindowMessageA(FS6IPC_MSGNAME1); if (m_msg == 0) { dwResult = FSUIPC_ERR_REGMSG; return false; } // create the name of our file-mapping object nTry = nTry + 1; // Ensures a unique string is used in case user closes and reopens szName = FS6IPC_MSGNAME1 + ":" + GetCurrentProcessId().ToString("x") + ":" + nTry.ToString("x") + Convert.ToChar(0).ToString(); if (szName.Length > 23) { //24 chars max szName = szName.Substring(0, 23) + Convert.ToChar(0).ToString(); } // stuff the name into a global atom m_atom = GlobalAddAtomA(szName); if (m_atom == 0) { dwResult = FSUIPC_ERR_ATOM; FSUIPC_Close(); return false; } // create the file-mapping object // use system paging file // security attrubute (0 = can! inherit) // protection // size // name m_hMap = CreateFileMappingA(0xFFFFFFFF, 0, PAGE_READWRITE, 0, MAX_SIZE + 256, szName); if ((m_hMap == 0) || (GetLastError() == ERROR_ALREADY_EXISTS)) { dwResult = FSUIPC_ERR_MAP; FSUIPC_Close(); return false; } // spawn a view of the file-mapping object m_pView = MapViewOfFile(m_hMap, FILE_MAP_WRITE, 0, 0, 0); if (m_pView == 0) { dwResult = FSUIPC_ERR_VIEW; FSUIPC_Close(); return false; } // Okay, now determine FSUIPC version AND FS type m_pNext = m_pView; // Try up to 5 times with a 100msec rest between each // Note that WideClient returns zeros initially, whilst waiting // for the Server to get the data do { i++; // Read FSUIPC version int t_FSUIPC_Version = 0; if (!FSUIPC_Read(0x3304, 4, ref t_FSUIPC_Version, ref dwResult)) { FSUIPC_Close(); return false; } // and FS version and validity check pattern int t_FSUIPC_FS_Version = 0; if (!FSUIPC_Read(0x3308, 4, ref t_FSUIPC_FS_Version, ref dwResult)) { FSUIPC_Close(); return false; } // write our Library version number to a special read-only offset // This is to assist diagnosis from FSUIPC logging // But only do this on first try int t_FSUIPC_Lib_Version = 0; if (i < 2 && FSUIPC_Write(0x330A, 2, ref t_FSUIPC_Lib_Version, ref dwResult) == false) { FSUIPC_Close(); return false; } // Actually send the request and get the responses ("process") if (!FSUIPC_Process(ref dwResult)) { FSUIPC_Close(); return false; } bool VersionGet = FSUIPC_Get(ref t_FSUIPC_Version, ref FSUIPC_Version); VersionGet = FSUIPC_Get(ref t_FSUIPC_FS_Version, ref FSUIPC_FS_Version); VersionGet = FSUIPC_Get(ref t_FSUIPC_Lib_Version, ref FSUIPC_Lib_Version); // Maybe running on WideClient, and need another try Sleep(100); // Give it a chance } while ((i < 5) && ((FSUIPC_Version == 0) || (FSUIPC_FS_Version == 0))); // Only allow running on FSUIPC 1.998e or later // with correct check pattern &HFADE if ((FSUIPC_Version < 0x19980005) || ((FSUIPC_FS_Version & 0xFFFF0000) != 0xFADE0000)) { if (fWideFS) { dwResult = FSUIPC_ERR_RUNNING; } else { dwResult = FSUIPC_ERR_VERSION; } FSUIPC_Close(); return false; } // grab the FS version number FSUIPC_FS_Version = (FSUIPC_FS_Version & 0xFFFF); // Optional version-specific request made? if so and wrong version, return error if (dwFSReq != 0 && dwFSReq != FSUIPC_FS_Version) { dwResult = FSUIPC_ERR_WRONGFS; FSUIPC_Close(); return false; } dwResult = FSUIPC_ERR_OK; return true; } //--- Read request --------------------------------------------------------------- ///<summary>Submits a read request</summary> ///<param name="dwOffset">The memory offset where the requested value is located</param> ///<param name="dwSize">The number of bytes comprising of the requested value</param> ///<param name="token">Contains the unique identifier token used to Get the value</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Read(int dwOffset, int dwSize, ref int Token, ref int dwResult) { int[] hdr = new int[4]; if ((IPCAlloc + dwSize + 4) >= (IPC_BUFFER_SIZE - 1)) { //Reset ptr to start of FifO buf IPCAlloc = 0; } // Assign Token as index into IPC Buffer FifO, and clear data ready flags Token = IPCAlloc; for (int i = IPCAlloc; i < (IPCAlloc + 4 + dwSize - 1); i++) { // 4=size of integer datablock size hdr IPC[i] = 0; IPCdr[i] = false; } IPCAlloc = IPCAlloc + 4 + dwSize; //first four bytes data block size (Int) plus data if (Token >= IPC_BUFFER_SIZE) { Token = -1; dwResult = FSUIPC_ERR_BUFOVERFLOW; return false; } // Check link is open if (m_pView == 0) { dwResult = FSUIPC_ERR_NOTOPEN; return false; } // Check have space for ( this request (including terminator) if ((m_pNext - m_pView + 4 + dwSize + LEN_RD_HDR) > MAX_SIZE) { dwResult = FSUIPC_ERR_SIZE; return false; } hdr[0] = FS6IPC_READSTATEDATA_ID; //Read request ID hdr[1] = dwOffset; //FSUIPC offset hdr[2] = dwSize; //data element size hdr[3] = Token; //index into managed data buffer IPC IntPtr _pNext = new IntPtr(m_pNext); Marshal.Copy(hdr, 0, _pNext, 4); //Header to FSUIPC data buffer // Move pointer past the Record m_pNext = m_pNext + LEN_RD_HDR; if (dwSize != 0) { // Zero the data reception area, so rubbish won//t be returned _pNext = new IntPtr(m_pNext); RtlZeroMemory(_pNext, dwSize); // Update the pointer ready for ( more data m_pNext = m_pNext + dwSize; } dwResult = FSUIPC_ERR_OK; return true; } //--- Process read/write ------------------------------------------------------ ///<summary>Processes read or write request</summary> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Process(ref int dwResult) { int dwError = 0; int[] hdr = new int[4]; int i = 0; if (m_pView == 0) { dwResult = FSUIPC_ERR_NOTOPEN; return false; } if (m_pView == m_pNext) { dwResult = FSUIPC_ERR_NODATA; return false; } // Write FSUIPC Data Area Terminator IntPtr _pNext = new IntPtr(m_pNext); RtlZeroMemory(_pNext, 4); m_pNext = m_pView; // send the request (allow up to 10 tries) i = 0; while (i < 10 && SendMessageTimeoutA(m_hWnd, m_msg, m_atom, 0, SMTO_BLOCK, 5000, dwError) == 0) // m_hWnd, // FS6 window handle // m_msg, // our registered message id // m_atom, // wparam: name of file-mapping object // 0, // lparam: offset of request into file-mapping obj // SMTO_BLOCK, // halt this thread until we get a response // 2000, // time out interval // dwError)) = 0) do begin // return value { i++; Sleep(100); // Allow for things to happen } if (i >= 10) { // Failed all tries if (GetLastError() == 0) { dwResult = FSUIPC_ERR_TIMEOUT; } else { dwResult = FSUIPC_ERR_SENDMSG; } return false; } // did IPC like the data request? //if (dwError != FS6IPC_MESSAGE_SUCCESS) { // // no... // dwResult = FSUIPC_ERR_DATA; // return false; //} // Decode and store results of Read requests m_pNext = m_pView; _pNext = new IntPtr(m_pNext); Marshal.Copy(_pNext, hdr, 0, 1); m_pNext = m_pNext + 4; //Advance ptr 4 bytes for Header pre-read // hdr[0) Operation ID (1=Read, 2=Write) // hdr[1) FSUIPC Offset value // hdr[2) Size of bata block to pass (bytes) // hdr[3) Token (offset into IPC FifO buffer) while (hdr[0] != 0) { switch (hdr[0]) { case FS6IPC_READSTATEDATA_ID: // copy the data FSUIPC read into the local FifO buffer _pNext = new IntPtr(m_pNext); Marshal.Copy(_pNext, hdr, 1, 3); m_pNext = m_pNext + LEN_RD_HDR - 4; if (hdr[2] != 0) { _pNext = new IntPtr(m_pNext); IntPtr _nBytes = Marshal.AllocHGlobal(4); //Ptr to # of bytes in record Marshal.WriteInt32(_nBytes, hdr[2]); //Write datablock size as block header Marshal.Copy(_nBytes, IPC, hdr[3], 4); //Write data into FifO buffer Marshal.FreeHGlobal(_nBytes); Marshal.Copy(_pNext, IPC, hdr[3] + 4, hdr[2]); //Copy data to IPC(Token) IPCdr[hdr[3]] = true; //Flag - data available for retrieval } m_pNext = m_pNext + hdr[2]; //Increment read buffer ptr by size of data element passed break; case FS6IPC_WRITESTATEDATA_ID: // Write transaction, no return data...pull header from datastream and waste _pNext = new IntPtr(m_pNext); Marshal.Copy(_pNext, hdr, 1, 2); m_pNext = m_pNext + LEN_WR_HDR - 4 + hdr[2]; break; default: // Invalid Operation ID...abort m_pNext = m_pView; return false; } _pNext = new IntPtr(m_pNext); Marshal.Copy(_pNext, hdr, 0, 1); m_pNext = m_pNext + 4; } m_pNext = m_pView; dwResult = FSUIPC_ERR_OK; return true; } //--- Internal Write request ------------------------------------------------------ ///<summary>Submits an "internal" write request, used by FSUIPC_Write</summary> ///<param name="dwOffset">The memory offset where the referenced value is located</param> ///<param name="dwSize">The number of bytes comprising of the referenced value</param> ///<param name="token">Contains the unique identifier token used to Get the value</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> private bool FSUIPC_Write_Req(int dwOffset, int dwSize, int Token, ref int dwResult) { int[] hdr = new int[4]; if (Token >= IPC_BUFFER_SIZE) { Token = -1; dwResult = FSUIPC_ERR_BUFOVERFLOW; return false; } // abort if necessary if (m_pView == 0) { dwResult = FSUIPC_ERR_NOTOPEN; return false; } // Check have FSUIPC buffer space for this request (including terminator) if ((((m_pNext) - (m_pView)) + 4 + (dwSize + LEN_WR_HDR)) > MAX_SIZE) { dwResult = FSUIPC_ERR_SIZE; return false; } // Initialise header for write request hdr[0] = FS6IPC_WRITESTATEDATA_ID; hdr[1] = dwOffset; hdr[2] = dwSize; IntPtr _pNext = new IntPtr(m_pNext); Marshal.Copy(hdr, 0, _pNext, 3); //Write header to FSUIPC data buffer // Move pointer past the record m_pNext = m_pNext + LEN_WR_HDR; if (dwSize != 0) { _pNext = new IntPtr(m_pNext); //convert int index to ptr into FSUIPC buffer Marshal.Copy(IPC, Token + 4, _pNext, dwSize); // Update the pointer ready for more data m_pNext = m_pNext + dwSize; } dwResult = FSUIPC_ERR_OK; return true; } //--- Write requests -------------------------------------------------------------- ///<summary>Submits a write request</summary> ///<param name="dwOffset">The memory offset where the referenced value is located</param> ///<param name="param">The value to be written</param> ///<param name="token">Contains the unique identifier token used to Get the value</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Write(int dwOffset, byte param, ref int Token, ref int dwResult) { int DataElementSize = 1; if ((IPCAlloc + DataElementSize + 4) >= (IPC_BUFFER_SIZE - 1)) { //Reset ptr to startbuf IPCAlloc = 0; } // Assign Token as index into IPC Buffer FifO, and clear data ready flags Token = IPCAlloc; int i; for (i = IPCAlloc; i < (IPCAlloc + 4 + DataElementSize - 1); i++) { // 4=size of int datablock size hdr IPC[i] = 0; IPCdr[i] = false; } IPCAlloc = IPCAlloc + 4 + DataElementSize; //first four bytes data block size (Int) plus data IntPtr heapbuf = Marshal.AllocHGlobal(4 + DataElementSize); Marshal.WriteInt32(heapbuf, DataElementSize); // Translate token to unmanaged byte stream Marshal.Copy(heapbuf, IPC, Token, 4); Marshal.WriteByte(heapbuf, param); // Transloate data and put in IPC array Marshal.Copy(heapbuf, IPC, Token + 4, DataElementSize); Marshal.FreeHGlobal(heapbuf); return FSUIPC_Write_Req(dwOffset, DataElementSize, Token, ref dwResult); } ///<summary>Submits a write request</summary> ///<param name="dwOffset">The memory offset where the referenced value is located</param> ///<param name="param">The value to be written</param> ///<param name="token">Contains the unique identifier token used to Get the value</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Write(int dwOffset, short param, ref int Token, ref int dwResult) { int DataElementSize = 2; if ((IPCAlloc + DataElementSize + 4) >= (IPC_BUFFER_SIZE - 1)) { //Reset ptr to startbuf IPCAlloc = 0; } // Assign Token as index into IPC Buffer FifO, and clear data ready flags Token = IPCAlloc; int i; for (i = IPCAlloc; i < (IPCAlloc + 4 + DataElementSize - 1); i++) { // 4=size of int datablock size hdr IPC[i] = 0; IPCdr[i] = false; } IPCAlloc = IPCAlloc + 4 + DataElementSize; //first four bytes data block size (Int) plus data IntPtr heapbuf = Marshal.AllocHGlobal(4 + DataElementSize); Marshal.WriteInt32(heapbuf, DataElementSize); // Translate token to unmanaged byte stream Marshal.Copy(heapbuf, IPC, Token, 4); Marshal.WriteInt16(heapbuf, param); // Transloate data and put in IPC array Marshal.Copy(heapbuf, IPC, Token + 4, DataElementSize); Marshal.FreeHGlobal(heapbuf); return FSUIPC_Write_Req(dwOffset, DataElementSize, Token, ref dwResult); } ///<summary>Submits a write request</summary> ///<param name="dwOffset">The memory offset where the referenced value is located</param> ///<param name="param">The value to be written</param> ///<param name="token">Contains the unique identifier token used to Get the value</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Write(int dwOffset, int param, ref int Token, ref int dwResult) { int DataElementSize = 4; if ((IPCAlloc + DataElementSize + 4) >= (IPC_BUFFER_SIZE - 1)) { //Reset ptr to startbuf IPCAlloc = 0; } // Assign Token as index into IPC Buffer FifO, and clear data + ready flags Token = IPCAlloc; int i; for (i = IPCAlloc; i < (IPCAlloc + 4 + DataElementSize - 1); i++) { // 4=size of int datablock size hdr IPC[i] = 0; IPCdr[i] = false; } IPCAlloc = IPCAlloc + 4 + DataElementSize; //first four bytes data block size (Int) plus data IntPtr heapbuf = Marshal.AllocHGlobal(4 + DataElementSize); Marshal.WriteInt32(heapbuf, DataElementSize); // Translate token to unmanaged byte stream Marshal.Copy(heapbuf, IPC, Token, 4); Marshal.WriteInt32(heapbuf, param); // Transloate data and put in IPC array Marshal.Copy(heapbuf, IPC, Token + 4, DataElementSize); Marshal.FreeHGlobal(heapbuf); return FSUIPC_Write_Req(dwOffset, DataElementSize, Token, ref dwResult); } ///<summary>Submits a write request</summary> ///<param name="dwOffset">The memory offset where the referenced value is located</param> ///<param name="param">The value to be written</param> ///<param name="token">Contains the unique identifier token used to Get the value</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Write(int dwOffset, long param, ref int Token, ref int dwResult) { int DataElementSize = 8; if ((IPCAlloc + DataElementSize + 4) >= (IPC_BUFFER_SIZE - 1)) { //Reset ptr to startbuf IPCAlloc = 0; } // Assign Token as index into IPC Buffer FifO, and clear data ready flags Token = IPCAlloc; int i; for (i = IPCAlloc; i < (IPCAlloc + 4 + DataElementSize - 1); i++) { // 4=size of int datablock size hdr IPC[i] = 0; IPCdr[i] = false; } IPCAlloc = IPCAlloc + 4 + DataElementSize; //first four bytes data block size (Int) plus data IntPtr heapbuf = Marshal.AllocHGlobal(4 + DataElementSize); Marshal.WriteInt32(heapbuf, DataElementSize); // Translate token to unmanaged byte stream Marshal.Copy(heapbuf, IPC, Token, 4); Marshal.WriteInt64(heapbuf, param); // Transloate data and put in IPC array Marshal.Copy(heapbuf, IPC, Token + 4, DataElementSize); Marshal.FreeHGlobal(heapbuf); return FSUIPC_Write_Req(dwOffset, DataElementSize, Token, ref dwResult); } ///<summary>Submits a write request</summary> ///<param name="dwOffset">The memory offset where the referenced value is located</param> ///<param name="param">The value to be written</param> ///<param name="token">Contains the unique identifier token used to Get the value</param> ///<param name="dwResult">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Write(int dwOffset, int dwSize, ref byte[] param, ref int Token, ref int dwResult) { if ((IPCAlloc + dwSize + 4) >= (IPC_BUFFER_SIZE - 1)) { //Reset ptr to startbuf IPCAlloc = 0; } // Assign Token as index into IPC Buffer FifO, and clear data ready flags Token = IPCAlloc; int i; for (i = IPCAlloc; i < (IPCAlloc + 4 + dwSize - 1); i++) { // 4=size of int datablock size hdr IPC[i] = 0; IPCdr[i] = false; } IPCAlloc = IPCAlloc + 4 + dwSize; //first four bytes data block size (Int) plus data IntPtr heapbuf = Marshal.AllocHGlobal(4); Marshal.WriteInt32(heapbuf, dwSize); // Translate size Int32 to unmanaged byte stream Marshal.Copy(heapbuf, IPC, Token, 4); // Write size header to IPC array Marshal.FreeHGlobal(heapbuf); for (i = 0; i < dwSize; i++) { IPC[Token + 4 + i] = param[i]; //xfer byte array to IPC managed FifO buffer } return FSUIPC_Write_Req(dwOffset, dwSize, Token, ref dwResult); } //--- Read requests ---------------------------------------------------------------- ///<summary>Retrieve data read from FSUIPC using token passed during read request</summary> ///<param name="token">The unique identifier token returned from the Read call</param> ///<param name="result">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Get(ref int Token, ref byte Result) { int Size = 1; // 1 byte if ((Token < 0) || (Token > IPC_BUFFER_SIZE - (4 + Size))) { //Token out of range Result = 0; return false; } IntPtr heapbuf = Marshal.AllocHGlobal(Size); Marshal.Copy(IPC, Token + 4, heapbuf, 1); Result = Marshal.ReadByte(heapbuf); Marshal.FreeHGlobal(heapbuf); if (IPCdr[Token]) { IPCdr[Token] = false; // reset data ready flag return true; } else { // if (data ready flag not set, function returns false and old buffer value return false; } } ///<summary>Retrieve data read from FSUIPC using token passed during read request</summary> ///<param name="token">The unique identifier token returned from the Read call</param> ///<param name="result">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Get(ref int Token, ref short Result) { int Size = 2; // 2 bytes in a short if ((Token < 0) || (Token > IPC_BUFFER_SIZE - (4 + Size))) { //Token out of range Result = 0; return false; } IntPtr heapbuf = Marshal.AllocHGlobal(Size); Marshal.Copy(IPC, Token + 4, heapbuf, 2); Result = Marshal.ReadInt16(heapbuf); Marshal.FreeHGlobal(heapbuf); if (IPCdr[Token]) { IPCdr[Token] = false; // reset data ready flag return true; } else { // if (data ready flag not set, function returns false and old buffer value return false; } } ///<summary>Retrieve data read from FSUIPC using token passed during read request</summary> ///<param name="token">The unique identifier token returned from the Read call</param> ///<param name="result">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Get(ref int Token, ref int Result) { int Size = 4; // 2 bytes in an int if ((Token < 0) || (Token > IPC_BUFFER_SIZE - (4 + Size))) { //Token out of range Result = 0; return false; } IntPtr heapbuf = Marshal.AllocHGlobal(Size); Marshal.Copy(IPC, Token + 4, heapbuf, 4); Result = Marshal.ReadInt32(heapbuf); Marshal.FreeHGlobal(heapbuf); if (IPCdr[Token]) { IPCdr[Token] = false; return true; } else { // if (data ready flag not set, function returns false and value found return false; } } ///<summary>Retrieve data read from FSUIPC using token passed during read request</summary> ///<param name="token">The unique identifier token returned from the Read call</param> ///<param name="result">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Get(ref int Token, ref long Result) { int Size = 8; // 8 bytes in a Long Int IntPtr heapbuf = Marshal.AllocHGlobal(Size); if ((Token < 0) || (Token > IPC_BUFFER_SIZE - (4 + Size))) { //Token out of range Result = 0; return false; } Marshal.Copy(IPC, Token + 4, heapbuf, 8); Result = Marshal.ReadInt64(heapbuf); Marshal.FreeHGlobal(heapbuf); if (IPCdr[Token]) { IPCdr[Token] = false; return true; } else { // if (data ready flag not set, function returns false and value found return false; } } ///<summary>Retrieve data read from FSUIPC using token passed during read request</summary> ///<param name="token">The unique identifier token returned from the Read call</param> ///<param name="dwSize">The size of memory locations in bytes</param> ///<param name="result">Contains the "error-code" if method's boolean comes back false</param> ///<return>true if successful, false otherwise. If false, dwResult contains the "error-code"</return> public bool FSUIPC_Get(ref int Token, int dwSize, ref byte[] Result) { if ((Token < 0) || (Token > IPC_BUFFER_SIZE - (4 + dwSize))) { //Token out of range return false; } IntPtr heapbuf = Marshal.AllocHGlobal(4); Marshal.Copy(IPC, Token, heapbuf, 4); int Size = Marshal.ReadInt32(heapbuf); Marshal.FreeHGlobal(heapbuf); if (dwSize > Size) { dwSize = Size; //Max size of return block is size of block written } int idx = Token + 4; //go past size block while (idx < Token + 4 + dwSize) { Result[idx - Token - 4] = IPC[idx]; idx = idx + 1; } if (IPCdr[Token]) { IPCdr[Token] = false; return true; } else { // if (data ready flag not set, function returns false and value found return false; } } // --- Stop the Client --------------------------------------------------------- ///<summary>Closes the FSUIPC client connection</summary> public void FSUIPC_Close() { m_hWnd = 0; m_msg = 0; m_pNext = 0; if (m_atom != 0) { GlobalDeleteAtom(m_atom); m_atom = 0; } if (m_pView != 0) { IntPtr _pView = new IntPtr(m_pView); UnmapViewOfFile(_pView); m_pView = 0; } if (m_hMap != 0) { CloseHandle(m_hMap); m_hMap = 0; } } } }
Thomas Richter Posted December 26, 2017 Report Posted December 26, 2017 Hi, just increase your FS versions check up to value 12 as P3Dv4 returns for Offset 0x3308 value 12. But also see below 40 minutes ago, Primo said: if (!FSUIPC_Read(0x3308, 4, ref t_FSUIPC_FS_Version, ref dwResult)) Offset 0x3308 is not 4 byte (int32) but it is 2 byte (int16, short), so you read for FS_Version Offset 0x3308 & 0x330A. Thomas
Primo Posted December 26, 2017 Author Report Posted December 26, 2017 15 minutes ago, Thomas Richter said: Hi, just increase your FS versions check up to value 12 as P3Dv4 returns for Offset 0x3308 value 12. But also see below Offset 0x3308 is not 4 byte (int32) but it is 2 byte (int16, short), so you read for FS_Version Offset 0x3308 & 0x330A. Thomas OK, Thanks for your help!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now