'Invalid FORMATETC structure' C# while drag and drop - c#

I am trying to convert the dataObject's data to CF_HDROP format when a drag operation starts. I was able to read the byteArray, which I will store at some point, but for now I am hard-coding the path to a file that actually exists on my drive.
I have used this C# drag-drop problem as a reference.
Here my implementation for OleDragEnter function:
public int OleDragEnter(object pDataObj, int grfKeyState, long pt, ref int pdwEffect)
{
if (pDataObj is IDataObject dataOb)
{
IEnumFORMATETC formatetc = dataOb.EnumFormatEtc(DATADIR.DATADIR_GET);
List<FORMATETC> formatetcList = GetFormatEtcList(formatetc);
if (formatetcList.Exists(f => f.tymed == TYMED.TYMED_ISTREAM))
{
FORMATETC iStreamFormatetc = formatetcList.Find(f => f.tymed == TYMED.TYMED_ISTREAM);
dataOb.GetData(ref iStreamFormatetc, out var stgmedium);
MemoryStream memStream = GetIStream(stgmedium);
byte[] rawData = memStream.ToArray(); //I will store this on the drive at somepoint
var fileName = StreamHelpers.GetFullFileName(); //Constant for now
String[] strFiles = {fileName};
_DROPFILES dropFiles = new _DROPFILES();
int intChar, intFile, intDataLen, intPos;
IntPtr ipGlobal = IntPtr.Zero;
intDataLen = 0;
for (intFile = 0; intFile <= strFiles.GetUpperBound(0); intFile++)
{
intDataLen += strFiles[intFile].Length + 1;
}
intDataLen++;
var byteData = new Byte[intDataLen];
intPos = 0;
for (intFile = 0; intFile <= strFiles.GetUpperBound(0); intFile++)
{
for (intChar = 0; intChar < strFiles[intFile].Length; intChar++)
{
byteData[intPos++] = (byte)strFiles[intFile][intChar];
}
byteData[intPos++] = 0;
}
byteData[intPos++] = 0;
int intTotalLen = Marshal.SizeOf(dropFiles) + intDataLen;
ipGlobal = Marshal.AllocHGlobal(intTotalLen);
if (ipGlobal == IntPtr.Zero)
{
return -1;
}
dropFiles.pFiles = Marshal.SizeOf(dropFiles);
dropFiles.fWide = false;
Marshal.StructureToPtr(dropFiles, ipGlobal, false);
IntPtr ipNew = new IntPtr(ipGlobal.ToInt32() + Marshal.SizeOf(dropFiles));
Marshal.Copy(byteData, 0, ipNew, intDataLen);
var formatEtc = new FORMATETC
{
cfFormat = (short) CLIPFORMAT.CF_HDROP, //15
dwAspect = DVASPECT.DVASPECT_CONTENT,
lindex = -1,
tymed = TYMED.TYMED_HGLOBAL,
ptd = IntPtr.Zero
};
var stgMedium = new STGMEDIUM
{
unionmember = ipGlobal,
tymed = TYMED.TYMED_HGLOBAL,
pUnkForRelease = IntPtr.Zero
};
dataOb.SetData(ref formatEtc, ref stgMedium, false);
}
}
return 0;
}
I keep getting "Invalid FORMATETC structure" error on:
dataOb.SetData(ref formatEtc, ref stgMedium, false);
I have tried running the application in non-debug mode & verified the integrity of the file. I noticed that DATADIR.DATADIR_SET does not return any available formats. Could that be the problem?
Edit: It seems to also be happening when I try to use the same formatEtc Object and stgMedium Object used for reading the data without any change.

Related

performing DFU OTA using mcumgr in xamarin forms

I am very new to firmware updates and the whole zephyr rtos. I am trying to perform a firmware update using the mcumgr. I ran into some problems. I read the documentation, but it's not very well written and even the autor phrased that it isn't even complete. So the problem is that i split up my bin file into packets and add the header (i think this is working), but when the transfer completes, the firmware isn't uploaded to any slot on the device. I am learning and implementing this code from boogie https://github.com/boogie/mcumgr-web
This is my code. The DfuSend method runs on a button click.
public async void DfuSend()
{
if (SelectedFirmwareFile == null)
{
await Application.Current.MainPage.DisplayAlert("Error", "No file selected", "OK");
return;
}
var service = await Globals.ConnectedDevice.GetServiceAsync(GattIdentifiers.UartGattSMPServiceId);
if (service != null)
{
try
{
sendCharacteristic = await service.GetCharacteristicAsync(GattIdentifiers.UartGattSMPCharacteristicsId);
receiveCharacteristic = await service.GetCharacteristicAsync(GattIdentifiers.UartGattSMPCharacteristicsId);
uploadIsInProgress = true;
sendCharacteristic.WriteType = CharacteristicWriteType.WithoutResponse;
FirmwareFileBytes = File.ReadAllBytes(SelectedFirmwareFile.FullName);
while (uploadIsInProgress == true)
{
await _uploadNext();
HandleUploadProgress(_uploadOffset);
}
sendCharacteristic.WriteType = CharacteristicWriteType.WithResponse;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
else
{
await Application.Current.MainPage.DisplayAlert("Error", "No service found", "OK");
}
The header bytes definition:
byte MGMT_OP_READ = 0;
byte MGMT_OP_READ_RSP = 1;
byte MGMT_OP_WRITE = 2;
byte MGMT_OP_WRITE_RSP = 3;
// Groups
byte MGMT_GROUP_ID_OS = 0;
byte MGMT_GROUP_ID_IMAGE = 1;
byte MGMT_GROUP_ID_STAT = 2;
byte MGMT_GROUP_ID_CONFIG = 3;
byte MGMT_GROUP_ID_LOG = 4;
byte MGMT_GROUP_ID_CRASH = 5;
byte MGMT_GROUP_ID_SPLIT = 6;
byte MGMT_GROUP_ID_RUN = 7;
byte MGMT_GROUP_ID_FS = 8;
byte MGMT_GROUP_ID_SHELL = 9;
// OS group
byte OS_MGMT_ID_ECHO = 0;
byte OS_MGMT_ID_CONS_ECHO_CTRL = 1;
byte OS_MGMT_ID_TASKSTAT = 2;
byte OS_MGMT_ID_MPSTAT = 3;
byte OS_MGMT_ID_DATETIME_STR = 4;
byte OS_MGMT_ID_RESET = 5;
// Image group
byte IMG_MGMT_ID_STATE = 0;
byte IMG_MGMT_ID_UPLOAD = 1;
byte IMG_MGMT_ID_FILE = 2;
byte IMG_MGMT_ID_CORELIST = 3;
byte IMG_MGMT_ID_CORELOAD = 4;
byte IMG_MGMT_ID_ERASE = 5;
private int _seq = 0;
and the uploadnext method:
private async Task _uploadNext()
{
if (_uploadOffset >= SelectedFirmwareFile.Length)
{
uploadIsInProgress = false;
HandleUploadFinished();
return;
}
if (uploadIsInProgress == false)
return;
const int nmpOverhead = 8;
var message = new ImageData();
if (_uploadOffset == 0)
{
message.len = Convert.ToInt32(SelectedFirmwareFile.Length);
using (var sha = SHA256.Create())
{
message.sha = sha.ComputeHash(await File.ReadAllBytesAsync(SelectedFirmwareFile.FullName));
}
}
//the encode function that i am trying to implement
var length = _mtu - Encode(message).Length - nmpOverhead;
message.data = new byte[SelectedFirmwareFile.Length - _uploadOffset > length ? length : SelectedFirmwareFile.Length - _uploadOffset];
Array.Copy(await File.ReadAllBytesAsync(SelectedFirmwareFile.FullName), _uploadOffset, message.data, 0, message.data.Length);
_uploadOffset += message.data.Length;
await SendMessage(MGMT_OP_WRITE, MGMT_GROUP_ID_IMAGE, IMG_MGMT_ID_UPLOAD, message);
}
And then i need to send the packet and encode it using CBOR. There is my code for the SendMessage method (i am really sure that it doesn't work)
async Task SendMessage(byte op, byte group, byte id, ImageData data)
{
var cborMessage = CBORObject.FromObject(new { op, group, id, seq = _seq++, data });
await sendCharacteristic.WriteAsync(cborMessage.EncodeToBytes());
}
BTW the characteristics use the SMP id.
I'll appreciate every comment or an idea. Thank you and have a nice day

C++/C# Data Marshalling not working as expected

On the C++ side, I have this:
double* s;
bool GetLeftOutputData(double ** a, int * i)
{
s = new double[4]{ 25,24.0,33.0,57.0 };
*a = s;
*i = 4;
return true;
}
And on the C# side, I have:
[DllImport("MyDLL")]
private static extern bool GetLeftOutputData(out IntPtr ptrResultVerts, out int resultVertLength);
void TestLeftOutputData()
{
IntPtr ptrNativeData;
int itemsLength;
bool success = GetLeftOutputData(out ptrNativeData, out itemsLength);
if (!success)
{
Debug.Log("Faild to get left out data");
return;
}
double[] SArray = new double[itemsLength]; // Where the final data will be stored.
Debug.Log("Length: " + itemsLength);
IntPtr p = ptrNativeData;
for (int i = 0; i < itemsLength; i++)
{
Marshal.PtrToStructure(p, SArray[i]);
p = new IntPtr(p.ToInt64() + Marshal.SizeOf(typeof(double)));
}
}
Code gives no error, but for some reason, double[] array is always filled with 0, i.e. no data is being copied. Where is my mistake?

Unreliable Marshal when Converting Int to String Depending on Framework

I am using the following line to convert my WTS_PROCESS_INFO object's ProcessName property to a string:
string name = Marshal.PtrToStringUni(processInfos[I].processName)
This seems to be quite reliable, and all the process names are successfully converted.
However, if I make this same call after passing WTS_PROCESS_INFO to another class and method, each attempt at converting to a string results in "" apart from the first attempt.
This only is only happening when using .NET-3.5 but seems to work fine in .NET-4.0
Example:
Working - each name is converted to the correct string before passing the entire list.
public static List<Proc> WTSEnumerateProcesses(string servername)
{
IntPtr pProcessInfo = IntPtr.Zero;
int processCount = 0;
var hServer = OpenServer(servername);
if (!Native.WTSEnumerateProcesses(hServer, 0, 1, ref pProcessInfo, ref processCount))
return null;
IntPtr pMemory = pProcessInfo;
WTS_PROCESS_INFO[] processInfos = new WTS_PROCESS_INFO[processCount];
for (int i = 0; i < processCount; i++)
{
processInfos[i] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
pProcessInfo = (IntPtr)((int)pProcessInfo + Marshal.SizeOf(processInfos[i]));
}
List<Proc> asd = new List<Proc>();
foreach (var item in processInfos)
{
if (item.SessionID == 5)
{
string procname = Marshal.PtrToStringUni(item.ProcessName);
var proc = new Proc(servername, 5, item.SessionID, procname);
asd.Add(proc);
}
}
Native.WTSFreeMemory(pMemory);
return asd;
}
Not working - the conversions which take place after passing the WTS_PROCESS_INFOs out result in empty strings (apart from the first one).
public static WTS_PROCESS_INFO[] WTSEnumerateProcesses(string servername)
{
IntPtr pProcessInfo = IntPtr.Zero;
int processCount = 0;
var hServer = OpenServer(servername);
if (!Native.WTSEnumerateProcesses(hServer, 0, 1, ref pProcessInfo, ref processCount))
return null;
IntPtr pMemory = pProcessInfo;
WTS_PROCESS_INFO[] processInfos = new WTS_PROCESS_INFO[processCount];
for (int i = 0; i < processCount; i++)
{
processInfos[i] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
pProcessInfo = (IntPtr)((int)pProcessInfo + Marshal.SizeOf(processInfos[i]));
}
Native.WTSFreeMemory(pMemory);
return processInfos;
}
Can anyone explain why this is happening?
Because you are calling Native.WTSFreeMemory(pMemory); that is freeing the memory associated with the strings. This call is freeing both the pMemory that is an array of WTS_PROCESS_INFO AND the memory pointed from the various pProcessName. So the solution is to copy somewhere those strings BEFORE calling Native.WTSFreeMemory(pMemory);

Received buffer of tcpclient contains not what expected

I have a server side app written in C
struct recv_packet
{
int magic;
int code;
int length;
char *body;
};
char send_buff[1024+1] = "";
ZeroMemory(&send_buff, 1024);
memset(send_buff, 'A', 1024);
//send_buff[1024] = '\0';
recv_packet rcv_pkt = { 0 };
rcv_pkt.magic = MAGIC;
rcv_pkt.code = 0;
rcv_pkt.length = strlen(send_buff);
rcv_pkt.body = send_buff;
int size = sizeof(rcv_pkt.magic) + sizeof(rcv_pkt.code) + sizeof(rcv_pkt.length) + 1024+1;
if (send(ClientSocket, (char *)&rcv_pkt, size, 0) == SOCKET_ERROR)
{
printf("Error %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
On the other side i grab this packet like this:
public struct recv_packet
{
public int magic;
public int code;
public int length;
public byte[] body;
};
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int port = 4000;
TcpClient client = new TcpClient("127.0.0.1", 4000);
NetworkStream nws = client.GetStream();
BinaryWriter bw = new BinaryWriter(nws);
BinaryReader br = new BinaryReader(nws);
byte[] buff = new byte[512];
send_packet pkt = new send_packet();
pkt.magic = magic;
pkt.cmd = (int)command.MOVE_MOUSE;
while (true)
{
bw.Write(pkt.magic);
bw.Write(pkt.cmd);
//br.Read(buff, 0, 512);
recv_packet rcv_pkt = new recv_packet();
rcv_pkt.magic = br.ReadInt32();
rcv_pkt.code = br.ReadInt32();
rcv_pkt.length = br.ReadInt32();
rcv_pkt.body = br.ReadBytes(rcv_pkt.length);
//string str = rcv_pkt.length.ToString();
string str = System.Text.Encoding.Default.GetString(rcv_pkt.body);
MessageBox.Show(str);
}
}
So it suppose that body will have only '65', but instead I've got some trash in it.
Why could this happen? Thank you for your time.
As I understood there are few ways of resolving this problem - one of them is to redecrlare struct a little bit and then creare a buffer, where all structure elements will be fitted one-by-one. So the solution looks like this:
char send_buff[1024+1] = "";
ZeroMemory(&send_buff, 1025);
memset(send_buff, 'A', 1024);
recv_packet *rcv_pkt = (recv_packet *)malloc(sizeof(recv_packet)+1024+1);
//recv_packet rcv_pkt = { 0 };
rcv_pkt->magic = MAGIC;
rcv_pkt->code = 0;
rcv_pkt->length = strlen(send_buff);
memcpy(rcv_pkt->body, send_buff, 1025);
int size = sizeof(rcv_pkt->magic) + sizeof(rcv_pkt->code) + sizeof(rcv_pkt->length) + 1024 + 1;
//printf("%d", size);
//getchar();
//return 0;
//if (send(ClientSocket, rcv_pkt.body, rcv_pkt.length, 0) == SOCKET_ERROR)
if (send(ClientSocket, (char *)rcv_pkt, size, 0) == SOCKET_ERROR)

SymFromAddr using C#

I was trying to see how could I use SymFromAddr from C#. Here is what I have got.
The problem is, DbgHelp.SymFromAddr(processHandle, (ulong)threadAddress, ref displacement, ref symbolInfo) returns error 87. What am I doing wrong?
*Made a slight mod. The SizeOfStruct has now been populated. But no fruit.
static void GetThreadList(int processId, IntPtr processHandle)
{
Console.WriteLine(string.Format("Process Id: {0:X4}", processId));
var threadCollection = Process.GetProcessById(processId).Threads.OfType<ProcessThread>();
foreach (ProcessThread processThread in threadCollection)
{
ulong dwAddress = (ulong)ThreadStartAddress(processThread.Id, processHandle);
Console.WriteLine(" Thread Id: {0:X4}, Start Address: {1:X16}",
processThread.Id, dwAddress);
}
}
static IntPtr ThreadStartAddress(int threadId, IntPtr processHandle)
{
var threadHandle = DbgHelp.OpenThread(DbgHelp.ThreadAccess.QueryInformation, false, threadId);
if (threadHandle == IntPtr.Zero)
throw new Win32Exception();
IntPtr threadAddress = IntPtr.Zero;
var buf = Marshal.AllocHGlobal(IntPtr.Size);
try
{
var result = DbgHelp.NtQueryInformationThread(threadHandle,
DbgHelp.ThreadInfoClass.ThreadQuerySetWin32StartAddress,
buf, IntPtr.Size, IntPtr.Zero);
if (0 != result)
throw new Win32Exception(string.Format("NtQueryInformationThread failed; NTSTATUS = {0:X8}", result));
threadAddress = Marshal.ReadIntPtr(buf);
unsafe
{
ulong displacement = 0;
uint symsetOptStatus = DbgHelp.SymSetOptions(DbgHelp.SymOpt.UNDNAME | DbgHelp.SymOpt.DEFERRED_LOADS); // Returns 6.
if (!DbgHelp.SymInitialize(threadHandle, null, true))
{
// SymInitialize failed with error C000000B.
Console.WriteLine("SymInitialize returned error : {0:X16}.\n", Marshal.GetLastWin32Error());
}
DbgHelp.SYMBOL_INFO symbolInfo = new DbgHelp.SYMBOL_INFO();
//symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(symbolInfo);
//symbolInfo.MaxNameLen = DbgHelp.MAX_SYM_NAME;
//const int maxNameLen = 512;
//int bufferSize = Marshal.SizeOf(typeof(DbgHelp.SYMBOL_INFO)) + (DbgHelp.MAX_SYM_NAME * 2);
//var buffer = Marshal.AllocHGlobal(bufferSize);
//DbgHelp.SYMBOL_INFO symbolInfo = (DbgHelp.SYMBOL_INFO)buffer;
symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(typeof(DbgHelp.SYMBOL_INFO));
symbolInfo.MaxNameLen = DbgHelp.MAX_SYM_NAME -1;
if (DbgHelp.SymFromAddr(processHandle, (ulong)threadAddress, ref displacement, ref symbolInfo))
{
// SymFromAddr returned success.
return threadAddress;
}
else
{
// SymFromAddr failed with error 87.
Console.WriteLine("SymFromAddr returned error : {0}.\n", Marshal.GetLastWin32Error());
return threadAddress;
}
}
}
finally
{
DbgHelp.CloseHandle(threadHandle);
Marshal.FreeHGlobal(buf);
}
}
Try:
const int maxNameLen = 512;
int bufferSize = sizeof(SYMBOL_INFO) + maxNameLen*2;
buffer = (byte*)Marshal.AllocHGlobal(bufferSize);
symbolInfo = (SYMBOL_INFO*)buffer;
symbolInfo->SizeOfStruct = (uint)sizeof(SYMBOL_INFO);
symbolInfo->MaxNameLen = maxNameLen - 1;
The only way I see is writing an unmanaged c++ wrapper for reading symbol info.

Categories

Resources