This is my PER_IO_CONTEXT structure (i stored them in singly linked list):
typedef struct _PER_IO_CONTEXT
{
SLIST_ENTRY ItemEntry;
WSAOVERLAPPED Overlapped;
WSABUF wsabuf;
/* some other data*/
} PER_IO_CONTEXT, *PPER_IO_CONTEXT;
and below is WSAsend , that use the list for getting WSAOVERLAPPED structure:
...
PSLIST_HEADER pListHead;
...
PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(pListHead);
PPER_IO_CONTEXT ovl = (PPER_IO_CONTEXT)pListEntry;
WSASend(pTmp1->Socket,..., &(ovl->Overlapped), NULL);
and the last part when GQCS gets notification:
LPWSAOVERLAPPED lpOverlapped = NULL;
PPER_IO_CONTEXT lpIOContext = NULL;
....
GetQueuedCompletionStatus(..... (LPOVERLAPPED *)&lpOverlapped, INFINITE);
lpIOContext = (PPER_IO_CONTEXT)lpOverlapped;
lpIOContext->wsabuf // this fail
As you can see following cast lpIOContext =(PPER_IO_CONTEXT)lpOverlapped doesn't work because WSAsend was provided with wsaoverlapped - the second member of PER_IO_CONTEXT structure, so dereferences such as lpIOContext-> can't be used in this case.
There is a way to deal with this situation?
To get the address of the corresponding PER_IO_CONTEXT struct you can use this:
lpIOContext = CONTAINING_RECORD(lpOverlapped, PER_IO_CONTEXT, Overlapped);
CONTAINING_RECORD is a macro defined in VC\crt\src\collections.h in such a way:
#define CONTAINING_RECORD(address, type, field) \
((type *)((char *)(address) - (ULONG_PTR)(&((type *)0)->field)))
More information: http://msdn.microsoft.com/en-us/library/windows/hardware/ff542043%28v=vs.85%29.aspx
I'm not sure whether there's a supported mechanism to convert a pointer to a member of a struct to a pointer to the struct. You could cast everything to BYTE * and do the arithmetic, which would work in practice, but depending on your needs it might be cleaner to reorganize to avoid the necessity:
typedef struct _PER_IO_CONTEXT
{
WSAOVERLAPPED Overlapped;
WSABUF wsabuf;
/* some other data*/
} PER_IO_CONTEXT, *PPER_IO_CONTEXT;
typedef struct _PER_IO_CONTEXT_LIST_ITEM
{
SLIST_ENTRY ItemEntry;
PER_IO_CONTEXT Item;
} PER_IO_CONTEXT_LIST_ITEM, *PPER_IO_CONTEXT_LIST_ITEM;
Related
The ENet library has packets that can be send, and includes a callback function once it has finished sending that specific packet.
http://enet.bespin.org/structENetPacket.html#ad602d6b6b35ef88b2b2e080fa5c9dc3d
typedef struct _ENetPacket
{
size_t referenceCount; /**< internal use only */
enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */
enet_uint8 * data; /**< allocated data for packet */
size_t dataLength; /**< length of data */
ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */
void * userData; /**< application private data, may be freely modified */
} ENetPacket;
The callback itself:
typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
Now I want to create a class that holds the host used to send those packets, and also to keep track how many packets were successfully sent.
template<typename T>
class Sender {
public:
explicit Sender() { }
void send(T* data, int32_t length)
{
ENetPacket* packet = enet_packet_create(data, length, ENET_PACKET_FLAG_RELIABLE);
packet->freeCallback = callbackPacket;
enet_host_broadcast(m_server, 0, packet);
}
void callbackPacket(ENetPacket* packet)
{
--m_counter_packets_active;
}
};
This does not compile: Error C3867 Sender<int32_t>::callbackPacket': non-standard syntax; use '&' to create a pointer to member
When I try
packet->freeCallback = &this->callbackPacket;
I get Error C2440 '=': cannot convert from 'void (Sender<int32_t>::* )(ENetPacket *)' to 'ENetPacketFreeCallback'
I just don't understand what the proper code would be for the packet calling the Sender object's method when the packet is done with.
Okay, this is pretty common. First, you can't call a non-static member method this way, not directly. Pain in the ass.
But that callback structure has a userData field. And that's what we're going to use.
void send(T* data, int32_t length) {
ENetPacket* packet = enet_packet_create(data, length, ENET_PACKET_FLAG_RELIABLE);
packet->freeCallback = &Sender::myStaticMethod;
packet->userData = this; // This is part of the magic
enet_host_broadcast(m_server, 0, packet);
}
static void myStaticMethod(ENetPacket * packet) {
Sender * sender = static_cast<Sender *>(packet->userData);
sender-> callbackPacket(packet);
}
In other words -- store this as your user data. Use a static method for the callback, and have him turn it around to call your real callback.
I have this structure:
typedef struct edagroup
{
UINT16 nodes; /* # slots - may not all be in use */
EHANDLE *eh; /* ptr to array of node handles */
} *GNUM;
And this:
typedef struct ehandle
{
UINT32 is_tag256; /* Is the remote node 256 character? */
UINT32 is_tag30 ; /* Is the remote node 30 character? */
}*EHANDLE;
And this method:
GNUM sample_call(UINT16 n_nodes, INT16 detect_changes);
We call to this method that returns a GNUM struture and I want to access to is_tag256 property.
Sample:
GNUM FixGroupInit = sample_call(1, 0);
EHANDLE *eh = FixGroupInit->eh;
...
Somebody can help me?
There is not enough information to tell us where the array comes in (and there is an ambiguity in the code comments -- the author of that API ought to be beaten with a stick) but you can try this:
(**(FixGroupInit->eh)).is_tag256
Winapi's ReadDirectoryChanges uses FILE_NOTIFY_INFORMATION to present it's results. The struct looks like this:
typedef struct _FILE_NOTIFY_INFORMATION {
DWORD NextEntryOffset;
DWORD Action;
DWORD FileNameLength;
WCHAR FileName[1];
} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
If I get this struct filled by winapi, how do I correctly delete the FileName WCHAR*? Do I have to delete it?
None of the examples (not that there are many examples) of the ReadDirectoryChanges mention deleting anything. Microsoft of course does not provide any examples at all.
If you use malloc you need call free after you finish using the object.
For example:
DWORD FileNameLength = 100;
PFILE_NOTIFY_INFORMATION file_notify_info = (PFILE_NOTIFY_INFORMATION)malloc(FIELD_OFFSET(FILE_NOTIFY_INFORMATION, FileName[FileNameLength]));
free(file_notify_info);
Refer to "Why do some structures end with an array of size 1?".
I have 2 data structures both in my injector and dll:
struct SubData_t
{
int SubTest;
};
struct DataHolder_t
{
int Test;
SubData_t SubData;
};
This is how I assign the data structure values:
DataHolder_t *DataHolder = new DataHolder_t();
DataHolder->Test = 123;
DataHolder->SubData.SubTest = 456;
int ResponseCode = Inject(4321, "test.dll", DataHolder);
And this is a custom LoadLibrary function that passes the data to dll export:
int Inject(DWORD ProcessId, char *DLLFile, DataHolder_t *Data)
{
// ...
LoadRemoteLibraryR(hProcess, lpBuffer, dwLength, NULL, 0xd13f5171 /* dllexport EntryPoint hash */, (LPVOID)Data, (DWORD)(sizeof(struct DataHolder_t) + 1));
// ...
}
Then I get the data in the dll export and assign the values from lpUserdata to the data structure:
DLLEXPORT BOOL EntryPoint(LPVOID lpUserdata, DWORD nUserdataLen)
{
DataHolder_t *DataHolder = (struct DataHolder_t *)lpUserdata;
char buffer[100];
sprintf(buffer, "%d | %d", DataHolder->Test, DataHolder->SubData.SubTest);
MessageBox(NULL, buffer, "Test", MB_OK);
return TRUE;
}
However I'm new to lambdas and can't figure out how (if it's even possible) to pass lambda (functions) the same way to the dll export. Or is there any other way to pass functions/logic to the dll export, so that they can be called from the target process that the dll was injected to?
Use type erasure, like std::function, or a reasonable facsimile, and pass the type-erased parameter as a reference, instead of passing by value, for best results.
I've been researching passing a struct as a parameter from a C++ client to a C++ server using COM. I've found many examples but none that really explained it to me like I'm five nor any that really provided a firm understanding of how to do what I want, which is simply pass a C++ struct through a COM interface where both sides are C++. Should be easy, right?
I have established my struct as follows in the IDL file on server-side:
[
uuid(7F0C9A48-3C41-425B-B4E6-8156B61D5355),
version(1.0)
]
typedef struct xxxData
{
int iWidth;
int iHeight;
SafeArray(short) pxxxData;
} xxxData;
// Fix for UUID DECLARATION FOR _uuidof() functionality
// From http://go4answers.webhost4life.com/Example/error-c2787-no-guid-been-associated-158947.aspx
cpp_quote("struct __declspec(uuid(\"{7F0C9A48-3C41-425B-B4E6-8156B61D5355}\")) xxxData;")
Which works, so far as I can tell.
Now my client calls GetImageData which is shown as follows:
[id(16)] HRESULT GetImageData([in,out] VARIANT* pData);
Now my client call is as follows with this function:
VARIANT* pData = new VARIANT;
VariantInit( pData );
xxxData* data = new xxxxData;
HRESULT hr = mpCOMEvents->GetImageData(pData);
data = (FBIS_ImageData*)(pData->pvRecord);
int length = data->iWidth * data->iHeight;
However, length is giving me an incorrect address location. This makes me wonder if my use of pvRecord is incorrect and if I can really typecast it?
Here is my COM server side:
xxxData data;
//SAFEARRAY *psa;
IRecordInfo *pRI;
HRESULT hr;
/* Pass in Structure Information */
data.iHeight = 100;
data.iWidth = 100;
// Used http://vcfaq.mvps.org/com/4.htm as reference
hr = GetRecordInfoFromGuids(LIBID_xxxLib, 1, 0, 0x409, _uuidof(xxxData), &pRI);
VariantInit(pData);
pData->vt = VT_RECORD;
pData->pvRecord = &data;
pData->pRecInfo = pRI;
pRI = NULL;
There's some confusion here.
If you're not aiming to be automation friendly, change your IDL to:
[size_is=iWidth*iHeight] unsigned short* pxxxData;
and don't use SAFEARRAY API on this. For marshalling, you'll have to compile a proxy/stub DLL and register it.
If you're aiming to be automation friendly, change your IDL to:
SAFEARRAY(short) pxxxData;
and do use the SAFEARRAY API on this. For marshalling, you'll have to compile a typelib (optionally, embed it) and register it. This also enables early-binding (e.g. VB6, tlbimp).
This will work for languages/environments that support user-defined types. For the ones that don't (e.g. scripting languages), you'll have to use an oleautomation/dual/IDispatch-based interface instead of a struct (and implement in in the server).
EDIT: Based on the changes you made to your question.
You should declare the pData parameter as out only, GetImageData will populate it, not use it and possibly replace it. It also only requires marshaling on return, not on the call. Here's a suggestion:
[id(16)] HRESULT GetImageData([out] VARIANT* pData);
Your client code has a memory leak, it always creates an xxxData. Here's a suggestion:
// If pData is in-out, this is not safe, use CoTaskMemAlloc(sizeof(VARIANT)) instead.
// The callee may override the buffer by assuming it was CoTaskMemAlloc'ed, thus
// assuming it can CoTaskMemFree the original location and set the pointer to a new
// CoTaskMemAlloc'ed location.
// The callee may be a proxy.
// Assuming it's out only, we can provide any location with enough space for a VARIANT.
VARIANT vData;
VariantInit( &vData );
xxxData* data; // remove memory leak
HRESULT hr = mpCOMEvents->GetImageData(&vData);
// error handling removed for clarity (I hope)
data = (xxxData*)(vData.pvRecord);
int length = data->iWidth * data->iHeight;
// ... use data ...
// Don't forget to clear the variant, or there'll be a memory leak
// It implies:
// vData.pRecInfo->RecordDestroy(vData.pvRecord);
// This should recursively release memory allocated in each field
// and finally release the memory allocated for the struct itself.
// vData.pRecInfo->Release();
VariantClear( &vData );
// don't use data past this point
Your server code is setting pData->pvRecord to point to the stack, which means that it will potentially be overwritten by a caller or some other invoked function. Here's a suggestion:
xxxData* data; // Changed to pointer
IRecordInfo *pRI;
HRESULT hr;
// data.iHeight = 100; // removed
// data.iWidth = 100; // removed
hr = GetRecordInfoFromGuids(LIBID_xxxLib, 1, 0, 0x409, _uuidof(xxxData), &pRI);
// error handling removed for clarity (I hope)
VariantInit(pData);
// This will allocate memory for the struct itself
// For fields that require memory allocation, follow "normal" COM rules,
// such as using CoTaskMemAlloc for buffers, SysAllocString or similar for BSTRs,
// etc.
// For each inner (pointed to) structure, you should call RecordCreate on the
// respective IRecordInfo instance for that type.
data = (xxxData*)pRI->RecordCreate();
data->iHeight = 100; // new
data->iWidth = 100; // new
// If pData is in-out, this will leak, use VariantClear instead.
// Assuming it's out only, use VariantInit as it points to (allocated) garbage.
VariantInit(pData);
pData->vt = VT_RECORD;
pData->pvRecord = data; // data is already a pointer
pData->pRecInfo = pRI;
pRI = NULL;
// This won't (normally) leak, the caller must call VariantClear on the out VARIANT.
// The caller may be a stub.