2

This is a block of sample C++ code. I read the definitions of typedef, struct, enum and union but I still can't decipher this.

typedef NTSTATUS (WINAPI * PFN_NTQUERYINFORMATIONFILE)(
    IN HANDLE FileHandle,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    OUT PVOID FileInformation,
    IN ULONG Length,
    IN FILE_INFORMATION_CLASS FileInformationClass
);
  1. Is NTSTATUS (WINAPI * PFN_NTQUERYINFORMATIONFILE) a function? Why does the parameter mean by having a * in between?
  2. IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock.. What does the IN/OUT mean?
  3. Why isn't there a new alias?
  4. Can I declare a new alias name and a pointer alias name? In the example below, would I use PFILE_NAME_INFORMATION for the pointer name and FILE_NAME_INFORMATION otherwise?

    typedef struct _FILE_NAME_INFORMATION { ... } 
    FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
    
transcend3nt
  • 101
  • 1
  • 4
  • additional whitespace, macros, ... do you have an IDE? – Karoly Horvath Oct 31 '15 at 18:18
  • First let me say `_FILE_NAME_INFORMATION` is a reserved identifier: You can't legally use it. Second, `IN` and `OUT` are not C++ keywords so I'm *guessing* they're just `#define`s to nothing and used only as annotation. – Mark B Oct 31 '15 at 18:19
  • In your last question, 4., are you really asking about `struct`s or is this just an analogy and you're actually asking about function pointers? – cadaniluk Oct 31 '15 at 18:49

3 Answers3

1

This typedef declaration

typedef NTSTATUS (WINAPI * PFN_NTQUERYINFORMATIONFILE)(
    IN HANDLE FileHandle,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    OUT PVOID FileInformation,
    IN ULONG Length,
    IN FILE_INFORMATION_CLASS FileInformationClass
);

introduces an alias namedPFN_NTQUERYINFORMATIONFILE` for the type

NTSTATUS (WINAPI * )(
    IN HANDLE FileHandle,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    OUT PVOID FileInformation,
    IN ULONG Length,
    IN FILE_INFORMATION_CLASS FileInformationClass
);

that represents a pointer to function with 5 parameters and the return type NTSTATUS.

Now you may use this name to declare pointers to functions of such a type

PFN_NTQUERYINFORMATIONFILE ptr;

You could get the same the following way that looks more clear

using PFN_NTQUERYINFORMATIONFILE =  
    NTSTATUS (WINAPI * )(
        IN HANDLE FileHandle,
        OUT PIO_STATUS_BLOCK IoStatusBlock,
        OUT PVOID FileInformation,
        IN ULONG Length,
        IN FILE_INFORMATION_CLASS FileInformationClass
    );

Also consider the following simple example

#include <iostream>

int sum( int x, int y )
{
    return x + y;
}

int product( int x, int y )
{
    return x * y;
}

int division( int x, int y )
{
    return x / y;
}

typedef int ( *fp )( int, int );

int main( )
{
    for ( fp f : { sum, product, division } ) std::cout << f( 10, 2 ) << std::endl;
}

The output is

12
20
5

Take into account that function names implicitly are converted to pointers to functions when they are used in expressions.

So for example this statement with the function from the above demonstrative program is valid

std::cout << ( ***/* replace the comment with as many asterisks as you like */****sum )( 10, 20 ) << std::endl;

So if you are paid accordingly to the number of typed symbols in the program then you can use this trick with function calls.

(****************************************************sum )( 10, 20 );

This is restricted only by the compiler limits.

As for IN and OUT then they are macros used by Microsoft to make it clear what each parameter of a function is used for, whether it provides an input value or it serves as an output parameter.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

This is a type alias for a function pointer.

Is NTSTATUS (WINAPI * PFN_NTQUERYINFORMATIONFILE) a function? Why does the parameter mean by having a * in between?

No, this is only part of the type. * denotes a pointer. This is a pointer to a function with a WINAPI (__stdcall) calling convention, an NTSTATUS return value, and several parameters (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, and FILE_INFORMATION_CLASS).

IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock.. What does the IN/OUT mean?

Those are annotations. IN means that the function uses the parameter for input only and OUT means the function uses the parameter for output only (it writes to what the parameter points to). INOUT would mean the function reads from and writes to what is being pointed to.

Neil MacIntosh actually gave a couple of presentations on static analysis at CppCon this year, where he talked about how such annotations came to be in the Microsoft codebase and how they help to improve static analysis tools' capabilities without requiring more resources. However, you can provide the same help with actual types instead of annotations that get compiled into nothing, and this is the approach that the CppCoreGuidelines project with the GSL is taking.

Why isn't there a new alias?

There is. It's PFN_NTQUERYINFORMATIONFILE. This is just a quirk of the C declaration syntax, which, for the most part, reads from the inside outward rather than left to right.

Can I declare a new alias name and a pointer alias name?

Not that I know of, no. Had you done the same trick with typedef NTSTATUS(WINAPI func)(...), *func_pointer;, func_pointer would be a NTSTATUS* while func is the same as in the question, but not a pointer.

This certainly works for other type aliases produced through typedef, though, such as the struct example in the question, which does indeed declare FILE_NAME_INFORMATION as a struct _FILE_NAME_INFORMATION and PFILE_NAME_INFORMATION as a struct _FILE_NAME_INFORMATION*, the struct being there to emphasize the different kinds of names being declared.

chris
  • 60,560
  • 13
  • 143
  • 205
0
  1. No, it's a function pointer. The asterisk in between is just part of the normal syntax for a function pointer - the WINAPI is just a macro.

  2. Macros too. IN indicates an argument read by the function (like a const reference or a copied-by-value argument) while OUT refers to an argument used to "return" an argument (like a non-const reference).

  3. There is one: PFN_NTQUERYINFORMATIONFILE.

  4. Yes.

Community
  • 1
  • 1
cadaniluk
  • 15,027
  • 2
  • 39
  • 67
  • I don't think that's what the OP is asking about with #4. I believe the question is whether there's a way to declare both an alias for a function type and an alias for a pointer to that same function type in a single statement, just like how you can with other type aliases, such as structures. – chris Oct 31 '15 at 18:38
  • @chris So you mean it's just an analogy? May be but I don't see any hint indicating that. The "In the example below [...]" convinces me. – cadaniluk Oct 31 '15 at 18:42
  • This was my interpretation of the question. The OP can certainly clarify. – chris Oct 31 '15 at 18:47