Reputation: 89
I have am trying to receive information from a EXE that was written in Delphi. The EXE passes me a pointer to one of its data structures:
Type
RecordType = Record
St: WideString;
Next: Pointer;
End;
Var
DataRec: ^RecordType;
So in Visual Studio MFC I have declared a data type that should be similar:
struct RecordRec
{
BSTR St;
void *Next;
};
RecordRec *DataRec;
The Delphi Help says that a WideString is compatible with a BSTR, however, this does not work. When I look at my St in Debug Mode it says
"0x0000000000000000 <Bad Ptr> wchar_t *"
I don't know how to declare the equivalent of a WideString in Visual Studio MFC.
If it was a ShortString I would declare:
struct RecordRec
{
BYTE StLen;
char St[255];
void *Next;
};
but this does not work for a WideString and I really don't think I should declare a variable with ~2^30 (1,073,741,824) characters in it.
What am I missing? I really hope that someone can help.
Upvotes: 1
Views: 275
Reputation: 596307
A Delphi WideString
is indeed a wrapper for a BSTR
, however, that does not mean a raw BSTR
pointer can be passed as-is from one process to another. Its data has to be marshalled when passing across process boundaries. COM normally handles that automatically, but passing a raw BSTR
pointer manually does not.
So, if you can't change the Delphi app to provide an IPC-safe data block for the character data (similar to the ShortString
workaround), then the receiving app will have to marshal the BSTR
data manually. It can use ReadProcessMemory()
for that:
BSTR
's length from within the Delphi app's address space (a BSTR
's character data is prefixed with a 4-byte integer specifying its length in wchar_t
elements)wchar_t[]
array of the specified length within its own address spaceFor example (error handling omitted for brevity):
RecordRec *DataRec = ...;
std::wstring DataSt;
if (DataRec->St)
{
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, TheDelphiAppProcessID);
int len = 0;
SIZE_T numRead = 0;
ReadProcessMemory(hProcess, LPBYTE(DataRec->St)-4, &len, 4, &numRead);
if (len > 0)
{
DataSt.resize(len);
ReadProcessMemory(hProcess, DataRec->St, &DataSt[0], len*2, &numRead);
}
CloseHandle(hProcess);
}
// use DataSt as needed...
Upvotes: 2
Reputation: 80187
So you have two different processes - Delphi one (DP) and VS one (VSP). Each has own address space, and valid pointer in the DP is not valid in VSP. That is why <Bad Ptr>
(exception?) appears.
BTW, I've noticed that address in VSP is 64-bit. Is Delphi process 64-bit too?
You need some kind of interprocess communication (IPC) through shared memory.
Because you have control over the Service and the MFC program, you could save received data to named memory-mapped file in DLL, then MFC process will open it and read data.
Upvotes: 1
Reputation: 163287
You're not missing anything. Delphi's WideString
is indeed equivalent to BSTR
. The value you see in the debugger is a null pointer. Delphi would treat that as an empty string; you should probably treat it the same way.
Upvotes: 2