Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why NTDDI_VERSION macro changes its value from cpp it includes to ntdddisk.h?

Why NTDDI_VERSION macro changes its value from cpp it includes to ntdddisk.h ?

I am using Visual Studio 2012 with cumulative update 4, and building on Windows 7 x64.

In one CPP i need to call new IOCTL_ .. for WIN 8.

In the CPP there is #include

ntdddisk.h defines the new IOCTL_ for WIN 8 under the guarded condition:

#if (NTDDI_VERSION >= NTDDI_WIN8)
...
#endif

Inside that cpp the NTDDI_VERSION macro has value NTDDI_WIN8 (as expected result from include sdkddkver.h and compilation with /D_WIN32_WINNT=0x0602)

However, in ntdddisk.h the value for NTDDI_VERSION macro has value < NTDDI_VISTA, that is, less than NTDDI_WIN8

Compilation fails with error

error C2065: 'IOCTL_..' : undeclared identifier

Looks like a bug unless i miss something else. Thoughts?

Details are:

In the CPP file there are these includes

#pragma once
// Needed for  new IOCTL_  for  WIN 8 
#include <sdkddkver.h>
#include <windows.h>
// Check  NTDDI_VERSION ...
#if (NTDDI_VERSION >= NTDDI_WIN8)
// Value is  NTDDI_WIN8 as expected
// #include <TROUBLE.h>
#endif

#pragma pack(8)
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <lm.h>
#include <objbase.h>

/*=== IMPORTANT: this struct needs to have 8-byte packing ===*/
typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS {
    SCSI_PASS_THROUGH spt;
    ULONG             Filler;      // realign buffers to double word boundary
    UCHAR             SenseBuf[32];
    UCHAR             DataBuf[512];
} SCSI_PASS_THROUGH_WITH_BUFFERS;
#pragma pack()

Compilation with CL has these parameters including with -D_WIN32_WINNT=0x0602

cl -nologo @COMPL.TMP /Fo..\\..\\..\\optimized\\obj\\x86\\CPP.obj CPP.cpp

COMPL.TMP contains

/I*** application-headers ***       
-D_AFXDLL -c -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DBTREEDB -O2 -Ox -MD -Zi   -DNT_CLIENT -DWIN32 -D"_CONSOLE"  -D_THREADS  -D_OPSYS_TYPE=DS_WINNT  -DPSAPI_VERSION=1 -D_WIN32_WINNT=0x0602 -TP -DMBCS=1 -D_LONG_LONG=1 -D_DSM_VLK_BTREE -DDSM_WIDECHAR  -D_UNICODE -DUNICODE  -DUSE_XML=1 -DXMLUTIL_EXPORTS=1 -DUSE_XERCES_2_8=1 -DPEGASUS_PLATFORM_WIN32_IX86_MSVC=1 -DPEGASUS_USE_EXPERIMENTAL_INTERFACES -Zp1 -D_DSM_LONG_NAME    -W3 -EHsc -GF       
like image 658
TonyI Avatar asked Aug 02 '26 04:08

TonyI


1 Answers

The problem isn't with the _WIN32_WINNT or NTDDI_VERSION macros.

The problem is that windows.h indirectly includes winioctl.h which has the following curious couple of lines about halfway through:

#ifndef _NTDDDISK_H_
#define _NTDDDISK_H_

Unsurprisingly, ntdddisk.h starts with those very same lines and therefore is effectively not included at all.

I couldn't easily come up with a combination or ordering of headers that would work around this problem - I think it's something that MS really needs to fix.

However, the following terrible workaround (that I really don't suggest, unless you can't get any help from MS) seemed to get the compiler to actually process ntdddisk.h:

#define _NTDDDISK_H_
#include <windows.h>
#undef _NTDDDISK_H_

But, I suspect there may be other problems that might pop up as a result of this hack - so if you decide to use it, please test carefully.

like image 179
Michael Burr Avatar answered Aug 05 '26 16:08

Michael Burr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!