Assigning a pointer to an array

T

The Hole Pounder

My C skills are rather meager so forgive me if I do not express my
question
clearly enough. Here is a struct that is declared in Windows:

typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

Now I'm going to show my attempt at assigning to "DataBuffer". This code
is
written in Eiffel but the part inside of the square brackets ([]) is C
code
except you will see some "$" symbols which you can ignore:

set_c_generic_reparse_buffer_data_buffer_pointer (a_item, v: POINTER) is
external
"C inline use <Windows.h>"
alias
"[
{
PREPARSE_GUID_DATA_BUFFER itm;
BYTE* db;
itm = $a_item;
db = $v;
&((itm->GenericReparseBuffer).DataBuffer) = db;
}
]"
end

Line 5 of the C code part is where I attempt to assign the array
"DataBuffer[]" in the struct "GenericReparseBuffer" which is a member of
the
struct "REPARSE_GUID_DATA_BUFFER". My Eiffel compiler translates the
Eiffel
code into C and uses MSVC++ to compile it. The C compiler gives me this
error:

error C2106: '=' : left operand must be l-value

I'm hoping I can get some assistance with this. Sorry about the Eiffel
code
but this is a problem with the C part.
 
B

Ben Bacarisse

The Hole Pounder said:
My C skills are rather meager so forgive me if I do not express my
question
clearly enough. Here is a struct that is declared in Windows:

typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

This is significant. The 1 byte array suggests that in reality objects
of this type will really be larger that you see here. It's a common
technique that goes by the name "the struct hack". It means these sort
of objects are intended to be over-allocated with the extra space being
available via the array member called DataBuffer.
} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

Now I'm going to show my attempt at assigning to "DataBuffer". This code
is
written in Eiffel but the part inside of the square brackets ([]) is C
code
except you will see some "$" symbols which you can ignore:

set_c_generic_reparse_buffer_data_buffer_pointer (a_item, v: POINTER) is
external
"C inline use <Windows.h>"
alias
"[
{
PREPARSE_GUID_DATA_BUFFER itm;
BYTE* db;
itm = $a_item;
db = $v;

You say this is C but these two lines (with the $s) are not C. To help
in detail, people would need to know what these lines mean and that to
do with the Eiffel/C interface.
&((itm->GenericReparseBuffer).DataBuffer) = db;

You don't need any of those parentheses though of course they do no
harm.
}
]"
end

Line 5 of the C code part is where I attempt to assign the array
"DataBuffer[]" in the struct "GenericReparseBuffer" which is a member of
the
struct "REPARSE_GUID_DATA_BUFFER". My Eiffel compiler translates the
Eiffel
code into C and uses MSVC++ to compile it. The C compiler gives me this
error:

error C2106: '=' : left operand must be l-value

The compiler is telling you can't assign to the result of an
&expression. Just like +x = 1 is not allowed, neither is &<anything> =
<anything else>.

& gives you the address and I can see why you want to assign to it --
your intent is probably to make DataBuffer point at the data you want it
to but you simply can't do that. Had the structure defined that member
to be a pointer you could (and you would not need the &) but an array
can't be made to refer to anything other than it elements.

It's not possible for me to help much more because I have no idea what
this fragment of code is supposed to do. Should it allocate a
REPARSE_GUID_DATA_BUFFER? Should it copy the data pointed to by 'v'
into the DataBuffer member of an existing REPARSE_GUID_DATA_BUFFER?
How much data should be copied?
I'm hoping I can get some assistance with this. Sorry about the Eiffel
code
but this is a problem with the C part.

It's mainly an Eiffel issue in the sense that Eiffel people can tell you
how this sort of thing is usually done. For a C person to help, you'd
have to provide a lot of detail about exactly what the code should do.
If you can find some Eiffel group, that is likely to be a better source
of help.
 
C

Charles Keepax

            &((itm->GenericReparseBuffer).DataBuffer) = db;
error C2106: '=' : left operand must be l-value
The issue here is that the & operator returns the address of that
struct member, you can not assign to that the compiler decides where
it goes. It looks like you are expecting DataBuffer to be a pointer in
which case this would work without the &, however...
    struct {BYTE DataBuffer[1]; } GenericReparseBuffer;
I have to say I find this definition a bit suspect this defines
DataBuffer as an array rather than a pointer. Whilst for the most part
they are fairly interchangeable in C, in this case space will actually
be allocated in the struct for the bytes, in this case just 1 byte.
Effectively, this means you can't assign the address of something to
it and just have to use the provided 1 byte buffer. Perhaps someone
who knows the Windows API better than me can shed some light on the
appropriate use of this struct.

Hope that helps some,
Charles Keepax
 
B

Ben Bacarisse

Charles Keepax said:
    struct {BYTE DataBuffer[1]; } GenericReparseBuffer;
I have to say I find this definition a bit suspect this defines
DataBuffer as an array rather than a pointer. Whilst for the most part
they are fairly interchangeable in C, in this case space will actually
be allocated in the struct for the bytes, in this case just 1 byte.
Effectively, this means you can't assign the address of something to
it and just have to use the provided 1 byte buffer. Perhaps someone
who knows the Windows API better than me can shed some light on the
appropriate use of this struct.

It is almost certainly an example of the struct hack described here:

http://c-faq.com/struct/structhack.html
 
N

Nick

The Hole Pounder said:
My C skills are rather meager so forgive me if I do not express my
question
clearly enough. Here is a struct that is declared in Windows:

typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

I've never liked typedefing a pointer rather than defining the bare type
and using a * when you want a pointer (just like stdio.h does with FILE
- that's a big hint to everybody), and I've never liked Hungarian style
notation.

Here we see the two coming together in an horrible way. You appear to
have two buffer types, one for reparsing and one for preparsing, but
in fact:
REPARSE_GUID_DATA_BUFFER *ptr
will generate a PREPARSE_GUID_DATA_BUFFER.

Urg!
 
B

Ben Bacarisse

Nick said:
The Hole Pounder said:
My C skills are rather meager so forgive me if I do not express my
question
clearly enough. Here is a struct that is declared in Windows:

typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

I've never liked typedefing a pointer rather than defining the bare type
and using a * when you want a pointer (just like stdio.h does with FILE
- that's a big hint to everybody), and I've never liked Hungarian style
notation.

I don't see anything that I'd call Hungarian there.

<snip>
 
S

Shao Miller

Nick said:
The Hole Pounder said:
... ... ... Here is a struct that is declared in Windows:

typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

I've never liked typedefing a pointer rather than defining the bare type
and using a * when you want a pointer (just like stdio.h does with FILE
- that's a big hint to everybody), and I've never liked Hungarian style
notation.

Here we see the two coming together in an horrible way. You appear to
have two buffer types, one for reparsing and one for preparsing, but
in fact:
REPARSE_GUID_DATA_BUFFER *ptr
will generate a PREPARSE_GUID_DATA_BUFFER.

Urg!

That's just the way it is, in Windows. That is, it's pretty common.
The above is from Microsoft.
 
B

BartC

Ben Bacarisse said:
typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

I've never liked typedefing a pointer rather than defining the bare type
and using a * when you want a pointer (just like stdio.h does with FILE
- that's a big hint to everybody), and I've never liked Hungarian style
notation.

I don't see anything that I'd call Hungarian there.

Possibly the "P" in "PREPARSE" (pointer to a REPARSE buffer). This is
confusing because it looks like "PRE-PARSE".
 
B

Ben Bacarisse

BartC said:
Ben Bacarisse said:
typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

I've never liked typedefing a pointer rather than defining the bare type
and using a * when you want a pointer (just like stdio.h does with FILE
- that's a big hint to everybody), and I've never liked Hungarian style
notation.

I don't see anything that I'd call Hungarian there.

Possibly the "P" in "PREPARSE" (pointer to a REPARSE buffer). This is
confusing because it looks like "PRE-PARSE".

I see, yes, that might count. Hungarian prefixes are normally lower
case though.
 
N

Nick

Shao Miller said:
Nick said:
The Hole Pounder said:
... ... ... Here is a struct that is declared in Windows:

typedef struct _REPARSE_GUID_DATA_BUFFER
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
GUID ReparseGuid;
struct {BYTE DataBuffer[1]; } GenericReparseBuffer;

} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;

I've never liked typedefing a pointer rather than defining the bare type
and using a * when you want a pointer (just like stdio.h does with FILE
- that's a big hint to everybody), and I've never liked Hungarian style
notation.

Here we see the two coming together in an horrible way. You appear to
have two buffer types, one for reparsing and one for preparsing, but
in fact:
REPARSE_GUID_DATA_BUFFER *ptr
will generate a PREPARSE_GUID_DATA_BUFFER.

Urg!

That's just the way it is, in Windows. That is, it's pretty
common. The above is from Microsoft.

Finally the explanation for all those botnets is starting to appear.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top