I'm working with vanetza to make cpms messages, I have built the .c and .cpp files from the asn1, so the structures of the message have the structure of the asn1. I have a structure (PerceptionDataContainer) which is a SEQUENCE OF PerceptionData, the Sequence of is a special type of list. Each PerceptionData have a perceivedobjects structure which is a SEQUENCE OF PerceivedObject struct, I have made this code to add information to these struct;
vanetza::asn1::Cpm cpm;
auto object = asn1::allocate<PerceivedObject_t>(); //this fill the struct PerceivedObject with basic info
auto perception = asn1::allocate<PerceptionData_t>();
PerceivedObject *arrayobjeto[2];
cpm->cpm.cpmParameters.perceptionData = asn1::allocate<CpmParameters::CpmParameters__perceptionData>();
cpm->header.protocolVersion=2;
cpm->header.messageID=ItsPduHeader__messageID_cpm;
cpm->header.stationID=1;
cpm->cpm.cpmParameters.managementContainer.stationType=2;
for(int i=0; i<2;i++) {
arrayobjeto[i]=asn1::allocate<PerceivedObject>();
arrayobjeto[i]->objectID= i+1;
arrayobjeto[i]->timeOfMeasurement = TimeOfMeasurement_oneMilliSecond;
arrayobjeto[i]->xDistance.value = DistanceValue_oneMeter;
arrayobjeto[i]->xDistance.confidence = DistanceConfidence_oneMeter;
arrayobjeto[i]->yDistance.value = DistanceValue_oneMeter;
arrayobjeto[i]->yDistance.confidence = DistanceConfidence_oneMeter;
arrayobjeto[i]->xSpeed.value = SpeedValueExtended_oneCentimeterPerSec;
arrayobjeto[i]->xSpeed.confidence = SpeedConfidence_equalOrWithinOneMeterPerSec;
arrayobjeto[i]->ySpeed.value = SpeedValueExtended_oneCentimeterPerSec;
arrayobjeto[i]->ySpeed.confidence = SpeedConfidence_equalOrWithinOneMeterPerSec;
}
perception->containerId=1;
perception->containerData.present=PerceptionData__containerData_PR_PerceivedObjectContainer;
perception->containerData.choice.PerceivedObjectContainer.numberOfPerceivedObjects=1;
for(int i=0; i<2;i++) {
EXPECT_EQ(0, ASN_SEQUENCE_ADD(&perception->containerData.choice.PerceivedObjectContainer.perceivedObjects,arrayobjeto[i]));
}
EXPECT_EQ(0, ASN_SEQUENCE_ADD(&cpm->cpm.cpmParameters.perceptionData->list, perception));
EXPECT_EQ(1, cpm->cpm.cpmParameters.perceptionData->list.count);
EXPECT_EQ(2, cpm->cpm.cpmParameters.perceptionData->list.array[0]->containerData.choice.PerceivedObjectContainer.perceivedObjects.list.count);
EXPECT_EQ(perception, cpm->cpm.cpmParameters.perceptionData->list.array[0]);
EXPECT_EQ(arrayobjeto[0], cpm->cpm.cpmParameters.perceptionData->list.array[0]->containerData.choice.PerceivedObjectContainer.perceivedObjects.list.array[0]);
EXPECT_TRUE(cpm.validate());
EXPECT_FALSE(cpm.encode().empty());
ByteBuffer buffer = cpm.encode();
std::cout << "tamaƱo: " << buffer.size() << "\n";
for (const auto byte:buffer){
printf("%02x ",byte);
}
ASSERT_TRUE(cpm.decode(buffer));
std::cout << cpm.size();
The definitions of the structs are these:
typedef struct CpmParameters {
CpmManagementContainer_t managementContainer;
struct OriginatingStationData *stationDataContainer; /* OPTIONAL */
struct CpmParameters__perceptionData {
A_SEQUENCE_OF(struct PerceptionData) list;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} *perceptionData;
....
typedef struct PerceptionData {
CpmContainerId_t containerId;
struct PerceptionData__containerData {
PerceptionData__containerData_PR present;
union PerceptionData__containerData_u {
SensorInformationContainer_t SensorInformationContainer;
PerceivedObjectContainer_t PerceivedObjectContainer;
FreeSpaceAddendumContainer_t FreeSpaceAddendumContainer;
} choice;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} containerData;
....
typedef struct PerceivedObjectContainer {
NumberOfPerceivedObjects_t numberOfPerceivedObjects; /* DEFAULT 0 */
struct PerceivedObjectContainer__perceivedObjects {
A_SEQUENCE_OF(struct PerceivedObject) list;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} perceivedObjects;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} PerceivedObjectContainer_t;
I have reached a good encode but it can not be decode correctly and it seems I have loaded the data into the structs not perfectly, anyone knows how to do it correctly?
I am trying to update table
CREATE TABLE some_table
(
id integer NOT NULL,
client_fid bigint NOT NULL,
index bytea[],
update_time timestamp without time zone
)
WITH (
OIDS = FALSE
using modified code snipped from here How to insert text array in PostgreSQL table in binary format using libpq?
#define BYTEAARRAYOID 1001
#define BYTEAOID 17
Here is a pgvals_t structure definition
struct pgvals_t
{
/* number of array dimensions */
int32_t ndims;
/* flag describing if array has NULL values */
int32_t hasNull;
/* Oid of data stored in array. In our case is 25 for TEXT */
Oid oidType;
/* Number of elements in array */
int32_t totalLen;
/* Not sure for this one.
I think it describes dimensions of elements in case of arrays storing arrays */
int32_t subDims;
/* Here our data begins */
} __attribute__ ((__packed__));
I've removed dataBegins pointer from struct as it affects data layout in memo
std::size_t nElems = _data.size();
uint32_t valsDataSize = sizeof(prx::pgvals_t) + sizeof(int32_t) * nElems +
sizeof(uint8_t)*nElems;
void *pData = malloc(valsDataSize);
prx::pgvals_t* pvals = (prx::pgvals_t*)pData;
/* our array has one dimension */
pvals->ndims = ntohl(1);
/* our array has no NULL elements */
pvals->hasNull = ntohl(0);
/* type of our elements is bytea */
pvals->oidType = ntohl(BYTEAOID);
/* our array has nElems elements */
pvals->totalLen = ntohl(nElems);
pvals->subDims = ntohl(1);
int32_t elemLen = ntohl(sizeof(uint8_t));
std::size_t offset = sizeof(elemLen) + sizeof(_data[0]);
char * ptr = (char*)(pvals + sizeof(prx::pgvals_t));
for(auto byte : _data){
memcpy(ptr, &elemLen, sizeof(elemLen));
memcpy(ptr + sizeof(elemLen), &byte, sizeof(byte));
ptr += offset;
}
Oid paramTypes[] = { BYTEAARRAYOID };
char * paramValues[] = {(char* )pData};
int paramLengths[] = { (int)valsDataSize };
int paramFormats[] = {1};
PGresult *res = PQexecParams(m_conn, _statement.c_str(),
1,
paramTypes,
paramValues,
paramLengths,
paramFormats,
1
);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
std::string errMsg = PQresultErrorMessage(res);
PQclear(res);
throw std::runtime_error(errMsg);
}
free(pData);
The binary data is contained in std::vector variable and am using the following query in a _statement variable of type std::string
INSERT INTO some_table \
(id, client_id, \"index\", update_time) \
VALUES \
(1, 2, $1, NOW())
Now after call to PQExecParams I am get an exception with message
"incorrect binary data format in bind parameter 1"
What can be the problem here?
If you want to pass a bytea[] in binary format, you have to use the binary array format as read by array_recv and written by array_send.
You cannot just pass a C array.
Is it possible for an attribute of a 'struct' to host multiple structures?
Example, I need the attribute LPWFSPINFDK lppFDKs; which is part of the struct _wfs_pin_func_key_detail, receive multiple structs _wfs_pin_fdk.
I'm trying this way, compiles, but the final program does not recognize:
WFSPINFUNCKEYDETAIL PinFunKeyDetail;
WFSPINFDK ObjPinKey;
LPWFSPINFDK PinKey;
PinKey = &ObjPinKey;
PinKey->ulFDK = WFS_PIN_FK_FDK01;
PinKey->usXPosition = 5;
PinKey->usYPosition = 5;
PinFunKeyDetail.lppFDKs = &PinKey;
STRUCT: _wfs_pin_fdk
typedef struct _wfs_pin_fdk
{
ULONG ulFDK;
USHORT usXPosition;
USHORT usYPosition;
} WFSPINFDK, * LPWFSPINFDK;
STRUCT: _wfs_pin_func_key_detail
typedef struct _wfs_pin_func_key_detail
{
ULONG ulFuncMask;
USHORT usNumberFDKs;
LPWFSPINFDK * lppFDKs; //I want to receive the structs here
} WFSPINFUNCKEYDETAIL, * LPWFSPINFUNCKEYDETAIL;
In C, you sometimes see something like:
struct foobar
{
int size;
int data[1];
};
where the data member doesn't really have just one element; rather it's meant to be variable length.
If you do something like that in D, is it going to let you, for example, read myfoobar.data[4]?
I know D has variable length arrays, e.g. int[] myvarlenintarray;, but what if you're trying to interface with some code that already puts out a data structure in memory like the one above, and possibly much more complex than that? Let's say it's in the first portion of int[3000] buffer;. Is there an easy way to cast it to a usable struct without moving it in memory? If not, is there an easy way to get the data into a similar struct without having to manually parse out each member of the struct?
edit:
I think I need to give a practical example so you see where I'm coming from.
import std.c.windows.windows;
import std.utf;
import std.stdio;
public struct REPARSE_DATA_BUFFER
{
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union
{
struct SymbolicLinkReparseBuffer
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR[1] PathBuffer;
}
SymbolicLinkReparseBuffer mySymbolicLinkReparseBuffer;
struct MountPointReparseBuffer
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR[1] PathBuffer;
}
MountPointReparseBuffer myMountPointReparseBuffer;
struct GenericReparseBuffer
{
UCHAR[1] DataBuffer;
}
GenericReparseBuffer myGenericReparseBuffer;
}
}
alias REPARSE_DATA_BUFFER* PREPARSE_DATA_BUFFER;
enum MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16*1024;
// Values for 'ReparseTag' member of REPARSE_DATA_BUFFER:
enum : DWORD {
IO_REPARSE_TAG_SYMLINK = 0xA000000C,
IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 // which also defines a Junction Point
}
enum DWORD FSCTL_GET_REPARSE_POINT = 0x000900a8;
enum FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000;
public extern(Windows) BOOL function(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPVOID, OVERLAPPED*) DeviceIoControl;
void main()
{
DeviceIoControl = cast(BOOL function(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPVOID, OVERLAPPED*))GetProcAddress(LoadLibraryA("kernel32.dll"), "DeviceIoControl");
auto RPHandle = CreateFileW((r"J:\Documents and Settings").toUTF16z(), 0, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT + FILE_FLAG_BACKUP_SEMANTICS, null);
if (RPHandle == INVALID_HANDLE_VALUE)
{
printf("CreateFileW failed with error code %d.", GetLastError());
return;
}
BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE] reparsebuffer;
uint reparsedatasize;
auto getreparsepointresult = DeviceIoControl(RPHandle, FSCTL_GET_REPARSE_POINT, null, 0, cast(void*) reparsebuffer.ptr, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &reparsedatasize, null);
if (getreparsepointresult == 0)
{
printf("DeviceIoControl with FSCTL_GET_REPARSE_POINT failed with error code %d.", GetLastError());
return;
}
// Now what?
// If I do this:
auto ReparseDataPtr = cast(REPARSE_DATA_BUFFER*) reparsebuffer.ptr;
printf("%d == %d\n", reparsebuffer.ptr, ReparseDataPtr); // Alright, data hasn't been copied.
// But what good is a pointer? Can I use a pointer to a struct to access one of its members apart from dereferencing?
printf("%d == %d\n", &reparsebuffer[0], &(*ReparseDataPtr)); // Here, I dereference ReparseDataPtr, but nothing moves.
printf("%d == %d\n", &reparsebuffer[0], &((*ReparseDataPtr).ReparseTag)); // Same here, so I can access members in a roundabout way.
printf("%d == %d\n", &reparsebuffer[0], &(ReparseDataPtr.ReparseTag)); // And thanks to Jim's comment, here's a less roundabout way.
auto ReparseData = *ReparseDataPtr; // But if I assign a name to the dereferenced ReparseDataPtr,
printf("%d != %d\n", &reparsebuffer[0], &(ReparseData.ReparseTag)); // the data is copied to a new location, leaving most of PathBuffer behind.
REPARSE_DATA_BUFFER ReparseDataFn() {return *ReparseDataPtr;} // Similarly, this way
printf("%d != %d\n", &reparsebuffer[0], &(ReparseDataFn().ReparseTag)); // copies stuff to a new location.
}
Firstly, I don't understand why it's different for the case in which I don't give *ReparseDataPtr a name.
Secondly, is there no way to have a symbol whose type is REPARSE_DATA_BUFFER and whose data is located at reparsebuffer.ptr?
Have you tried doing the exact same thing in D as in C?
struct foobar { int size; int data[1]; };
It works... just use data.ptr instead of data to access the elements, because otherwise it will perform bounds checking with a length of 1.
You could access it via a helper method:
struct foobar
{
public:
int[] Data() { return data.ptr[0..size]; }
private:
int size;
int data[1];
}
You might also want to put int a static foreach over the members of foobar that uses static assert to make sure that the offset of each is less than the offset of data.
I am developing a driver with Filter. So when I write the SendNetBufferListsComplete function in filter.cpp I got a crash (bluescreen). WinDbug pointed to some buffer allocation. The code is here:
Edited:
sendNetBufferListsComplete(
IN PNET_BUFFER_LIST NetBufferLists,
IN ULONG SendCompleteFlags) {
PNET_BUFFER_LIST pNetBufferList = NetBufferLists;
PNET_BUFFER_LIST pNextNetBufferList = NULL;
while (pNetBufferList)
{
pNextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(pNetBufferList);
NET_BUFFER_LIST_NEXT_NBL(pNetBufferList) = NULL;
PNET_BUFFER_LIST pParentNetBufferList = pNetBufferList->ParentNetBufferList;
if (pParentNetBufferList != NULL)
{
NDIS_STATUS status = NET_BUFFER_LIST_STATUS(pNetBufferList);
NdisFreeNetBufferList(pNetBufferList);
if (NdisInterlockedDecrement(&pParentNetBufferList->ChildRefCount) == 0) {
NET_BUFFER_LIST_STATUS(pParentNetBufferList) = status;
NdisFSendNetBufferListsComplete(m_hFilter, pParentNetBufferList, SendCompleteFlags);
}
}
else
{
if(pNetBufferList != NULL)
{
**---windbug pointed here---****
PVOID pBuffer = *(PVOID*) NET_BUFFER_LIST_CONTEXT_DATA_START(pNetBufferList);
PMDL pMdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(pNetBufferList));
if(pMdl)
NdisFreeMdl(pMdl);
if(pBuffer)
delete[] (UCHAR*) pBuffer;
NdisFreeNetBufferList(pNetBufferList);
}
}
NdisInterlockedDecrement(&m_nSendNetBufferListCount);
pNetBufferList = pNextNetBufferList;
}
What is the actual problem? Is it overflow? Or NULL check problems?
In ndish.h
#define NET_BUFFER_LIST_CONTEXT_DATA_START(_NBL) ((PUCHAR)(((_NBL)->Context)+1)+(_NBL)->Context->Offset)
like this . and in Wdm.h
//
// I/O system definitions.
//
// Define a Memory Descriptor List (MDL)
//
// An MDL describes pages in a virtual buffer in terms of physical pages. The
// pages associated with the buffer are described in an array that is allocated
// just after the MDL header structure itself.
//
typedef
_Struct_size_bytes_(_Inexpressible_(sizeof(struct _MDL) + // 747934
(ByteOffset + ByteCount + PAGE_SIZE-1) / PAGE_SIZE * sizeof(PFN_NUMBER)))
struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa; /* see creators for field size annotations. */
PVOID StartVa; /* see creators for validity; could be address 0. */
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;