Variable Number of Argument function in WDM

Hi All,
I have a variable list of argument function which
copies all the
specified buffer content into a single buffer. I am
listing the source
code of this function. In this function even if I pass
a single
variable in the variable argument list, while loop in
this function is
getting executed. I tested this code in User mode and
is working fine.
Please help…

STATUS
PackOutputBuffer(
PUCHAR puOutBuf_o, //output buffer to be filled
PUINT32 pu32NumBytes_o, //Number of bytes copied in
out buf
PVOID ArgumentList_i, //variable list of arguments
… //Variable number of arguments
)
{

va_list valist;
PVOID Argument = NULL;
UINT32 u32OutStatus =0;
UINT32 u32CurBuffPos = ZERO;
UINT8 uArgLen = ZERO;
UINT8 puArg = NULL;

if ( NULL == ArgumentList_i )
return INVALIDPARAM;

if ( ( NULL == puOutBuf_o ) || ( NULL ==
pu32NumBytes_o))
return INVALIDPARAM;

Argument = ArgumentList_i; //first argument

//first element is always status with 4 bytes length
u32OutStatus = *((PUINT32)Argument);
RtlCopyMemory ((puOutBuf_o +
u32CurBuffPos),&u32OutStatus,
STATUS_SIZE);
u32CurBuffPos += STATUS_SIZE;

//Initialize variable arguments
va_start(valist,ArgumentList_i);

//go throught the list until no more aruguments
Argument = va_arg( valist, PVOID);

while( NULL != Argument )
{
// Now onwards first argument is length, next is
buffer
uArgLen = *((PUINT8)Argument);
//get the buffer
Argument = va_arg( valist, PVOID);
if ( NULL != Argument)
{
//copy this to the output buffer
RtlCopyMemory ((puOutBuf_o +
u32CurBuffPos),Argument, uArgLen);
u32CurBuffPos += uArgLen;
}
//get next one
Argument = va_arg( valist, PVOID);
} // end of while () completed the list

//Reset variable arguments
va_end( valist );
//copy the number of bytes copied information
*pu32NumBytes_o = u32CurBuffPos;
}

*****When I invoke this function with only one
argument in this
varaibel argument list, that while loop is getting
executed twice.
WHY??? It is supposed to omit the while loop… But
not…

PackOutputBuffer(pu8OutBuf,
&u32NumBytes,(PVOID)&u32BlstStatus );

Thanks in adavance
Suja


Do you Yahoo!?
Yahoo! Photos: High-quality 4x6 digital prints for 25¢
http://photos.yahoo.com/ph/print_splash

I don’t care if your code works in user mode or not, it is broken. Your call
to va_start and va_arg have to be before your use of the first variable
argument, not after.

=====================
Mark Roddy

-----Original Message-----
From: SUJA JAMES [mailto:xxxxx@yahoo.com]
Sent: Wednesday, April 21, 2004 10:19 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Variable Number of Argument function in WDM

Hi All,
I have a variable list of argument function which copies all
the specified buffer content into a single buffer. I am
listing the source code of this function. In this function
even if I pass a single variable in the variable argument
list, while loop in this function is getting executed. I
tested this code in User mode and is working fine.
Please help…

STATUS
PackOutputBuffer(
PUCHAR puOutBuf_o, //output buffer to be filled
PUINT32 pu32NumBytes_o, //Number of bytes copied in out buf
PVOID ArgumentList_i, //variable list of arguments
… //Variable number of arguments
)
{

va_list valist;
PVOID Argument = NULL;
UINT32 u32OutStatus =0;
UINT32 u32CurBuffPos = ZERO;
UINT8 uArgLen = ZERO;
UINT8 puArg = NULL;

if ( NULL == ArgumentList_i )
return INVALIDPARAM;

if ( ( NULL == puOutBuf_o ) || ( NULL ==
pu32NumBytes_o))
return INVALIDPARAM;

Argument = ArgumentList_i; //first argument

//first element is always status with 4 bytes length
u32OutStatus = *((PUINT32)Argument);
RtlCopyMemory ((puOutBuf_o +
u32CurBuffPos),&u32OutStatus,
STATUS_SIZE);
u32CurBuffPos += STATUS_SIZE;

//Initialize variable arguments
va_start(valist,ArgumentList_i);

//go throught the list until no more aruguments
Argument = va_arg( valist, PVOID);

while( NULL != Argument )
{
// Now onwards first argument is length, next is buffer
uArgLen = *((PUINT8)Argument);
//get the buffer
Argument = va_arg( valist, PVOID);
if ( NULL != Argument)
{
//copy this to the output buffer
RtlCopyMemory ((puOutBuf_o +
u32CurBuffPos),Argument, uArgLen);
u32CurBuffPos += uArgLen;
}
//get next one
Argument = va_arg( valist, PVOID);
} // end of while () completed the list

//Reset variable arguments
va_end( valist );
//copy the number of bytes copied information
*pu32NumBytes_o = u32CurBuffPos;
}

*****When I invoke this function with only one argument in
this varaibel argument list, that while loop is getting
executed twice.
WHY??? It is supposed to omit the while loop… But not…

PackOutputBuffer(pu8OutBuf,
&u32NumBytes,(PVOID)&u32BlstStatus );

Thanks in adavance
Suja


Do you Yahoo!?
Yahoo! Photos: High-quality 4x6 digital prints for 25?
http://photos.yahoo.com/ph/print_splash


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as:
xxxxx@stratus.com To unsubscribe send a blank email to
xxxxx@lists.osr.com

“SUJA JAMES” wrote in message news:xxxxx@ntdev…
>
> I have a variable list of argument function which copies
> all the specified buffer content into a single buffer.
> I am listing the source code of this function. In this
> function even if I pass a single variable in the variable
> argument list, while loop in this function is getting
> executed. I tested this code in User mode and is working
> fine.

It looks like this ought to work for any odd number of unnamed
arguments as long as the last argument is PVOID with value NULL.
Calling it with an even number of unnamed parameters, or with the
last one not a NULL PVOID, results in C’s ‘undefined behavior’.

If you are meeting these conditions and seeing problems, I’d check
your copies to make sure you’re not corrupting yourself somewhere.

> STATUS
> PackOutputBuffer(
> PUCHAR puOutBuf_o, //output buffer to be filled
> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> out buf
> PVOID ArgumentList_i, //variable list of arguments
> … //Variable number of arguments
> )
> {
>
> va_list valist;
> PVOID Argument = NULL;
> UINT32 u32OutStatus =0;
> UINT32 u32CurBuffPos = ZERO;
> UINT8 uArgLen = ZERO;
> UINT8 puArg = NULL;
>
> if ( NULL == ArgumentList_i )
> return INVALIDPARAM;
>
> if ( ( NULL == puOutBuf_o ) || ( NULL ==
> pu32NumBytes_o))
> return INVALIDPARAM;
>
> Argument = ArgumentList_i; //first argument
>
> //first element is always status with 4 bytes length
> u32OutStatus = *((PUINT32)Argument);
> RtlCopyMemory ((puOutBuf_o +
> u32CurBuffPos),&u32OutStatus,
> STATUS_SIZE);
> u32CurBuffPos += STATUS_SIZE;
>
> //Initialize variable arguments
> va_start(valist,ArgumentList_i);
>
> //go throught the list until no more aruguments
> Argument = va_arg( valist, PVOID);
>
> while( NULL != Argument )
> {
> // Now onwards first argument is length, next is
> buffer
> uArgLen = *((PUINT8)Argument);
> //get the buffer
> Argument = va_arg( valist, PVOID);
> if ( NULL != Argument)
> {
> //copy this to the output buffer
> RtlCopyMemory ((puOutBuf_o +
> u32CurBuffPos),Argument, uArgLen);
> u32CurBuffPos += uArgLen;
> }
> //get next one
> Argument = va_arg( valist, PVOID);
> } // end of while () completed the list
>
> //Reset variable arguments
> va_end( valist );
> //copy the number of bytes copied information
> *pu32NumBytes_o = u32CurBuffPos;
> }
>
> ***** When I invoke this function with only one
> argument in this
> varaibel argument list, that while loop is getting
> executed twice.
> WHY??? It is supposed to omit the while loop… But
> not…
>
> PackOutputBuffer(pu8OutBuf,
> &u32NumBytes,(PVOID)&u32BlstStatus );

Use a debugger, and look at the return values of va_arg at each call
when only 1 argument is passed.

The first time, it’s ArgumentList_i, the second time it’s null, and the
third time you call it, it’s *completely undefined*. It might be a
reasonable value, it might not.

That third call needs to be inside the if for the second one. (at
least… I haven’t really thought much about how to design this better,
though I’m pretty sure it can be).

J. J. Farrell wrote:

“SUJA JAMES” wrote in message news:xxxxx@ntdev…
>
>>I have a variable list of argument function which copies
>>all the specified buffer content into a single buffer.
>>I am listing the source code of this function. In this
>>function even if I pass a single variable in the variable
>>argument list, while loop in this function is getting
>>executed. I tested this code in User mode and is working
>>fine.
>
>
> It looks like this ought to work for any odd number of unnamed
> arguments as long as the last argument is PVOID with value NULL.
> Calling it with an even number of unnamed parameters, or with the
> last one not a NULL PVOID, results in C’s ‘undefined behavior’.
>
> If you are meeting these conditions and seeing problems, I’d check
> your copies to make sure you’re not corrupting yourself somewhere.
>
>
>>STATUS
>>PackOutputBuffer(
>> PUCHAR puOutBuf_o, //output buffer to be filled
>> PUINT32 pu32NumBytes_o, //Number of bytes copied in
>>out buf
>> PVOID ArgumentList_i, //variable list of arguments
>>… //Variable number of arguments
>>)
>>{
>>
>>va_list valist;
>>PVOID Argument = NULL;
>>UINT32 u32OutStatus =0;
>>UINT32 u32CurBuffPos = ZERO;
>>UINT8 uArgLen = ZERO;
>>UINT8 puArg = NULL;
>>
>> if ( NULL == ArgumentList_i )
>>return INVALIDPARAM;
>>
>>if ( ( NULL == puOutBuf_o ) || ( NULL ==
>>pu32NumBytes_o))
>>return INVALIDPARAM;
>>
>>Argument = ArgumentList_i; //first argument
>>
>>//first element is always status with 4 bytes length
>>u32OutStatus = *((PUINT32)Argument);
>>RtlCopyMemory ((puOutBuf_o +
>>u32CurBuffPos),&u32OutStatus,
>>STATUS_SIZE);
>>u32CurBuffPos += STATUS_SIZE;
>>
>>//Initialize variable arguments
>>va_start(valist,ArgumentList_i);
>>
>>//go throught the list until no more aruguments
>>Argument = va_arg( valist, PVOID);
>>
>>while( NULL != Argument )
>>{
>>// Now onwards first argument is length, next is
>>buffer
>> uArgLen = *((PUINT8)Argument);
>> //get the buffer
>> Argument = va_arg( valist, PVOID);
>> if ( NULL != Argument)
>> {
>>//copy this to the output buffer
>>RtlCopyMemory ((puOutBuf_o +
>>u32CurBuffPos),Argument, uArgLen);
>>u32CurBuffPos += uArgLen;
>> }
>> //get next one
>>Argument = va_arg( valist, PVOID);
>>} // end of while () completed the list
>>
>>//Reset variable arguments
>>va_end( valist );
>>//copy the number of bytes copied information
>>*pu32NumBytes_o = u32CurBuffPos;
>>}
>>
>> ***** When I invoke this function with only one
>>argument in this
>>varaibel argument list, that while loop is getting
>>executed twice.
>>WHY??? It is supposed to omit the while loop… But
>>not…
>>
>>PackOutputBuffer(pu8OutBuf,
>>&u32NumBytes,(PVOID)&u32BlstStatus );
>
>


…/ray..

Please remove “.spamblock” from my email address if you need to contact
me outside the newgroup.

“Ray Trent” wrote in message
news:xxxxx@ntdev…
>
> Use a debugger, and look at the return values of va_arg at each call
> when only 1 argument is passed.
>
> The first time, it’s ArgumentList_i,

I haven’t used a debugger. If what you say is true then it
looks like there’s a major problem with the implementation.
The first call to va_arg should return the value of the
first unnamed parameter.

> the second time it’s null,

If only one unnamed parameter is passed, then a second call
to va_arg results in C’s ‘undefined behaviour’. At that
point all bets are off and anything can happen.

> and the
> third time you call it, it’s completely undefined. It might be a
> reasonable value, it might not.
>
> That third call needs to be inside the if for the second one. (at
> least… I haven’t really thought much about how to design this better,
> though I’m pretty sure it can be).

The ‘variable arguments’ aspects of this code should be fine
as long as there is an odd number of unnamed parameters and
the last one is a PVOID with value NULL. If there is a single
unnamed parameter that’s a NULL PVOID, then the contents of
the while loop should never be executed.

If the calls to this function meet these conditions but the
while loop doesn’t behave, then something else is screwing
things up.

> J. J. Farrell wrote:
>
> > “SUJA JAMES” wrote in message
news:xxxxx@ntdev…
> >
> >>I have a variable list of argument function which copies
> >>all the specified buffer content into a single buffer.
> >>I am listing the source code of this function. In this
> >>function even if I pass a single variable in the variable
> >>argument list, while loop in this function is getting
> >>executed. I tested this code in User mode and is working
> >>fine.
> >
> >
> > It looks like this ought to work for any odd number of unnamed
> > arguments as long as the last argument is PVOID with value NULL.
> > Calling it with an even number of unnamed parameters, or with the
> > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> >
> > If you are meeting these conditions and seeing problems, I’d check
> > your copies to make sure you’re not corrupting yourself somewhere.
> >
> >
> >>STATUS
> >>PackOutputBuffer(
> >> PUCHAR puOutBuf_o, //output buffer to be filled
> >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> >>out buf
> >> PVOID ArgumentList_i, //variable list of arguments
> >>… //Variable number of arguments
> >>)
> >>{
> >>
> >>va_list valist;
> >>PVOID Argument = NULL;
> >>UINT32 u32OutStatus =0;
> >>UINT32 u32CurBuffPos = ZERO;
> >>UINT8 uArgLen = ZERO;
> >>UINT8 puArg = NULL;
> >>
> >> if ( NULL == ArgumentList_i )
> >>return INVALIDPARAM;
> >>
> >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> >>pu32NumBytes_o))
> >>return INVALIDPARAM;
> >>
> >>Argument = ArgumentList_i; //first argument
> >>
> >>//first element is always status with 4 bytes length
> >>u32OutStatus = *((PUINT32)Argument);
> >>RtlCopyMemory ((puOutBuf_o +
> >>u32CurBuffPos),&u32OutStatus,
> >>STATUS_SIZE);
> >>u32CurBuffPos += STATUS_SIZE;
> >>
> >>//Initialize variable arguments
> >>va_start(valist,ArgumentList_i);
> >>
> >>//go throught the list until no more aruguments
> >>Argument = va_arg( valist, PVOID);
> >>
> >>while( NULL != Argument )
> >>{
> >>// Now onwards first argument is length, next is
> >>buffer
> >> uArgLen = *((PUINT8)Argument);
> >> //get the buffer
> >> Argument = va_arg( valist, PVOID);
> >> if ( NULL != Argument)
> >> {
> >>//copy this to the output buffer
> >>RtlCopyMemory ((puOutBuf_o +
> >>u32CurBuffPos),Argument, uArgLen);
> >>u32CurBuffPos += uArgLen;
> >> }
> >> //get next one
> >>Argument = va_arg( valist, PVOID);
> >>} // end of while () completed the list
> >>
> >>//Reset variable arguments
> >>va_end( valist );
> >>//copy the number of bytes copied information
> >>*pu32NumBytes_o = u32CurBuffPos;
> >>}
> >>
> >> ***** When I invoke this function with only one
> >>argument in this
> >>varaibel argument list, that while loop is getting
> >>executed twice.
> >>WHY??? It is supposed to omit the while loop… But
> >>not…
> >>
> >>PackOutputBuffer(pu8OutBuf,
> >>&u32NumBytes,(PVOID)&u32BlstStatus );

I got it to work the following way. Note a few caveats:

  1. The variable argument list passed to the procedure must have your own
    end marker. I use NULL.
  2. The first call to va_arg() gives me the *second* argument. Don’t ask me
    why.
  3. To get the first argument, you just use an “arg=parameter” line.

If you go to the MSDN Library and ask for va_arg, they have a source program
that explains it pretty decently. Hope this helps !

Alberto.

=============

#include <string.h>

void poBuffer(char *aList, …)
{
va_list valist;
va_start(valist,aList);
char arg = aList;

int count=0;

while (arg!=NULL)
{
printf(“%d. %s\n”, count, arg);
arg = va_arg(valist,char
);
count++;
}
}

main()
{
char *p = “hello”;
char *q = “there”;
poBuffer(p, NULL);
printf(“=====================\n”);
poBuffer(p, q, NULL);
return 0;
}

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
Sent: Tuesday, April 27, 2004 10:32 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Variable Number of Argument function in WDM

“Ray Trent” wrote in message
news:xxxxx@ntdev…
>
> Use a debugger, and look at the return values of va_arg at each call
> when only 1 argument is passed.
>
> The first time, it’s ArgumentList_i,

I haven’t used a debugger. If what you say is true then it
looks like there’s a major problem with the implementation.
The first call to va_arg should return the value of the
first unnamed parameter.

> the second time it’s null,

If only one unnamed parameter is passed, then a second call
to va_arg results in C’s ‘undefined behaviour’. At that
point all bets are off and anything can happen.

> and the
> third time you call it, it’s completely undefined. It might be a
> reasonable value, it might not.
>
> That third call needs to be inside the if for the second one. (at
> least… I haven’t really thought much about how to design this better,
> though I’m pretty sure it can be).

The ‘variable arguments’ aspects of this code should be fine
as long as there is an odd number of unnamed parameters and
the last one is a PVOID with value NULL. If there is a single
unnamed parameter that’s a NULL PVOID, then the contents of
the while loop should never be executed.

If the calls to this function meet these conditions but the
while loop doesn’t behave, then something else is screwing
things up.

> J. J. Farrell wrote:
>
> > “SUJA JAMES” wrote in message
news:xxxxx@ntdev…
> >
> >>I have a variable list of argument function which copies
> >>all the specified buffer content into a single buffer.
> >>I am listing the source code of this function. In this
> >>function even if I pass a single variable in the variable
> >>argument list, while loop in this function is getting
> >>executed. I tested this code in User mode and is working
> >>fine.
> >
> >
> > It looks like this ought to work for any odd number of unnamed
> > arguments as long as the last argument is PVOID with value NULL.
> > Calling it with an even number of unnamed parameters, or with the
> > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> >
> > If you are meeting these conditions and seeing problems, I’d check
> > your copies to make sure you’re not corrupting yourself somewhere.
> >
> >
> >>STATUS
> >>PackOutputBuffer(
> >> PUCHAR puOutBuf_o, //output buffer to be filled
> >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> >>out buf
> >> PVOID ArgumentList_i, //variable list of arguments
> >>… //Variable number of arguments
> >>)
> >>{
> >>
> >>va_list valist;
> >>PVOID Argument = NULL;
> >>UINT32 u32OutStatus =0;
> >>UINT32 u32CurBuffPos = ZERO;
> >>UINT8 uArgLen = ZERO;
> >>UINT8 puArg = NULL;
> >>
> >> if ( NULL == ArgumentList_i )
> >>return INVALIDPARAM;
> >>
> >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> >>pu32NumBytes_o))
> >>return INVALIDPARAM;
> >>
> >>Argument = ArgumentList_i; //first argument
> >>
> >>//first element is always status with 4 bytes length
> >>u32OutStatus = *((PUINT32)Argument);
> >>RtlCopyMemory ((puOutBuf_o +
> >>u32CurBuffPos),&u32OutStatus,
> >>STATUS_SIZE);
> >>u32CurBuffPos += STATUS_SIZE;
> >>
> >>//Initialize variable arguments
> >>va_start(valist,ArgumentList_i);
> >>
> >>//go throught the list until no more aruguments
> >>Argument = va_arg( valist, PVOID);
> >>
> >>while( NULL != Argument )
> >>{
> >>// Now onwards first argument is length, next is
> >>buffer
> >> uArgLen = *((PUINT8)Argument);
> >> //get the buffer
> >> Argument = va_arg( valist, PVOID);
> >> if ( NULL != Argument)
> >> {
> >>//copy this to the output buffer
> >>RtlCopyMemory ((puOutBuf_o +
> >>u32CurBuffPos),Argument, uArgLen);
> >>u32CurBuffPos += uArgLen;
> >> }
> >> //get next one
> >>Argument = va_arg( valist, PVOID);
> >>} // end of while () completed the list
> >>
> >>//Reset variable arguments
> >>va_end( valist );
> >>//copy the number of bytes copied information
> >>*pu32NumBytes_o = u32CurBuffPos;
> >>}
> >>
> >> ***** When I invoke this function with only one
> >>argument in this
> >>varaibel argument list, that while loop is getting
> >>executed twice.
> >>WHY??? It is supposed to omit the while loop… But
> >>not…
> >>
> >>PackOutputBuffer(pu8OutBuf,
> >>&u32NumBytes,(PVOID)&u32BlstStatus );


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@compuware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

The contents of this e-mail are intended for the named addressee only. It
contains information that may be confidential. Unless you are the named
addressee or an authorized designee, you may not copy or use it, or disclose
it to anyone else. If you received it in error please notify us immediately
and then destroy it.</string.h>

Ok, I believe I found the reason why I always get the second parameter the
first time I call va_arg(). The MSDN documentation states that va_start() is
called as follows:

va_start(arg_ptr, prev_param)

where "prev_param" is the parameter ONE BEFORE the first element of the list
! To quote the MSDN documentation,

====================================
va_start sets arg_ptr to the first optional argument in the list of
arguments passed to the function. The argument arg_ptr must have va_list
type. The argument prev_param is the name of the required parameter
immediately preceding the first optional argument in the argument list. If
prev_param is declared with the register storage class, the macro's behavior
is undefined. va_start must be used before va_arg is used for the first
time.

So, if I call va_start(valist, myList), this is stating that myList is the
"one before" parameter, therefore the first element I get when I call
va_arg() is actually the SECOND argument in the list.

Somehow I think the Unix way was more sensible, but hey, this is how the
ANSI standard works.

Alberto.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Moreira, Alberto
Sent: Wednesday, April 28, 2004 11:24 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Variable Number of Argument function in WDM

I got it to work the following way. Note a few caveats:

  1. The variable argument list passed to the procedure must have your own
    end marker. I use NULL.
  2. The first call to va_arg() gives me the *second* argument. Don't ask me
    why.
  3. To get the first argument, you just use an "arg=parameter" line.

If you go to the MSDN Library and ask for va_arg, they have a source program
that explains it pretty decently. Hope this helps !

Alberto.

=============

#include <string.h>

void poBuffer(char *aList, ...)
{
va_list valist;
va_start(valist,aList);
char arg = aList;

int count=0;

while (arg!=NULL)
{
printf("%d. %s\n", count, arg);
arg = va_arg(valist,char
);
count++;
}
}

main()
{
char *p = "hello";
char *q = "there";
poBuffer(p, NULL);
printf("=====================\n");
poBuffer(p, q, NULL);
return 0;
}

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
Sent: Tuesday, April 27, 2004 10:32 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Variable Number of Argument function in WDM

"Ray Trent" wrote in message
news:xxxxx@ntdev...
>
> Use a debugger, and look at the return values of va_arg at each call
> when only 1 argument is passed.
>
> The first time, it's ArgumentList_i,

I haven't used a debugger. If what you say is true then it
looks like there's a major problem with the implementation.
The first call to va_arg should return the value of the
first unnamed parameter.

> the second time it's null,

If only one unnamed parameter is passed, then a second call
to va_arg results in C's 'undefined behaviour'. At that
point all bets are off and anything can happen.

> and the
> third time you call it, it's completely undefined. It might be a
> reasonable value, it might not.
>
> That third call needs to be inside the if for the second one. (at
> least... I haven't really thought much about how to design this better,
> though I'm pretty sure it can be).

The 'variable arguments' aspects of this code should be fine
as long as there is an odd number of unnamed parameters and
the last one is a PVOID with value NULL. If there is a single
unnamed parameter that's a NULL PVOID, then the contents of
the while loop should never be executed.

If the calls to this function meet these conditions but the
while loop doesn't behave, then something else is screwing
things up.

> J. J. Farrell wrote:
>
> > "SUJA JAMES" wrote in message
news:xxxxx@ntdev...
> >
> >>I have a variable list of argument function which copies
> >>all the specified buffer content into a single buffer.
> >>I am listing the source code of this function. In this
> >>function even if I pass a single variable in the variable
> >>argument list, while loop in this function is getting
> >>executed. I tested this code in User mode and is working
> >>fine.
> >
> >
> > It looks like this ought to work for any odd number of unnamed
> > arguments as long as the last argument is PVOID with value NULL.
> > Calling it with an even number of unnamed parameters, or with the
> > last one not a NULL PVOID, results in C's 'undefined behavior'.
> >
> > If you are meeting these conditions and seeing problems, I'd check
> > your copies to make sure you're not corrupting yourself somewhere.
> >
> >
> >>STATUS
> >>PackOutputBuffer(
> >> PUCHAR puOutBuf_o, //output buffer to be filled
> >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> >>out buf
> >> PVOID ArgumentList_i, //variable list of arguments
> >>... //Variable number of arguments
> >>)
> >>{
> >>
> >>va_list valist;
> >>PVOID Argument = NULL;
> >>UINT32 u32OutStatus =0;
> >>UINT32 u32CurBuffPos = ZERO;
> >>UINT8 uArgLen = ZERO;
> >>UINT8 puArg = NULL;
> >>
> >> if ( NULL == ArgumentList_i )
> >>return INVALIDPARAM;
> >>
> >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> >>pu32NumBytes_o))
> >>return INVALIDPARAM;
> >>
> >>Argument = ArgumentList_i; //first argument
> >>
> >>//first element is always status with 4 bytes length
> >>u32OutStatus = *((PUINT32)Argument);
> >>RtlCopyMemory ((puOutBuf_o +
> >>u32CurBuffPos),&u32OutStatus,
> >>STATUS_SIZE);
> >>u32CurBuffPos += STATUS_SIZE;
> >>
> >>//Initialize variable arguments
> >>va_start(valist,ArgumentList_i);
> >>
> >>//go throught the list until no more aruguments
> >>Argument = va_arg( valist, PVOID);
> >>
> >>while( NULL != Argument )
> >>{
> >>// Now onwards first argument is length, next is
> >>buffer
> >> uArgLen = *((PUINT8)Argument);
> >> //get the buffer
> >> Argument = va_arg( valist, PVOID);
> >> if ( NULL != Argument)
> >> {
> >>//copy this to the output buffer
> >>RtlCopyMemory ((puOutBuf_o +
> >>u32CurBuffPos),Argument, uArgLen);
> >>u32CurBuffPos += uArgLen;
> >> }
> >> //get next one
> >>Argument = va_arg( valist, PVOID);
> >>} // end of while () completed the list
> >>
> >>//Reset variable arguments
> >>va_end( valist );
> >>//copy the number of bytes copied information
> >>*pu32NumBytes_o = u32CurBuffPos;
> >>}
> >>
> >> ***** When I invoke this function with only one
> >>argument in this
> >>varaibel argument list, that while loop is getting
> >>executed twice.
> >>WHY??? It is supposed to omit the while loop... But
> >>not......
> >>
> >>PackOutputBuffer(pu8OutBuf,
> >>&u32NumBytes,(PVOID)&u32BlstStatus );

---
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@compuware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

The contents of this e-mail are intended for the named addressee only. It
contains information that may be confidential. Unless you are the named
addressee or an authorized designee, you may not copy or use it, or disclose
it to anyone else. If you received it in error please notify us immediately
and then destroy it.

---
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@compuware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

The contents of this e-mail are intended for the named addressee only. It
contains information that may be confidential. Unless you are the named
addressee or an authorized designee, you may not copy or use it, or disclose
it to anyone else. If you received it in error please notify us immediately
and then destroy it.</string.h>

Yes it reminds me particularly two things —

Why stack has to grow downward ?. And yes there is a reason for it!. Convenience.

Why variable number of agruments on a function needs to be processed from right to left, at the agrument passing time ?.

These might have tangential connection with the va_start(), va_arg(), va_end();

ANSI or posix are good standards, but often gives me indigestion. Just a personal taste…

-pro

I think you’re making it seem more complicated than it is. It’s perhaps
easier to think in these terms: the call to va_start must specify the
last parameter that is explicitly declared (the last “named parameter”),
the first call to va_arg gives the first parameter that is not explicitly
declared (the first “unnamed parameter”), subsequent calls to va_arg
retrieve subsequent unnamed parameters. There are ways to do fancier
things, but that’s the basics.

The original poster’s code expects zero or more pairs of unnamed
parameters followed by a null pointer. If it gets that it should be
happy, unless he has problems elsewhere.

This functionality is standard C - there’s nothing MS-specific here.

“Moreira, Alberto” wrote in message
news:xxxxx@ntdev…
> Ok, I believe I found the reason why I always get the second parameter the
> first time I call va_arg(). The MSDN documentation states that va_start()
is
> called as follows:
>
> va_start(arg_ptr, prev_param)
>
> where “prev_param” is the parameter ONE BEFORE the first element of the
list
> ! To quote the MSDN documentation,
>
> ====================================
> va_start sets arg_ptr to the first optional argument in the list of
> arguments passed to the function. The argument arg_ptr must have va_list
> type. The argument prev_param is the name of the required parameter
> immediately preceding the first optional argument in the argument list. If
> prev_param is declared with the register storage class, the macro’s
behavior
> is undefined. va_start must be used before va_arg is used for the first
> time.
> ====================================
>
> So, if I call va_start(valist, myList), this is stating that myList is the
> “one before” parameter, therefore the first element I get when I call
> va_arg() is actually the SECOND argument in the list.
>
> Somehow I think the Unix way was more sensible, but hey, this is how the
> ANSI standard works.
>
>
> Alberto.
>
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of Moreira, Alberto
> Sent: Wednesday, April 28, 2004 11:24 AM
> To: Windows System Software Devs Interest List
> Subject: RE: [ntdev] Variable Number of Argument function in WDM
>
>
> I got it to work the following way. Note a few caveats:
>
> 1. The variable argument list passed to the procedure must have your own
> end marker. I use NULL.
> 2. The first call to va_arg() gives me the second argument. Don’t ask
me
> why.
> 3. To get the first argument, you just use an “arg=parameter” line.
>
> If you go to the MSDN Library and ask for va_arg, they have a source
program
> that explains it pretty decently. Hope this helps !
>
> Alberto.
>
> =============
>
> #include <string.h>
>
> void poBuffer(char *aList, …)
> {
> va_list valist;
> va_start(valist,aList);
> char arg = aList;
>
> int count=0;
>
> while (arg!=NULL)
> {
> printf(“%d. %s\n”, count, arg);
> arg = va_arg(valist,char
);
> count++;
> }
> }
>
>
> main()
> {
> char *p = “hello”;
> char *q = “there”;
> poBuffer(p, NULL);
> printf(“=====================\n”);
> poBuffer(p, q, NULL);
> return 0;
> }
>
>
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> Sent: Tuesday, April 27, 2004 10:32 PM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] Variable Number of Argument function in WDM
>
>
>
> “Ray Trent” wrote in message
> news:xxxxx@ntdev…
> >
> > Use a debugger, and look at the return values of va_arg at each call
> > when only 1 argument is passed.
> >
> > The first time, it’s ArgumentList_i,
>
> I haven’t used a debugger. If what you say is true then it
> looks like there’s a major problem with the implementation.
> The first call to va_arg should return the value of the
> first unnamed parameter.
>
> > the second time it’s null,
>
> If only one unnamed parameter is passed, then a second call
> to va_arg results in C’s ‘undefined behaviour’. At that
> point all bets are off and anything can happen.
>
> > and the
> > third time you call it, it’s completely undefined. It might be a
> > reasonable value, it might not.
> >
> > That third call needs to be inside the if for the second one. (at
> > least… I haven’t really thought much about how to design this better,
> > though I’m pretty sure it can be).
>
> The ‘variable arguments’ aspects of this code should be fine
> as long as there is an odd number of unnamed parameters and
> the last one is a PVOID with value NULL. If there is a single
> unnamed parameter that’s a NULL PVOID, then the contents of
> the while loop should never be executed.
>
> If the calls to this function meet these conditions but the
> while loop doesn’t behave, then something else is screwing
> things up.
>
> > J. J. Farrell wrote:
> >
> > > “SUJA JAMES” wrote in message
> news:xxxxx@ntdev…
> > >
> > >>I have a variable list of argument function which copies
> > >>all the specified buffer content into a single buffer.
> > >>I am listing the source code of this function. In this
> > >>function even if I pass a single variable in the variable
> > >>argument list, while loop in this function is getting
> > >>executed. I tested this code in User mode and is working
> > >>fine.
> > >
> > >
> > > It looks like this ought to work for any odd number of unnamed
> > > arguments as long as the last argument is PVOID with value NULL.
> > > Calling it with an even number of unnamed parameters, or with the
> > > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> > >
> > > If you are meeting these conditions and seeing problems, I’d check
> > > your copies to make sure you’re not corrupting yourself somewhere.
> > >
> > >
> > >>STATUS
> > >>PackOutputBuffer(
> > >> PUCHAR puOutBuf_o, //output buffer to be filled
> > >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> > >>out buf
> > >> PVOID ArgumentList_i, //variable list of arguments
> > >>… //Variable number of arguments
> > >>)
> > >>{
> > >>
> > >>va_list valist;
> > >>PVOID Argument = NULL;
> > >>UINT32 u32OutStatus =0;
> > >>UINT32 u32CurBuffPos = ZERO;
> > >>UINT8 uArgLen = ZERO;
> > >>UINT8 puArg = NULL;
> > >>
> > >> if ( NULL == ArgumentList_i )
> > >>return INVALIDPARAM;
> > >>
> > >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> > >>pu32NumBytes_o))
> > >>return INVALIDPARAM;
> > >>
> > >>Argument = ArgumentList_i; //first argument
> > >>
> > >>//first element is always status with 4 bytes length
> > >>u32OutStatus = *((PUINT32)Argument);
> > >>RtlCopyMemory ((puOutBuf_o +
> > >>u32CurBuffPos),&u32OutStatus,
> > >>STATUS_SIZE);
> > >>u32CurBuffPos += STATUS_SIZE;
> > >>
> > >>//Initialize variable arguments
> > >>va_start(valist,ArgumentList_i);
> > >>
> > >>//go throught the list until no more aruguments
> > >>Argument = va_arg( valist, PVOID);
> > >>
> > >>while( NULL != Argument )
> > >>{
> > >>// Now onwards first argument is length, next is
> > >>buffer
> > >> uArgLen = *((PUINT8)Argument);
> > >> //get the buffer
> > >> Argument = va_arg( valist, PVOID);
> > >> if ( NULL != Argument)
> > >> {
> > >>//copy this to the output buffer
> > >>RtlCopyMemory ((puOutBuf_o +
> > >>u32CurBuffPos),Argument, uArgLen);
> > >>u32CurBuffPos += uArgLen;
> > >> }
> > >> //get next one
> > >>Argument = va_arg( valist, PVOID);
> > >>} // end of while () completed the list
> > >>
> > >>//Reset variable arguments
> > >>va_end( valist );
> > >>//copy the number of bytes copied information
> > >>*pu32NumBytes_o = u32CurBuffPos;
> > >>}
> > >>
> > >> ***** When I invoke this function with only one
> > >>argument in this
> > >>varaibel argument list, that while loop is getting
> > >>executed twice.
> > >>WHY??? It is supposed to omit the while loop… But
> > >>not…
> > >>
> > >>PackOutputBuffer(pu8OutBuf,
> > >>&u32NumBytes,(PVOID)&u32BlstStatus );
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@compuware.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>
> The contents of this e-mail are intended for the named addressee only. It
> contains information that may be confidential. Unless you are the named
> addressee or an authorized designee, you may not copy or use it, or
disclose
> it to anyone else. If you received it in error please notify us
immediately
> and then destroy it.
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@compuware.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>
> The contents of this e-mail are intended for the named addressee only. It
> contains information that may be confidential. Unless you are the named
> addressee or an authorized designee, you may not copy or use it, or
disclose
> it to anyone else. If you received it in error please notify us
immediately
> and then destroy it.
>
></string.h>

If the OP wants to pass zero or more parameters followed by a NULL pointer,
it’s simple enough to do it the way I suggest, which is the same way shown
in Microsoft’s MSDN description of va_arg(). That is, define the function as
follows:

void myfunc(foo bar, char* parmList, …);
{
va_list vaList;
char* ptr = parmList;
va_start(vaList, parmList);
setupWhateverElseNeedsToBeSetUp();
while (ptr != NULL)
{
handleThisArg(ptr);
ptr=va_arg(valist,char*);
}
doWhateverElseIsNeeded();
}

and he will be able to pass zero, one or more parameters as long as they’re
followed by a NULL.

Alberto.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
Sent: Wednesday, April 28, 2004 3:02 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Variable Number of Argument function in WDM

I think you’re making it seem more complicated than it is. It’s perhaps
easier to think in these terms: the call to va_start must specify the
last parameter that is explicitly declared (the last “named parameter”),
the first call to va_arg gives the first parameter that is not explicitly
declared (the first “unnamed parameter”), subsequent calls to va_arg
retrieve subsequent unnamed parameters. There are ways to do fancier
things, but that’s the basics.

The original poster’s code expects zero or more pairs of unnamed
parameters followed by a null pointer. If it gets that it should be
happy, unless he has problems elsewhere.

This functionality is standard C - there’s nothing MS-specific here.

“Moreira, Alberto” wrote in message
news:xxxxx@ntdev…
> Ok, I believe I found the reason why I always get the second parameter the
> first time I call va_arg(). The MSDN documentation states that va_start()
is
> called as follows:
>
> va_start(arg_ptr, prev_param)
>
> where “prev_param” is the parameter ONE BEFORE the first element of the
list
> ! To quote the MSDN documentation,
>
> ====================================
> va_start sets arg_ptr to the first optional argument in the list of
> arguments passed to the function. The argument arg_ptr must have va_list
> type. The argument prev_param is the name of the required parameter
> immediately preceding the first optional argument in the argument list. If
> prev_param is declared with the register storage class, the macro’s
behavior
> is undefined. va_start must be used before va_arg is used for the first
> time.
> ====================================
>
> So, if I call va_start(valist, myList), this is stating that myList is the
> “one before” parameter, therefore the first element I get when I call
> va_arg() is actually the SECOND argument in the list.
>
> Somehow I think the Unix way was more sensible, but hey, this is how the
> ANSI standard works.
>
>
> Alberto.
>
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of Moreira, Alberto
> Sent: Wednesday, April 28, 2004 11:24 AM
> To: Windows System Software Devs Interest List
> Subject: RE: [ntdev] Variable Number of Argument function in WDM
>
>
> I got it to work the following way. Note a few caveats:
>
> 1. The variable argument list passed to the procedure must have your own
> end marker. I use NULL.
> 2. The first call to va_arg() gives me the second argument. Don’t ask
me
> why.
> 3. To get the first argument, you just use an “arg=parameter” line.
>
> If you go to the MSDN Library and ask for va_arg, they have a source
program
> that explains it pretty decently. Hope this helps !
>
> Alberto.
>
> =============
>
> #include <string.h>
>
> void poBuffer(char *aList, …)
> {
> va_list valist;
> va_start(valist,aList);
> char arg = aList;
>
> int count=0;
>
> while (arg!=NULL)
> {
> printf(“%d. %s\n”, count, arg);
> arg = va_arg(valist,char
);
> count++;
> }
> }
>
>
> main()
> {
> char *p = “hello”;
> char *q = “there”;
> poBuffer(p, NULL);
> printf(“=====================\n”);
> poBuffer(p, q, NULL);
> return 0;
> }
>
>
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> Sent: Tuesday, April 27, 2004 10:32 PM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] Variable Number of Argument function in WDM
>
>
>
> “Ray Trent” wrote in message
> news:xxxxx@ntdev…
> >
> > Use a debugger, and look at the return values of va_arg at each call
> > when only 1 argument is passed.
> >
> > The first time, it’s ArgumentList_i,
>
> I haven’t used a debugger. If what you say is true then it
> looks like there’s a major problem with the implementation.
> The first call to va_arg should return the value of the
> first unnamed parameter.
>
> > the second time it’s null,
>
> If only one unnamed parameter is passed, then a second call
> to va_arg results in C’s ‘undefined behaviour’. At that
> point all bets are off and anything can happen.
>
> > and the
> > third time you call it, it’s completely undefined. It might be a
> > reasonable value, it might not.
> >
> > That third call needs to be inside the if for the second one. (at
> > least… I haven’t really thought much about how to design this better,
> > though I’m pretty sure it can be).
>
> The ‘variable arguments’ aspects of this code should be fine
> as long as there is an odd number of unnamed parameters and
> the last one is a PVOID with value NULL. If there is a single
> unnamed parameter that’s a NULL PVOID, then the contents of
> the while loop should never be executed.
>
> If the calls to this function meet these conditions but the
> while loop doesn’t behave, then something else is screwing
> things up.
>
> > J. J. Farrell wrote:
> >
> > > “SUJA JAMES” wrote in message
> news:xxxxx@ntdev…
> > >
> > >>I have a variable list of argument function which copies
> > >>all the specified buffer content into a single buffer.
> > >>I am listing the source code of this function. In this
> > >>function even if I pass a single variable in the variable
> > >>argument list, while loop in this function is getting
> > >>executed. I tested this code in User mode and is working
> > >>fine.
> > >
> > >
> > > It looks like this ought to work for any odd number of unnamed
> > > arguments as long as the last argument is PVOID with value NULL.
> > > Calling it with an even number of unnamed parameters, or with the
> > > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> > >
> > > If you are meeting these conditions and seeing problems, I’d check
> > > your copies to make sure you’re not corrupting yourself somewhere.
> > >
> > >
> > >>STATUS
> > >>PackOutputBuffer(
> > >> PUCHAR puOutBuf_o, //output buffer to be filled
> > >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> > >>out buf
> > >> PVOID ArgumentList_i, //variable list of arguments
> > >>… //Variable number of arguments
> > >>)
> > >>{
> > >>
> > >>va_list valist;
> > >>PVOID Argument = NULL;
> > >>UINT32 u32OutStatus =0;
> > >>UINT32 u32CurBuffPos = ZERO;
> > >>UINT8 uArgLen = ZERO;
> > >>UINT8 puArg = NULL;
> > >>
> > >> if ( NULL == ArgumentList_i )
> > >>return INVALIDPARAM;
> > >>
> > >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> > >>pu32NumBytes_o))
> > >>return INVALIDPARAM;
> > >>
> > >>Argument = ArgumentList_i; //first argument
> > >>
> > >>//first element is always status with 4 bytes length
> > >>u32OutStatus = *((PUINT32)Argument);
> > >>RtlCopyMemory ((puOutBuf_o +
> > >>u32CurBuffPos),&u32OutStatus,
> > >>STATUS_SIZE);
> > >>u32CurBuffPos += STATUS_SIZE;
> > >>
> > >>//Initialize variable arguments
> > >>va_start(valist,ArgumentList_i);
> > >>
> > >>//go throught the list until no more aruguments
> > >>Argument = va_arg( valist, PVOID);
> > >>
> > >>while( NULL != Argument )
> > >>{
> > >>// Now onwards first argument is length, next is
> > >>buffer
> > >> uArgLen = *((PUINT8)Argument);
> > >> //get the buffer
> > >> Argument = va_arg( valist, PVOID);
> > >> if ( NULL != Argument)
> > >> {
> > >>//copy this to the output buffer
> > >>RtlCopyMemory ((puOutBuf_o +
> > >>u32CurBuffPos),Argument, uArgLen);
> > >>u32CurBuffPos += uArgLen;
> > >> }
> > >> //get next one
> > >>Argument = va_arg( valist, PVOID);
> > >>} // end of while () completed the list
> > >>
> > >>//Reset variable arguments
> > >>va_end( valist );
> > >>//copy the number of bytes copied information
> > >>*pu32NumBytes_o = u32CurBuffPos;
> > >>}
> > >>
> > >> ***** When I invoke this function with only one
> > >>argument in this
> > >>varaibel argument list, that while loop is getting
> > >>executed twice.
> > >>WHY??? It is supposed to omit the while loop… But
> > >>not…
> > >>
> > >>PackOutputBuffer(pu8OutBuf,
> > >>&u32NumBytes,(PVOID)&u32BlstStatus );
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@compuware.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>
> The contents of this e-mail are intended for the named addressee only. It
> contains information that may be confidential. Unless you are the named
> addressee or an authorized designee, you may not copy or use it, or
disclose
> it to anyone else. If you received it in error please notify us
immediately
> and then destroy it.
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@compuware.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>
> The contents of this e-mail are intended for the named addressee only. It
> contains information that may be confidential. Unless you are the named
> addressee or an authorized designee, you may not copy or use it, or
disclose
> it to anyone else. If you received it in error please notify us
immediately
> and then destroy it.
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@compuware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

The contents of this e-mail are intended for the named addressee only. It
contains information that may be confidential. Unless you are the named
addressee or an authorized designee, you may not copy or use it, or disclose
it to anyone else. If you received it in error please notify us immediately
and then destroy it.</string.h>

I confess I’m losing track of this discussion. I described what the OP’s
code does. Why should he change it (unless he wants it to do something
else)? Unless my eyesight or brain is failing, your handling of unnamed
parameters is identical to his except that his expects pairs of unnamed
parameters followed by a null pointer whereas yours expects singles.

“Moreira, Alberto” wrote in message
news:xxxxx@ntdev…
> If the OP wants to pass zero or more parameters followed by a NULL
pointer,
> it’s simple enough to do it the way I suggest, which is the same way shown
> in Microsoft’s MSDN description of va_arg(). That is, define the function
as
> follows:
>
> void myfunc(foo bar, char* parmList, …);
> {
> va_list vaList;
> char* ptr = parmList;
> va_start(vaList, parmList);
> setupWhateverElseNeedsToBeSetUp();
> while (ptr != NULL)
> {
> handleThisArg(ptr);
> ptr=va_arg(valist,char*);
> }
> doWhateverElseIsNeeded();
> }
>
> and he will be able to pass zero, one or more parameters as long as
they’re
> followed by a NULL.
>
>
> Alberto.
>
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> Sent: Wednesday, April 28, 2004 3:02 PM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] Variable Number of Argument function in WDM
>
>
> I think you’re making it seem more complicated than it is. It’s perhaps
> easier to think in these terms: the call to va_start must specify the
> last parameter that is explicitly declared (the last “named parameter”),
> the first call to va_arg gives the first parameter that is not explicitly
> declared (the first “unnamed parameter”), subsequent calls to va_arg
> retrieve subsequent unnamed parameters. There are ways to do fancier
> things, but that’s the basics.
>
> The original poster’s code expects zero or more pairs of unnamed
> parameters followed by a null pointer. If it gets that it should be
> happy, unless he has problems elsewhere.
>
> This functionality is standard C - there’s nothing MS-specific here.
>
> “Moreira, Alberto” wrote in message
> news:xxxxx@ntdev…
> > Ok, I believe I found the reason why I always get the second parameter
the
> > first time I call va_arg(). The MSDN documentation states that
va_start()
> is
> > called as follows:
> >
> > va_start(arg_ptr, prev_param)
> >
> > where “prev_param” is the parameter ONE BEFORE the first element of the
> list
> > ! To quote the MSDN documentation,
> >
> > ====================================
> > va_start sets arg_ptr to the first optional argument in the list of
> > arguments passed to the function. The argument arg_ptr must have va_list
> > type. The argument prev_param is the name of the required parameter
> > immediately preceding the first optional argument in the argument list.
If
> > prev_param is declared with the register storage class, the macro’s
> behavior
> > is undefined. va_start must be used before va_arg is used for the first
> > time.
> > ====================================
> >
> > So, if I call va_start(valist, myList), this is stating that myList is
the
> > “one before” parameter, therefore the first element I get when I call
> > va_arg() is actually the SECOND argument in the list.
> >
> > Somehow I think the Unix way was more sensible, but hey, this is how the
> > ANSI standard works.
> >
> >
> > Alberto.
> >
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com]On Behalf Of Moreira, Alberto
> > Sent: Wednesday, April 28, 2004 11:24 AM
> > To: Windows System Software Devs Interest List
> > Subject: RE: [ntdev] Variable Number of Argument function in WDM
> >
> >
> > I got it to work the following way. Note a few caveats:
> >
> > 1. The variable argument list passed to the procedure must have your
own
> > end marker. I use NULL.
> > 2. The first call to va_arg() gives me the second argument. Don’t
ask
> me
> > why.
> > 3. To get the first argument, you just use an “arg=parameter” line.
> >
> > If you go to the MSDN Library and ask for va_arg, they have a source
> program
> > that explains it pretty decently. Hope this helps !
> >
> > Alberto.
> >
> > =============
> >
> > #include <string.h>
> >
> > void poBuffer(char *aList, …)
> > {
> > va_list valist;
> > va_start(valist,aList);
> > char arg = aList;
> >
> > int count=0;
> >
> > while (arg!=NULL)
> > {
> > printf(“%d. %s\n”, count, arg);
> > arg = va_arg(valist,char
);
> > count++;
> > }
> > }
> >
> >
> > main()
> > {
> > char *p = “hello”;
> > char *q = “there”;
> > poBuffer(p, NULL);
> > printf(“=====================\n”);
> > poBuffer(p, q, NULL);
> > return 0;
> > }
> >
> >
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> > Sent: Tuesday, April 27, 2004 10:32 PM
> > To: Windows System Software Devs Interest List
> > Subject: Re:[ntdev] Variable Number of Argument function in WDM
> >
> >
> >
> > “Ray Trent” wrote in message
> > news:xxxxx@ntdev…
> > >
> > > Use a debugger, and look at the return values of va_arg at each call
> > > when only 1 argument is passed.
> > >
> > > The first time, it’s ArgumentList_i,
> >
> > I haven’t used a debugger. If what you say is true then it
> > looks like there’s a major problem with the implementation.
> > The first call to va_arg should return the value of the
> > first unnamed parameter.
> >
> > > the second time it’s null,
> >
> > If only one unnamed parameter is passed, then a second call
> > to va_arg results in C’s ‘undefined behaviour’. At that
> > point all bets are off and anything can happen.
> >
> > > and the
> > > third time you call it, it’s completely undefined. It might be a
> > > reasonable value, it might not.
> > >
> > > That third call needs to be inside the if for the second one. (at
> > > least… I haven’t really thought much about how to design this
better,
> > > though I’m pretty sure it can be).
> >
> > The ‘variable arguments’ aspects of this code should be fine
> > as long as there is an odd number of unnamed parameters and
> > the last one is a PVOID with value NULL. If there is a single
> > unnamed parameter that’s a NULL PVOID, then the contents of
> > the while loop should never be executed.
> >
> > If the calls to this function meet these conditions but the
> > while loop doesn’t behave, then something else is screwing
> > things up.
> >
> > > J. J. Farrell wrote:
> > >
> > > > “SUJA JAMES” wrote in message
> > news:xxxxx@ntdev…
> > > >
> > > >>I have a variable list of argument function which copies
> > > >>all the specified buffer content into a single buffer.
> > > >>I am listing the source code of this function. In this
> > > >>function even if I pass a single variable in the variable
> > > >>argument list, while loop in this function is getting
> > > >>executed. I tested this code in User mode and is working
> > > >>fine.
> > > >
> > > >
> > > > It looks like this ought to work for any odd number of unnamed
> > > > arguments as long as the last argument is PVOID with value NULL.
> > > > Calling it with an even number of unnamed parameters, or with the
> > > > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> > > >
> > > > If you are meeting these conditions and seeing problems, I’d check
> > > > your copies to make sure you’re not corrupting yourself somewhere.
> > > >
> > > >
> > > >>STATUS
> > > >>PackOutputBuffer(
> > > >> PUCHAR puOutBuf_o, //output buffer to be filled
> > > >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> > > >>out buf
> > > >> PVOID ArgumentList_i, //variable list of arguments
> > > >>… //Variable number of arguments
> > > >>)
> > > >>{
> > > >>
> > > >>va_list valist;
> > > >>PVOID Argument = NULL;
> > > >>UINT32 u32OutStatus =0;
> > > >>UINT32 u32CurBuffPos = ZERO;
> > > >>UINT8 uArgLen = ZERO;
> > > >>UINT8 puArg = NULL;
> > > >>
> > > >> if ( NULL == ArgumentList_i )
> > > >>return INVALIDPARAM;
> > > >>
> > > >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> > > >>pu32NumBytes_o))
> > > >>return INVALIDPARAM;
> > > >>
> > > >>Argument = ArgumentList_i; //first argument
> > > >>
> > > >>//first element is always status with 4 bytes length
> > > >>u32OutStatus = *((PUINT32)Argument);
> > > >>RtlCopyMemory ((puOutBuf_o +
> > > >>u32CurBuffPos),&u32OutStatus,
> > > >>STATUS_SIZE);
> > > >>u32CurBuffPos += STATUS_SIZE;
> > > >>
> > > >>//Initialize variable arguments
> > > >>va_start(valist,ArgumentList_i);
> > > >>
> > > >>//go throught the list until no more aruguments
> > > >>Argument = va_arg( valist, PVOID);
> > > >>
> > > >>while( NULL != Argument )
> > > >>{
> > > >>// Now onwards first argument is length, next is
> > > >>buffer
> > > >> uArgLen = *((PUINT8)Argument);
> > > >> //get the buffer
> > > >> Argument = va_arg( valist, PVOID);
> > > >> if ( NULL != Argument)
> > > >> {
> > > >>//copy this to the output buffer
> > > >>RtlCopyMemory ((puOutBuf_o +
> > > >>u32CurBuffPos),Argument, uArgLen);
> > > >>u32CurBuffPos += uArgLen;
> > > >> }
> > > >> //get next one
> > > >>Argument = va_arg( valist, PVOID);
> > > >>} // end of while () completed the list
> > > >>
> > > >>//Reset variable arguments
> > > >>va_end( valist );
> > > >>//copy the number of bytes copied information
> > > >>*pu32NumBytes_o = u32CurBuffPos;
> > > >>}
> > > >>
> > > >> ***** When I invoke this function with only one
> > > >>argument in this
> > > >>varaibel argument list, that while loop is getting
> > > >>executed twice.
> > > >>WHY??? It is supposed to omit the while loop… But
> > > >>not…
> > > >>
> > > >>PackOutputBuffer(pu8OutBuf,
> > > >>&u32NumBytes,(PVOID)&u32BlstStatus );</string.h>

I thought it was clear, no ? He declares his function as

STATUS PackOutputBuffer(
PUCHAR puOutBuf_o,
PUINT32 pu32NumBytes_o,
PVOID ArgumentList_i,
… )

His code does this:

Argument = ArgumentList_i; //first argument
u32OutStatus = *((PUINT32)Argument);
RtlCopyMemory ((puOutBuf_o + u32CurBuffPos),&u32OutStatus,STATUS_SIZE);

Meaning, the first argument must be a pointer. Now he does a va_arg() to get
the second argument, which is a length, and he tests it for NULL. Meaning,
his argument list must be of the form

pointer, length, pointer, length, pointer, length, …, …, pointer, 0

because he tests every *second* element of his list for null.

So, the minimum number of arguments to be passed is 2, not 1, and he must
pass parameters in pairs, never an odd number of them. He calls his function
this way:

PackOutputBuffer(pu8OutBuf, &u32NumBytes, (PVOID)&u32BlstStatus );

when he should rather call it this way:

PackOutputBuffer(pu8OutBuf, &u32NumBytes, (PVOID)&u32BlstStatus, 0 );

because the way he coded things, in pairs, precludes passing an odd number
of parameters to his function. I don’t know, I would declare a structure
such as

typedef struct { int len; char *ptr; } myStruct;

and pass a single list of structures to the function. If nothing else,
provides for cleaner code.

Alberto.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
Sent: Wednesday, April 28, 2004 3:48 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Variable Number of Argument function in WDM

I confess I’m losing track of this discussion. I described what the OP’s
code does. Why should he change it (unless he wants it to do something
else)? Unless my eyesight or brain is failing, your handling of unnamed
parameters is identical to his except that his expects pairs of unnamed
parameters followed by a null pointer whereas yours expects singles.

“Moreira, Alberto” wrote in message
news:xxxxx@ntdev…
> If the OP wants to pass zero or more parameters followed by a NULL
pointer,
> it’s simple enough to do it the way I suggest, which is the same way shown
> in Microsoft’s MSDN description of va_arg(). That is, define the function
as
> follows:
>
> void myfunc(foo bar, char* parmList, …);
> {
> va_list vaList;
> char* ptr = parmList;
> va_start(vaList, parmList);
> setupWhateverElseNeedsToBeSetUp();
> while (ptr != NULL)
> {
> handleThisArg(ptr);
> ptr=va_arg(valist,char*);
> }
> doWhateverElseIsNeeded();
> }
>
> and he will be able to pass zero, one or more parameters as long as
they’re
> followed by a NULL.
>
>
> Alberto.
>
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> Sent: Wednesday, April 28, 2004 3:02 PM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] Variable Number of Argument function in WDM
>
>
> I think you’re making it seem more complicated than it is. It’s perhaps
> easier to think in these terms: the call to va_start must specify the
> last parameter that is explicitly declared (the last “named parameter”),
> the first call to va_arg gives the first parameter that is not explicitly
> declared (the first “unnamed parameter”), subsequent calls to va_arg
> retrieve subsequent unnamed parameters. There are ways to do fancier
> things, but that’s the basics.
>
> The original poster’s code expects zero or more pairs of unnamed
> parameters followed by a null pointer. If it gets that it should be
> happy, unless he has problems elsewhere.
>
> This functionality is standard C - there’s nothing MS-specific here.
>
> “Moreira, Alberto” wrote in message
> news:xxxxx@ntdev…
> > Ok, I believe I found the reason why I always get the second parameter
the
> > first time I call va_arg(). The MSDN documentation states that
va_start()
> is
> > called as follows:
> >
> > va_start(arg_ptr, prev_param)
> >
> > where “prev_param” is the parameter ONE BEFORE the first element of the
> list
> > ! To quote the MSDN documentation,
> >
> > ====================================
> > va_start sets arg_ptr to the first optional argument in the list of
> > arguments passed to the function. The argument arg_ptr must have va_list
> > type. The argument prev_param is the name of the required parameter
> > immediately preceding the first optional argument in the argument list.
If
> > prev_param is declared with the register storage class, the macro’s
> behavior
> > is undefined. va_start must be used before va_arg is used for the first
> > time.
> > ====================================
> >
> > So, if I call va_start(valist, myList), this is stating that myList is
the
> > “one before” parameter, therefore the first element I get when I call
> > va_arg() is actually the SECOND argument in the list.
> >
> > Somehow I think the Unix way was more sensible, but hey, this is how the
> > ANSI standard works.
> >
> >
> > Alberto.
> >
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com]On Behalf Of Moreira, Alberto
> > Sent: Wednesday, April 28, 2004 11:24 AM
> > To: Windows System Software Devs Interest List
> > Subject: RE: [ntdev] Variable Number of Argument function in WDM
> >
> >
> > I got it to work the following way. Note a few caveats:
> >
> > 1. The variable argument list passed to the procedure must have your
own
> > end marker. I use NULL.
> > 2. The first call to va_arg() gives me the second argument. Don’t
ask
> me
> > why.
> > 3. To get the first argument, you just use an “arg=parameter” line.
> >
> > If you go to the MSDN Library and ask for va_arg, they have a source
> program
> > that explains it pretty decently. Hope this helps !
> >
> > Alberto.
> >
> > =============
> >
> > #include <string.h>
> >
> > void poBuffer(char *aList, …)
> > {
> > va_list valist;
> > va_start(valist,aList);
> > char arg = aList;
> >
> > int count=0;
> >
> > while (arg!=NULL)
> > {
> > printf(“%d. %s\n”, count, arg);
> > arg = va_arg(valist,char
);
> > count++;
> > }
> > }
> >
> >
> > main()
> > {
> > char *p = “hello”;
> > char *q = “there”;
> > poBuffer(p, NULL);
> > printf(“=====================\n”);
> > poBuffer(p, q, NULL);
> > return 0;
> > }
> >
> >
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> > Sent: Tuesday, April 27, 2004 10:32 PM
> > To: Windows System Software Devs Interest List
> > Subject: Re:[ntdev] Variable Number of Argument function in WDM
> >
> >
> >
> > “Ray Trent” wrote in message
> > news:xxxxx@ntdev…
> > >
> > > Use a debugger, and look at the return values of va_arg at each call
> > > when only 1 argument is passed.
> > >
> > > The first time, it’s ArgumentList_i,
> >
> > I haven’t used a debugger. If what you say is true then it
> > looks like there’s a major problem with the implementation.
> > The first call to va_arg should return the value of the
> > first unnamed parameter.
> >
> > > the second time it’s null,
> >
> > If only one unnamed parameter is passed, then a second call
> > to va_arg results in C’s ‘undefined behaviour’. At that
> > point all bets are off and anything can happen.
> >
> > > and the
> > > third time you call it, it’s completely undefined. It might be a
> > > reasonable value, it might not.
> > >
> > > That third call needs to be inside the if for the second one. (at
> > > least… I haven’t really thought much about how to design this
better,
> > > though I’m pretty sure it can be).
> >
> > The ‘variable arguments’ aspects of this code should be fine
> > as long as there is an odd number of unnamed parameters and
> > the last one is a PVOID with value NULL. If there is a single
> > unnamed parameter that’s a NULL PVOID, then the contents of
> > the while loop should never be executed.
> >
> > If the calls to this function meet these conditions but the
> > while loop doesn’t behave, then something else is screwing
> > things up.
> >
> > > J. J. Farrell wrote:
> > >
> > > > “SUJA JAMES” wrote in message
> > news:xxxxx@ntdev…
> > > >
> > > >>I have a variable list of argument function which copies
> > > >>all the specified buffer content into a single buffer.
> > > >>I am listing the source code of this function. In this
> > > >>function even if I pass a single variable in the variable
> > > >>argument list, while loop in this function is getting
> > > >>executed. I tested this code in User mode and is working
> > > >>fine.
> > > >
> > > >
> > > > It looks like this ought to work for any odd number of unnamed
> > > > arguments as long as the last argument is PVOID with value NULL.
> > > > Calling it with an even number of unnamed parameters, or with the
> > > > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> > > >
> > > > If you are meeting these conditions and seeing problems, I’d check
> > > > your copies to make sure you’re not corrupting yourself somewhere.
> > > >
> > > >
> > > >>STATUS
> > > >>PackOutputBuffer(
> > > >> PUCHAR puOutBuf_o, //output buffer to be filled
> > > >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> > > >>out buf
> > > >> PVOID ArgumentList_i, //variable list of arguments
> > > >>… //Variable number of arguments
> > > >>)
> > > >>{
> > > >>
> > > >>va_list valist;
> > > >>PVOID Argument = NULL;
> > > >>UINT32 u32OutStatus =0;
> > > >>UINT32 u32CurBuffPos = ZERO;
> > > >>UINT8 uArgLen = ZERO;
> > > >>UINT8 puArg = NULL;
> > > >>
> > > >> if ( NULL == ArgumentList_i )
> > > >>return INVALIDPARAM;
> > > >>
> > > >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> > > >>pu32NumBytes_o))
> > > >>return INVALIDPARAM;
> > > >>
> > > >>Argument = ArgumentList_i; //first argument
> > > >>
> > > >>//first element is always status with 4 bytes length
> > > >>u32OutStatus = *((PUINT32)Argument);
> > > >>RtlCopyMemory ((puOutBuf_o +
> > > >>u32CurBuffPos),&u32OutStatus,
> > > >>STATUS_SIZE);
> > > >>u32CurBuffPos += STATUS_SIZE;
> > > >>
> > > >>//Initialize variable arguments
> > > >>va_start(valist,ArgumentList_i);
> > > >>
> > > >>//go throught the list until no more aruguments
> > > >>Argument = va_arg( valist, PVOID);
> > > >>
> > > >>while( NULL != Argument )
> > > >>{
> > > >>// Now onwards first argument is length, next is
> > > >>buffer
> > > >> uArgLen = *((PUINT8)Argument);
> > > >> //get the buffer
> > > >> Argument = va_arg( valist, PVOID);
> > > >> if ( NULL != Argument)
> > > >> {
> > > >>//copy this to the output buffer
> > > >>RtlCopyMemory ((puOutBuf_o +
> > > >>u32CurBuffPos),Argument, uArgLen);
> > > >>u32CurBuffPos += uArgLen;
> > > >> }
> > > >> //get next one
> > > >>Argument = va_arg( valist, PVOID);
> > > >>} // end of while () completed the list
> > > >>
> > > >>//Reset variable arguments
> > > >>va_end( valist );
> > > >>//copy the number of bytes copied information
> > > >>*pu32NumBytes_o = u32CurBuffPos;
> > > >>}
> > > >>
> > > >> ***** When I invoke this function with only one
> > > >>argument in this
> > > >>varaibel argument list, that while loop is getting
> > > >>executed twice.
> > > >>WHY??? It is supposed to omit the while loop… But
> > > >>not…
> > > >>
> > > >>PackOutputBuffer(pu8OutBuf,
> > > >>&u32NumBytes,(PVOID)&u32BlstStatus );


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@compuware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

The contents of this e-mail are intended for the named addressee only. It
contains information that may be confidential. Unless you are the named
addressee or an authorized designee, you may not copy or use it, or disclose
it to anyone else. If you received it in error please notify us immediately
and then destroy it.</string.h>

The ISO C standard explicitly disallows the ‘zero or more’. You must
have one non-varying argument.

“Moreira, Alberto” wrote in message
news:xxxxx@ntdev…
>
> I thought it was clear, no ?

I think the original poster’s code, and yours, are both clear. They’re
almost identical, except his expects pairs of arguments. We appear to
be in violent agreement, though using slightly different terminology.

> He declares his function as
>
> STATUS PackOutputBuffer(
> PUCHAR puOutBuf_o,
> PUINT32 pu32NumBytes_o,
> PVOID ArgumentList_i,
> … )
>
> His code does this:
>
> Argument = ArgumentList_i; //first argument

Confusion seems to be arising from the OP describing the third argument
to his function (the last named argument, the argument before the first
unnamed argument) as the “first argument”.

> u32OutStatus = ((PUINT32)Argument);
> RtlCopyMemory ((puOutBuf_o + u32CurBuffPos),&u32OutStatus,STATUS_SIZE);
>
> Meaning, the first argument must be a pointer. Now he does a va_arg() to
get
> the second argument,

(that is, to get the first unnamed parameter)

> which is a length, and he tests it for NULL. Meaning,
> his argument list must be of the form
>
> pointer, length, pointer, length, pointer, length, …, …, pointer, 0
>
> because he tests every second element of his list for null.
>
> So, the minimum number of arguments to be passed is 2, not 1,

2 “arguments” (as defined by the OP rather than by C), 1 unnamed parameter.

> and he must pass parameters in pairs, never an odd number of them.

agreed - in other words he must always pass an odd number of unnamed
parameters, with the last of them being a NULL PVOID.

Though the list of arguments (in the OP’s sense) is not a simple list
of pairs - the first argument is the second half of a pair whose first
half is elided and its value assumed, and the last argument is the first
half of a pair whose second half isn’t needed. That is, it’s

pointer, {length, pointer}, {length, pointer}, {…}, NULL

> He calls his function this way:
>
> PackOutputBuffer(pu8OutBuf, &u32NumBytes, (PVOID)&u32BlstStatus );
>
> when he should rather call it this way:
>
> PackOutputBuffer(pu8OutBuf, &u32NumBytes, (PVOID)&u32BlstStatus, 0 );

That may be the case, and explains the problem if it is. However, that’s
not what he says he does. He says “I invoke this function with only one
argument in this varaibel argument list” which I assume means he invokes
it with the three fixed arguments plus the first variable one. The two
interesting cases are

PackOutputBuffer(pBuf, &count, &Status, (PVOID)NULL);

which should be fine, and

PackOutputBuffer(pBuf, &count, &Status, (PVOID)&x);

which gives undefined behaviour.

He might not have meant what he said, or he might have meant something
unusual by “variable argument list”. It would have saved a lot of
confusion if the OP had shown us exactly how he calls the function.

> I don’t know, I would declare a structure such as
>
> typedef struct { int len; char ptr; } myStruct;
>
> and pass a single list of structures to the function. If nothing else,
> provides for cleaner code.

Definitely. It would also give shorter and clearer code (with a
trivial loss of efficiency) if he didn’t special-case the first
“argument” by building in an assumed length for it.

> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> Sent: Wednesday, April 28, 2004 3:48 PM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] Variable Number of Argument function in WDM
>
>
> I confess I’m losing track of this discussion. I described what the OP’s
> code does. Why should he change it (unless he wants it to do something
> else)? Unless my eyesight or brain is failing, your handling of unnamed
> parameters is identical to his except that his expects pairs of unnamed
> parameters followed by a null pointer whereas yours expects singles.
>
> “Moreira, Alberto” wrote in message
> news:xxxxx@ntdev…
> > If the OP wants to pass zero or more parameters followed by a NULL
> pointer,
> > it’s simple enough to do it the way I suggest, which is the same way
shown
> > in Microsoft’s MSDN description of va_arg(). That is, define the
function
> as
> > follows:
> >
> > void myfunc(foo bar, char
parmList, …);
> > {
> > va_list vaList;
> > char
ptr = parmList;
> > va_start(vaList, parmList);
> > setupWhateverElseNeedsToBeSetUp();
> > while (ptr != NULL)
> > {
> > handleThisArg(ptr);
> > ptr=va_arg(valist,char*);
> > }
> > doWhateverElseIsNeeded();
> > }
> >
> > and he will be able to pass zero, one or more parameters as long as
> they’re
> > followed by a NULL.
> >
> >
> > Alberto.
> >
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> > Sent: Wednesday, April 28, 2004 3:02 PM
> > To: Windows System Software Devs Interest List
> > Subject: Re:[ntdev] Variable Number of Argument function in WDM
> >
> >
> > I think you’re making it seem more complicated than it is. It’s perhaps
> > easier to think in these terms: the call to va_start must specify the
> > last parameter that is explicitly declared (the last “named parameter”),
> > the first call to va_arg gives the first parameter that is not
explicitly
> > declared (the first “unnamed parameter”), subsequent calls to va_arg
> > retrieve subsequent unnamed parameters. There are ways to do fancier
> > things, but that’s the basics.
> >
> > The original poster’s code expects zero or more pairs of unnamed
> > parameters followed by a null pointer. If it gets that it should be
> > happy, unless he has problems elsewhere.
> >
> > This functionality is standard C - there’s nothing MS-specific here.
> >
> > “Moreira, Alberto” wrote in message
> > news:xxxxx@ntdev…
> > > Ok, I believe I found the reason why I always get the second parameter
> the
> > > first time I call va_arg(). The MSDN documentation states that
> va_start()
> > is
> > > called as follows:
> > >
> > > va_start(arg_ptr, prev_param)
> > >
> > > where “prev_param” is the parameter ONE BEFORE the first element of
the
> > list
> > > ! To quote the MSDN documentation,
> > >
> > > ====================================
> > > va_start sets arg_ptr to the first optional argument in the list of
> > > arguments passed to the function. The argument arg_ptr must have
va_list
> > > type. The argument prev_param is the name of the required parameter
> > > immediately preceding the first optional argument in the argument
list.
> If
> > > prev_param is declared with the register storage class, the macro’s
> > behavior
> > > is undefined. va_start must be used before va_arg is used for the
first
> > > time.
> > > ====================================
> > >
> > > So, if I call va_start(valist, myList), this is stating that myList is
> the
> > > “one before” parameter, therefore the first element I get when I call
> > > va_arg() is actually the SECOND argument in the list.
> > >
> > > Somehow I think the Unix way was more sensible, but hey, this is how
the
> > > ANSI standard works.
> > >
> > >
> > > Alberto.
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: xxxxx@lists.osr.com
> > > [mailto:xxxxx@lists.osr.com]On Behalf Of Moreira, Alberto
> > > Sent: Wednesday, April 28, 2004 11:24 AM
> > > To: Windows System Software Devs Interest List
> > > Subject: RE: [ntdev] Variable Number of Argument function in WDM
> > >
> > >
> > > I got it to work the following way. Note a few caveats:
> > >
> > > 1. The variable argument list passed to the procedure must have your
> own
> > > end marker. I use NULL.
> > > 2. The first call to va_arg() gives me the second argument. Don’t
> ask
> > me
> > > why.
> > > 3. To get the first argument, you just use an “arg=parameter” line.
> > >
> > > If you go to the MSDN Library and ask for va_arg, they have a source
> > program
> > > that explains it pretty decently. Hope this helps !
> > >
> > > Alberto.
> > >
> > > =============
> > >
> > > #include <string.h>
> > >
> > > void poBuffer(char *aList, …)
> > > {
> > > va_list valist;
> > > va_start(valist,aList);
> > > char arg = aList;
> > >
> > > int count=0;
> > >
> > > while (arg!=NULL)
> > > {
> > > printf(“%d. %s\n”, count, arg);
> > > arg = va_arg(valist,char
);
> > > count++;
> > > }
> > > }
> > >
> > >
> > > main()
> > > {
> > > char *p = “hello”;
> > > char *q = “there”;
> > > poBuffer(p, NULL);
> > > printf(“=====================\n”);
> > > poBuffer(p, q, NULL);
> > > return 0;
> > > }
> > >
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: xxxxx@lists.osr.com
> > > [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> > > Sent: Tuesday, April 27, 2004 10:32 PM
> > > To: Windows System Software Devs Interest List
> > > Subject: Re:[ntdev] Variable Number of Argument function in WDM
> > >
> > >
> > >
> > > “Ray Trent” wrote in message
> > > news:xxxxx@ntdev…
> > > >
> > > > Use a debugger, and look at the return values of va_arg at each call
> > > > when only 1 argument is passed.
> > > >
> > > > The first time, it’s ArgumentList_i,
> > >
> > > I haven’t used a debugger. If what you say is true then it
> > > looks like there’s a major problem with the implementation.
> > > The first call to va_arg should return the value of the
> > > first unnamed parameter.
> > >
> > > > the second time it’s null,
> > >
> > > If only one unnamed parameter is passed, then a second call
> > > to va_arg results in C’s ‘undefined behaviour’. At that
> > > point all bets are off and anything can happen.
> > >
> > > > and the
> > > > third time you call it, it’s completely undefined. It might be a
> > > > reasonable value, it might not.
> > > >
> > > > That third call needs to be inside the if for the second one. (at
> > > > least… I haven’t really thought much about how to design this
> better,
> > > > though I’m pretty sure it can be).
> > >
> > > The ‘variable arguments’ aspects of this code should be fine
> > > as long as there is an odd number of unnamed parameters and
> > > the last one is a PVOID with value NULL. If there is a single
> > > unnamed parameter that’s a NULL PVOID, then the contents of
> > > the while loop should never be executed.
> > >
> > > If the calls to this function meet these conditions but the
> > > while loop doesn’t behave, then something else is screwing
> > > things up.
> > >
> > > > J. J. Farrell wrote:
> > > >
> > > > > “SUJA JAMES” wrote in message
> > > news:xxxxx@ntdev…
> > > > >
> > > > >>I have a variable list of argument function which copies
> > > > >>all the specified buffer content into a single buffer.
> > > > >>I am listing the source code of this function. In this
> > > > >>function even if I pass a single variable in the variable
> > > > >>argument list, while loop in this function is getting
> > > > >>executed. I tested this code in User mode and is working
> > > > >>fine.
> > > > >
> > > > >
> > > > > It looks like this ought to work for any odd number of unnamed
> > > > > arguments as long as the last argument is PVOID with value NULL.
> > > > > Calling it with an even number of unnamed parameters, or with the
> > > > > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> > > > >
> > > > > If you are meeting these conditions and seeing problems, I’d check
> > > > > your copies to make sure you’re not corrupting yourself somewhere.
> > > > >
> > > > >
> > > > >>STATUS
> > > > >>PackOutputBuffer(
> > > > >> PUCHAR puOutBuf_o, //output buffer to be filled
> > > > >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> > > > >>out buf
> > > > >> PVOID ArgumentList_i, //variable list of arguments
> > > > >>… //Variable number of arguments
> > > > >>)
> > > > >>{
> > > > >>
> > > > >>va_list valist;
> > > > >>PVOID Argument = NULL;
> > > > >>UINT32 u32OutStatus =0;
> > > > >>UINT32 u32CurBuffPos = ZERO;
> > > > >>UINT8 uArgLen = ZERO;
> > > > >>UINT8 puArg = NULL;
> > > > >>
> > > > >> if ( NULL == ArgumentList_i )
> > > > >>return INVALIDPARAM;
> > > > >>
> > > > >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> > > > >>pu32NumBytes_o))
> > > > >>return INVALIDPARAM;
> > > > >>
> > > > >>Argument = ArgumentList_i; //first argument
> > > > >>
> > > > >>//first element is always status with 4 bytes length
> > > > >>u32OutStatus = *((PUINT32)Argument);
> > > > >>RtlCopyMemory ((puOutBuf_o +
> > > > >>u32CurBuffPos),&u32OutStatus,
> > > > >>STATUS_SIZE);
> > > > >>u32CurBuffPos += STATUS_SIZE;
> > > > >>
> > > > >>//Initialize variable arguments
> > > > >>va_start(valist,ArgumentList_i);
> > > > >>
> > > > >>//go throught the list until no more aruguments
> > > > >>Argument = va_arg( valist, PVOID);
> > > > >>
> > > > >>while( NULL != Argument )
> > > > >>{
> > > > >>// Now onwards first argument is length, next is
> > > > >>buffer
> > > > >> uArgLen = *((PUINT8)Argument);
> > > > >> //get the buffer
> > > > >> Argument = va_arg( valist, PVOID);
> > > > >> if ( NULL != Argument)
> > > > >> {
> > > > >>//copy this to the output buffer
> > > > >>RtlCopyMemory ((puOutBuf_o +
> > > > >>u32CurBuffPos),Argument, uArgLen);
> > > > >>u32CurBuffPos += uArgLen;
> > > > >> }
> > > > >> //get next one
> > > > >>Argument = va_arg( valist, PVOID);
> > > > >>} // end of while () completed the list
> > > > >>
> > > > >>//Reset variable arguments
> > > > >>va_end( valist );
> > > > >>//copy the number of bytes copied information
> > > > >>*pu32NumBytes_o = u32CurBuffPos;
> > > > >>}
> > > > >>
> > > > >> ***** When I invoke this function with only one
> > > > >>argument in this
> > > > >>varaibel argument list, that while loop is getting
> > > > >>executed twice.
> > > > >>WHY??? It is supposed to omit the while loop… But
> > > > >>not…
> > > > >>
> > > > >>PackOutputBuffer(pu8OutBuf,
> > > > >>&u32NumBytes,(PVOID)&u32BlstStatus );</string.h>

Yup… I believe now we totally agree.

Alberto.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
Sent: Wednesday, April 28, 2004 9:04 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Variable Number of Argument function in WDM

“Moreira, Alberto” wrote in message
news:xxxxx@ntdev…
>
> I thought it was clear, no ?

I think the original poster’s code, and yours, are both clear. They’re
almost identical, except his expects pairs of arguments. We appear to
be in violent agreement, though using slightly different terminology.

> He declares his function as
>
> STATUS PackOutputBuffer(
> PUCHAR puOutBuf_o,
> PUINT32 pu32NumBytes_o,
> PVOID ArgumentList_i,
> … )
>
> His code does this:
>
> Argument = ArgumentList_i; //first argument

Confusion seems to be arising from the OP describing the third argument
to his function (the last named argument, the argument before the first
unnamed argument) as the “first argument”.

> u32OutStatus = ((PUINT32)Argument);
> RtlCopyMemory ((puOutBuf_o + u32CurBuffPos),&u32OutStatus,STATUS_SIZE);
>
> Meaning, the first argument must be a pointer. Now he does a va_arg() to
get
> the second argument,

(that is, to get the first unnamed parameter)

> which is a length, and he tests it for NULL. Meaning,
> his argument list must be of the form
>
> pointer, length, pointer, length, pointer, length, …, …, pointer, 0
>
> because he tests every second element of his list for null.
>
> So, the minimum number of arguments to be passed is 2, not 1,

2 “arguments” (as defined by the OP rather than by C), 1 unnamed parameter.

> and he must pass parameters in pairs, never an odd number of them.

agreed - in other words he must always pass an odd number of unnamed
parameters, with the last of them being a NULL PVOID.

Though the list of arguments (in the OP’s sense) is not a simple list
of pairs - the first argument is the second half of a pair whose first
half is elided and its value assumed, and the last argument is the first
half of a pair whose second half isn’t needed. That is, it’s

pointer, {length, pointer}, {length, pointer}, {…}, NULL

> He calls his function this way:
>
> PackOutputBuffer(pu8OutBuf, &u32NumBytes, (PVOID)&u32BlstStatus );
>
> when he should rather call it this way:
>
> PackOutputBuffer(pu8OutBuf, &u32NumBytes, (PVOID)&u32BlstStatus, 0 );

That may be the case, and explains the problem if it is. However, that’s
not what he says he does. He says “I invoke this function with only one
argument in this varaibel argument list” which I assume means he invokes
it with the three fixed arguments plus the first variable one. The two
interesting cases are

PackOutputBuffer(pBuf, &count, &Status, (PVOID)NULL);

which should be fine, and

PackOutputBuffer(pBuf, &count, &Status, (PVOID)&x);

which gives undefined behaviour.

He might not have meant what he said, or he might have meant something
unusual by “variable argument list”. It would have saved a lot of
confusion if the OP had shown us exactly how he calls the function.

> I don’t know, I would declare a structure such as
>
> typedef struct { int len; char ptr; } myStruct;
>
> and pass a single list of structures to the function. If nothing else,
> provides for cleaner code.

Definitely. It would also give shorter and clearer code (with a
trivial loss of efficiency) if he didn’t special-case the first
“argument” by building in an assumed length for it.

> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> Sent: Wednesday, April 28, 2004 3:48 PM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] Variable Number of Argument function in WDM
>
>
> I confess I’m losing track of this discussion. I described what the OP’s
> code does. Why should he change it (unless he wants it to do something
> else)? Unless my eyesight or brain is failing, your handling of unnamed
> parameters is identical to his except that his expects pairs of unnamed
> parameters followed by a null pointer whereas yours expects singles.
>
> “Moreira, Alberto” wrote in message
> news:xxxxx@ntdev…
> > If the OP wants to pass zero or more parameters followed by a NULL
> pointer,
> > it’s simple enough to do it the way I suggest, which is the same way
shown
> > in Microsoft’s MSDN description of va_arg(). That is, define the
function
> as
> > follows:
> >
> > void myfunc(foo bar, char
parmList, …);
> > {
> > va_list vaList;
> > char
ptr = parmList;
> > va_start(vaList, parmList);
> > setupWhateverElseNeedsToBeSetUp();
> > while (ptr != NULL)
> > {
> > handleThisArg(ptr);
> > ptr=va_arg(valist,char*);
> > }
> > doWhateverElseIsNeeded();
> > }
> >
> > and he will be able to pass zero, one or more parameters as long as
> they’re
> > followed by a NULL.
> >
> >
> > Alberto.
> >
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> > Sent: Wednesday, April 28, 2004 3:02 PM
> > To: Windows System Software Devs Interest List
> > Subject: Re:[ntdev] Variable Number of Argument function in WDM
> >
> >
> > I think you’re making it seem more complicated than it is. It’s perhaps
> > easier to think in these terms: the call to va_start must specify the
> > last parameter that is explicitly declared (the last “named parameter”),
> > the first call to va_arg gives the first parameter that is not
explicitly
> > declared (the first “unnamed parameter”), subsequent calls to va_arg
> > retrieve subsequent unnamed parameters. There are ways to do fancier
> > things, but that’s the basics.
> >
> > The original poster’s code expects zero or more pairs of unnamed
> > parameters followed by a null pointer. If it gets that it should be
> > happy, unless he has problems elsewhere.
> >
> > This functionality is standard C - there’s nothing MS-specific here.
> >
> > “Moreira, Alberto” wrote in message
> > news:xxxxx@ntdev…
> > > Ok, I believe I found the reason why I always get the second parameter
> the
> > > first time I call va_arg(). The MSDN documentation states that
> va_start()
> > is
> > > called as follows:
> > >
> > > va_start(arg_ptr, prev_param)
> > >
> > > where “prev_param” is the parameter ONE BEFORE the first element of
the
> > list
> > > ! To quote the MSDN documentation,
> > >
> > > ====================================
> > > va_start sets arg_ptr to the first optional argument in the list of
> > > arguments passed to the function. The argument arg_ptr must have
va_list
> > > type. The argument prev_param is the name of the required parameter
> > > immediately preceding the first optional argument in the argument
list.
> If
> > > prev_param is declared with the register storage class, the macro’s
> > behavior
> > > is undefined. va_start must be used before va_arg is used for the
first
> > > time.
> > > ====================================
> > >
> > > So, if I call va_start(valist, myList), this is stating that myList is
> the
> > > “one before” parameter, therefore the first element I get when I call
> > > va_arg() is actually the SECOND argument in the list.
> > >
> > > Somehow I think the Unix way was more sensible, but hey, this is how
the
> > > ANSI standard works.
> > >
> > >
> > > Alberto.
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: xxxxx@lists.osr.com
> > > [mailto:xxxxx@lists.osr.com]On Behalf Of Moreira, Alberto
> > > Sent: Wednesday, April 28, 2004 11:24 AM
> > > To: Windows System Software Devs Interest List
> > > Subject: RE: [ntdev] Variable Number of Argument function in WDM
> > >
> > >
> > > I got it to work the following way. Note a few caveats:
> > >
> > > 1. The variable argument list passed to the procedure must have your
> own
> > > end marker. I use NULL.
> > > 2. The first call to va_arg() gives me the second argument. Don’t
> ask
> > me
> > > why.
> > > 3. To get the first argument, you just use an “arg=parameter” line.
> > >
> > > If you go to the MSDN Library and ask for va_arg, they have a source
> > program
> > > that explains it pretty decently. Hope this helps !
> > >
> > > Alberto.
> > >
> > > =============
> > >
> > > #include <string.h>
> > >
> > > void poBuffer(char *aList, …)
> > > {
> > > va_list valist;
> > > va_start(valist,aList);
> > > char arg = aList;
> > >
> > > int count=0;
> > >
> > > while (arg!=NULL)
> > > {
> > > printf(“%d. %s\n”, count, arg);
> > > arg = va_arg(valist,char
);
> > > count++;
> > > }
> > > }
> > >
> > >
> > > main()
> > > {
> > > char *p = “hello”;
> > > char *q = “there”;
> > > poBuffer(p, NULL);
> > > printf(“=====================\n”);
> > > poBuffer(p, q, NULL);
> > > return 0;
> > > }
> > >
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: xxxxx@lists.osr.com
> > > [mailto:xxxxx@lists.osr.com]On Behalf Of J. J. Farrell
> > > Sent: Tuesday, April 27, 2004 10:32 PM
> > > To: Windows System Software Devs Interest List
> > > Subject: Re:[ntdev] Variable Number of Argument function in WDM
> > >
> > >
> > >
> > > “Ray Trent” wrote in message
> > > news:xxxxx@ntdev…
> > > >
> > > > Use a debugger, and look at the return values of va_arg at each call
> > > > when only 1 argument is passed.
> > > >
> > > > The first time, it’s ArgumentList_i,
> > >
> > > I haven’t used a debugger. If what you say is true then it
> > > looks like there’s a major problem with the implementation.
> > > The first call to va_arg should return the value of the
> > > first unnamed parameter.
> > >
> > > > the second time it’s null,
> > >
> > > If only one unnamed parameter is passed, then a second call
> > > to va_arg results in C’s ‘undefined behaviour’. At that
> > > point all bets are off and anything can happen.
> > >
> > > > and the
> > > > third time you call it, it’s completely undefined. It might be a
> > > > reasonable value, it might not.
> > > >
> > > > That third call needs to be inside the if for the second one. (at
> > > > least… I haven’t really thought much about how to design this
> better,
> > > > though I’m pretty sure it can be).
> > >
> > > The ‘variable arguments’ aspects of this code should be fine
> > > as long as there is an odd number of unnamed parameters and
> > > the last one is a PVOID with value NULL. If there is a single
> > > unnamed parameter that’s a NULL PVOID, then the contents of
> > > the while loop should never be executed.
> > >
> > > If the calls to this function meet these conditions but the
> > > while loop doesn’t behave, then something else is screwing
> > > things up.
> > >
> > > > J. J. Farrell wrote:
> > > >
> > > > > “SUJA JAMES” wrote in message
> > > news:xxxxx@ntdev…
> > > > >
> > > > >>I have a variable list of argument function which copies
> > > > >>all the specified buffer content into a single buffer.
> > > > >>I am listing the source code of this function. In this
> > > > >>function even if I pass a single variable in the variable
> > > > >>argument list, while loop in this function is getting
> > > > >>executed. I tested this code in User mode and is working
> > > > >>fine.
> > > > >
> > > > >
> > > > > It looks like this ought to work for any odd number of unnamed
> > > > > arguments as long as the last argument is PVOID with value NULL.
> > > > > Calling it with an even number of unnamed parameters, or with the
> > > > > last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> > > > >
> > > > > If you are meeting these conditions and seeing problems, I’d check
> > > > > your copies to make sure you’re not corrupting yourself somewhere.
> > > > >
> > > > >
> > > > >>STATUS
> > > > >>PackOutputBuffer(
> > > > >> PUCHAR puOutBuf_o, //output buffer to be filled
> > > > >> PUINT32 pu32NumBytes_o, //Number of bytes copied in
> > > > >>out buf
> > > > >> PVOID ArgumentList_i, //variable list of arguments
> > > > >>… //Variable number of arguments
> > > > >>)
> > > > >>{
> > > > >>
> > > > >>va_list valist;
> > > > >>PVOID Argument = NULL;
> > > > >>UINT32 u32OutStatus =0;
> > > > >>UINT32 u32CurBuffPos = ZERO;
> > > > >>UINT8 uArgLen = ZERO;
> > > > >>UINT8 puArg = NULL;
> > > > >>
> > > > >> if ( NULL == ArgumentList_i )
> > > > >>return INVALIDPARAM;
> > > > >>
> > > > >>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> > > > >>pu32NumBytes_o))
> > > > >>return INVALIDPARAM;
> > > > >>
> > > > >>Argument = ArgumentList_i; //first argument
> > > > >>
> > > > >>//first element is always status with 4 bytes length
> > > > >>u32OutStatus = *((PUINT32)Argument);
> > > > >>RtlCopyMemory ((puOutBuf_o +
> > > > >>u32CurBuffPos),&u32OutStatus,
> > > > >>STATUS_SIZE);
> > > > >>u32CurBuffPos += STATUS_SIZE;
> > > > >>
> > > > >>//Initialize variable arguments
> > > > >>va_start(valist,ArgumentList_i);
> > > > >>
> > > > >>//go throught the list until no more aruguments
> > > > >>Argument = va_arg( valist, PVOID);
> > > > >>
> > > > >>while( NULL != Argument )
> > > > >>{
> > > > >>// Now onwards first argument is length, next is
> > > > >>buffer
> > > > >> uArgLen = *((PUINT8)Argument);
> > > > >> //get the buffer
> > > > >> Argument = va_arg( valist, PVOID);
> > > > >> if ( NULL != Argument)
> > > > >> {
> > > > >>//copy this to the output buffer
> > > > >>RtlCopyMemory ((puOutBuf_o +
> > > > >>u32CurBuffPos),Argument, uArgLen);
> > > > >>u32CurBuffPos += uArgLen;
> > > > >> }
> > > > >> //get next one
> > > > >>Argument = va_arg( valist, PVOID);
> > > > >>} // end of while () completed the list
> > > > >>
> > > > >>//Reset variable arguments
> > > > >>va_end( valist );
> > > > >>//copy the number of bytes copied information
> > > > >>*pu32NumBytes_o = u32CurBuffPos;
> > > > >>}
> > > > >>
> > > > >> ***** When I invoke this function with only one
> > > > >>argument in this
> > > > >>varaibel argument list, that while loop is getting
> > > > >>executed twice.
> > > > >>WHY??? It is supposed to omit the while loop… But
> > > > >>not…
> > > > >>
> > > > >>PackOutputBuffer(pu8OutBuf,
> > > > >>&u32NumBytes,(PVOID)&u32BlstStatus );


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@compuware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

The contents of this e-mail are intended for the named addressee only. It
contains information that may be confidential. Unless you are the named
addressee or an authorized designee, you may not copy or use it, or disclose
it to anyone else. If you received it in error please notify us immediately
and then destroy it.</string.h>

Sorry, braino. I didn’t use a debugger either :-). Some days it just
doesn’t pay to get out of bed…

Anyway, I just looked again, and the fundamental problem is that he’s
actually passing *zero* variable arguments, which isn’t allowed. His
very first call to va_arg is going to return an undefined result the way
he shows the function being called at the bottom of his posting…

J. J. Farrell wrote:

“Ray Trent” wrote in message
> news:xxxxx@ntdev…
>
>>Use a debugger, and look at the return values of va_arg at each call
>>when only 1 argument is passed.
>>
>>The first time, it’s ArgumentList_i,
>
>
> I haven’t used a debugger. If what you say is true then it
> looks like there’s a major problem with the implementation.
> The first call to va_arg should return the value of the
> first unnamed parameter.
>
>
>>the second time it’s null,
>
>
> If only one unnamed parameter is passed, then a second call
> to va_arg results in C’s ‘undefined behaviour’. At that
> point all bets are off and anything can happen.
>
>
>>and the
>>third time you call it, it’s completely undefined. It might be a
>>reasonable value, it might not.
>>
>>That third call needs to be inside the if for the second one. (at
>>least… I haven’t really thought much about how to design this better,
>>though I’m pretty sure it can be).
>
>
> The ‘variable arguments’ aspects of this code should be fine
> as long as there is an odd number of unnamed parameters and
> the last one is a PVOID with value NULL. If there is a single
> unnamed parameter that’s a NULL PVOID, then the contents of
> the while loop should never be executed.
>
> If the calls to this function meet these conditions but the
> while loop doesn’t behave, then something else is screwing
> things up.
>
>
>>J. J. Farrell wrote:
>>
>>
>>>“SUJA JAMES” wrote in message
>
> news:xxxxx@ntdev…
>
>>>>I have a variable list of argument function which copies
>>>>all the specified buffer content into a single buffer.
>>>>I am listing the source code of this function. In this
>>>>function even if I pass a single variable in the variable
>>>>argument list, while loop in this function is getting
>>>>executed. I tested this code in User mode and is working
>>>>fine.
>>>
>>>
>>>It looks like this ought to work for any odd number of unnamed
>>>arguments as long as the last argument is PVOID with value NULL.
>>>Calling it with an even number of unnamed parameters, or with the
>>>last one not a NULL PVOID, results in C’s ‘undefined behavior’.
>>>
>>>If you are meeting these conditions and seeing problems, I’d check
>>>your copies to make sure you’re not corrupting yourself somewhere.
>>>
>>>
>>>
>>>>STATUS
>>>>PackOutputBuffer(
>>>>PUCHAR puOutBuf_o, //output buffer to be filled
>>>>PUINT32 pu32NumBytes_o, //Number of bytes copied in
>>>>out buf
>>>>PVOID ArgumentList_i, //variable list of arguments
>>>>… //Variable number of arguments
>>>>)
>>>>{
>>>>
>>>>va_list valist;
>>>>PVOID Argument = NULL;
>>>>UINT32 u32OutStatus =0;
>>>>UINT32 u32CurBuffPos = ZERO;
>>>>UINT8 uArgLen = ZERO;
>>>>UINT8 puArg = NULL;
>>>>
>>>> if ( NULL == ArgumentList_i )
>>>>return INVALIDPARAM;
>>>>
>>>>if ( ( NULL == puOutBuf_o ) || ( NULL ==
>>>>pu32NumBytes_o))
>>>>return INVALIDPARAM;
>>>>
>>>>Argument = ArgumentList_i; //first argument
>>>>
>>>>//first element is always status with 4 bytes length
>>>>u32OutStatus = *((PUINT32)Argument);
>>>>RtlCopyMemory ((puOutBuf_o +
>>>>u32CurBuffPos),&u32OutStatus,
>>>>STATUS_SIZE);
>>>>u32CurBuffPos += STATUS_SIZE;
>>>>
>>>>//Initialize variable arguments
>>>>va_start(valist,ArgumentList_i);
>>>>
>>>>//go throught the list until no more aruguments
>>>>Argument = va_arg( valist, PVOID);
>>>>
>>>>while( NULL != Argument )
>>>>{
>>>>// Now onwards first argument is length, next is
>>>>buffer
>>>> uArgLen = *((PUINT8)Argument);
>>>> //get the buffer
>>>> Argument = va_arg( valist, PVOID);
>>>> if ( NULL != Argument)
>>>> {
>>>>//copy this to the output buffer
>>>>RtlCopyMemory ((puOutBuf_o +
>>>>u32CurBuffPos),Argument, uArgLen);
>>>>u32CurBuffPos += uArgLen;
>>>> }
>>>> //get next one
>>>>Argument = va_arg( valist, PVOID);
>>>>} // end of while () completed the list
>>>>
>>>>//Reset variable arguments
>>>>va_end( valist );
>>>>//copy the number of bytes copied information
>>>>*pu32NumBytes_o = u32CurBuffPos;
>>>>}
>>>>
>>>> ***** When I invoke this function with only one
>>>>argument in this
>>>>varaibel argument list, that while loop is getting
>>>>executed twice.
>>>>WHY??? It is supposed to omit the while loop… But
>>>>not…
>>>>
>>>>PackOutputBuffer(pu8OutBuf,
>>>>&u32NumBytes,(PVOID)&u32BlstStatus );
>
>
>


…/ray..

Please remove “.spamblock” from my email address if you need to contact
me outside the newgroup.

“Ray Trent” wrote in message
news:xxxxx@ntdev…
> Sorry, braino. I didn’t use a debugger either :-). Some days it just
> doesn’t pay to get out of bed…
>
> Anyway, I just looked again, and the fundamental problem is that he’s
> actually passing zero variable arguments, which isn’t allowed. His
> very first call to va_arg is going to return an undefined result the way
> he shows the function being called at the bottom of his posting…

Oh, man … Thanks Ray - I’d seen the bit of code at the bottom of
his posting, but assumed it was some editorial error. I hadn’t
realised that it was an example of how he calls the function, and
it makes his error crystal clear. My apologies to the OP for
complaining about his not giving an example of how he called it …

> J. J. Farrell wrote:
>
> > “Ray Trent” wrote in message
> > news:xxxxx@ntdev…
> >
> >>Use a debugger, and look at the return values of va_arg at each call
> >>when only 1 argument is passed.
> >>
> >>The first time, it’s ArgumentList_i,
> >
> >
> > I haven’t used a debugger. If what you say is true then it
> > looks like there’s a major problem with the implementation.
> > The first call to va_arg should return the value of the
> > first unnamed parameter.
> >
> >
> >>the second time it’s null,
> >
> >
> > If only one unnamed parameter is passed, then a second call
> > to va_arg results in C’s ‘undefined behaviour’. At that
> > point all bets are off and anything can happen.
> >
> >
> >>and the
> >>third time you call it, it’s completely undefined. It might be a
> >>reasonable value, it might not.
> >>
> >>That third call needs to be inside the if for the second one. (at
> >>least… I haven’t really thought much about how to design this better,
> >>though I’m pretty sure it can be).
> >
> >
> > The ‘variable arguments’ aspects of this code should be fine
> > as long as there is an odd number of unnamed parameters and
> > the last one is a PVOID with value NULL. If there is a single
> > unnamed parameter that’s a NULL PVOID, then the contents of
> > the while loop should never be executed.
> >
> > If the calls to this function meet these conditions but the
> > while loop doesn’t behave, then something else is screwing
> > things up.
> >
> >
> >>J. J. Farrell wrote:
> >>
> >>
> >>>“SUJA JAMES” wrote in message
> >
> > news:xxxxx@ntdev…
> >
> >>>>I have a variable list of argument function which copies
> >>>>all the specified buffer content into a single buffer.
> >>>>I am listing the source code of this function. In this
> >>>>function even if I pass a single variable in the variable
> >>>>argument list, while loop in this function is getting
> >>>>executed. I tested this code in User mode and is working
> >>>>fine.
> >>>
> >>>
> >>>It looks like this ought to work for any odd number of unnamed
> >>>arguments as long as the last argument is PVOID with value NULL.
> >>>Calling it with an even number of unnamed parameters, or with the
> >>>last one not a NULL PVOID, results in C’s ‘undefined behavior’.
> >>>
> >>>If you are meeting these conditions and seeing problems, I’d check
> >>>your copies to make sure you’re not corrupting yourself somewhere.
> >>>
> >>>
> >>>
> >>>>STATUS
> >>>>PackOutputBuffer(
> >>>>PUCHAR puOutBuf_o, //output buffer to be filled
> >>>>PUINT32 pu32NumBytes_o, //Number of bytes copied in
> >>>>out buf
> >>>>PVOID ArgumentList_i, //variable list of arguments
> >>>>… //Variable number of arguments
> >>>>)
> >>>>{
> >>>>
> >>>>va_list valist;
> >>>>PVOID Argument = NULL;
> >>>>UINT32 u32OutStatus =0;
> >>>>UINT32 u32CurBuffPos = ZERO;
> >>>>UINT8 uArgLen = ZERO;
> >>>>UINT8 puArg = NULL;
> >>>>
> >>>> if ( NULL == ArgumentList_i )
> >>>>return INVALIDPARAM;
> >>>>
> >>>>if ( ( NULL == puOutBuf_o ) || ( NULL ==
> >>>>pu32NumBytes_o))
> >>>>return INVALIDPARAM;
> >>>>
> >>>>Argument = ArgumentList_i; //first argument
> >>>>
> >>>>//first element is always status with 4 bytes length
> >>>>u32OutStatus = *((PUINT32)Argument);
> >>>>RtlCopyMemory ((puOutBuf_o +
> >>>>u32CurBuffPos),&u32OutStatus,
> >>>>STATUS_SIZE);
> >>>>u32CurBuffPos += STATUS_SIZE;
> >>>>
> >>>>//Initialize variable arguments
> >>>>va_start(valist,ArgumentList_i);
> >>>>
> >>>>//go throught the list until no more aruguments
> >>>>Argument = va_arg( valist, PVOID);
> >>>>
> >>>>while( NULL != Argument )
> >>>>{
> >>>>// Now onwards first argument is length, next is
> >>>>buffer
> >>>> uArgLen = *((PUINT8)Argument);
> >>>> //get the buffer
> >>>> Argument = va_arg( valist, PVOID);
> >>>> if ( NULL != Argument)
> >>>> {
> >>>>//copy this to the output buffer
> >>>>RtlCopyMemory ((puOutBuf_o +
> >>>>u32CurBuffPos),Argument, uArgLen);
> >>>>u32CurBuffPos += uArgLen;
> >>>> }
> >>>> //get next one
> >>>>Argument = va_arg( valist, PVOID);
> >>>>} // end of while () completed the list
> >>>>
> >>>>//Reset variable arguments
> >>>>va_end( valist );
> >>>>//copy the number of bytes copied information
> >>>>*pu32NumBytes_o = u32CurBuffPos;
> >>>>}
> >>>>
> >>>> ***** When I invoke this function with only one
> >>>>argument in this
> >>>>varaibel argument list, that while loop is getting
> >>>>executed twice.
> >>>>WHY??? It is supposed to omit the while loop… But
> >>>>not…
> >>>>
> >>>>PackOutputBuffer(pu8OutBuf,
> >>>>&u32NumBytes,(PVOID)&u32BlstStatus );