locked
What if I include <WinNT.h> directly? RRS feed

  • Question

  • I've been using C# since I started programming. And sometimes I need to work with some legacy C++ source code, but I always get frustrated by the numerous compiler/linker errors (and IMO some of error messages are really misleading) when trying to compile the simple projects of my own. (I did google quite a lot before I decided to ask a question here.)

    First off, I don't understand header files. My understanding about header files is,  when compiling,  what compiler does is reading the content of the header files and "pasting" the content to the cpp files which include the header files. If the compiler can not find the declaration of a data type or a function, or if the linker can not find the definition(implementation) of that declaration, errors are reported as "undefined identifier" or "can not resolve symbol"...

    See the following code sample, since no data type or function declared in WinNT.h is referenced in the sample code, why would compiler emits so many errors (mostly C2146, C4430) when I trying to compile it? -I include WinNT.h because I want to use the data type TCHAR.

    And if I add #include <Windows.h> before #include <WinNT.h>, the compiler stop complaining. What magic happened then?

    #include <WinNT.h> //compiler errors!

    int main()

    {

        return 0;

    }

    The compiler options are

    cl.exe /O2 /Oi /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FD /EHsc /MD /Gy /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /TP /nologo /errorReport:prompt  MyCpp.cpp

    • Edited by kennyzx Thursday, December 9, 2010 2:08 AM syntax error
    Wednesday, December 8, 2010 5:49 AM

Answers

  • Well, the root header is Windows.h, so that is the one which you should include. If you actually look at MSDN documentation about things in winnt.h you will see that they all tell you to include windows.h. See GetFiberData as an example. Notice the header section says include windows.h.

    I think the issue is that there is nowhere which outright says you must include windows.h but pick it up from examples and documentation which all include windows.h.

    In the end, if you are using Windows functions just including the windows header is the best way to go. If you are not using Windows functions but just the CRT functions then include tchar.h. You can use TCHAR through this means too. As an example.

    #include <tchar.h>
    #include <stdio.h>
    
    int _tmain()
    {
      TCHAR outstr[] = _TEXT("Hello world!");
    
      _tprintf(_TEXT("%s\n"), outstr);
    
      return 0;
    }
    
    Notice that I used TCHAR? Whats more it works? So as I said, if you don't need the Windows header, you can just use tchar.h to get what you want, otherwise you must use it.
    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
    Visit my (not very good) blog at
    http://ccprogramming.wordpress.com/
    • Marked as answer by kennyzx Thursday, December 9, 2010 1:45 AM
    Wednesday, December 8, 2010 3:32 PM

All replies

  • And if I add #include <Windows.h> before #include <WinNT.h>, the compiler stop complaining. What magic happened then?

    Windows.h is the most essential header. If you include this header all importand window specific data types were defined (since window.h includes windef.h). Also all important structures, the constants of the windows messages and a lot more will be defined. windows.h includes a lot more headers.

    If I remember correctly I never added "WinNT.h". This header shoulb be used automatically since it is somewhere in the "windows.h" include tree.

    There is no magic, open the windows.h and you see what I'm saying...

    BTW. for using TCHAR (ANSI and UNICODE handling of characters / strings) you can use TCHAR.H

    Wednesday, December 8, 2010 6:10 AM
  • Thank you Bordon, I open Windows.h and find that Windows.h includes Windef.h, and windef.h includes WinNT.h.

    Now I understand Windows.h is essential and including it can work.

    But I still don't understand if I include WinNT.h directly, what is the compiler complaining about?

    I think if WinNT.h relys on other header files, it will include them, and so no errors are expected if I simply include WinNT.h.

    And you can see, the following error messages do not seem to be caused by missing some header files.

     

    Error    1    error C2146: syntax error : missing ';' before identifier 'WCHAR'    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\WinNT.h

    Error    2    error C4430: missing type specifier - int assumed. Note: C++ does not support default-int    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\WinNT.h

    Error    3    error C2143: syntax error : missing ';' before '*'    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\WinNT.h

    Error    4    error C2040: 'PWSTR' : 'CONST' differs in levels of indirection from 'WCHAR *'    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\WinNT.h

    ...

     

     

    Wednesday, December 8, 2010 7:14 AM
  • Thank you Bordon, I open Windows.h and find that Windows.h includes Windef.h, and windef.h includes WinNT.h.

    Now I understand Windows.h is essential and including it can work.

    But I still don't understand if I include WinNT.h directly, what is the compiler complaining about?

    Me neither. I understand that Microsoft wants us to just include windows.h and be done with it (that is, rule is simple: if you want to work with Win API, you include windows first). But why other headers aren't self-sufficient (they should be, as per good C-header-coding practices), I don't understand. Perhaps they simply think it's easier this way ("include windows.h and don't think about it").

    Goran.

    Wednesday, December 8, 2010 7:50 AM
  • It would be less work for them to maintain if everyone just uses the main header file. Whats more, winnt.h is dependent on a lot of other areas of Windows. This is the header file for NT specific functionality, but as we should all know Win 9x had Win32 API functions but didn't have the NT stuff.

    kennyzx: TCHAR is dependent on the types WCHAR and CHAR which are defined in windef.h. If you want a way of getting TCHAR without having to include all of Windows.h then include the CRT tchar.h as this will include all of the TCHAR typedefs too. But including headers like winnt.h when the documentation tells you to include Windows.h is obviously going to cause trouble, that is why the MSDN documentation tells you to include Windows.h.


    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
    Visit my (not very good) blog at
    http://ccprogramming.wordpress.com/
    Wednesday, December 8, 2010 9:51 AM
  • Where can I find which header to include?
    I search for TCHAR on MSDN, all I get is where it is declared and how it is mapped to other data types (WCHAR, CHAR)

    From http://msdn.microsoft.com/en-us/library/aa383751%28VS.85%29.aspx

    This type is declared in WinNT.h as follows:

    #ifdef UNICODE

     typedef WCHAR TCHAR;

    #else

     typedef char TCHAR;

    #endif
    Wednesday, December 8, 2010 12:54 PM
  • Well, the root header is Windows.h, so that is the one which you should include. If you actually look at MSDN documentation about things in winnt.h you will see that they all tell you to include windows.h. See GetFiberData as an example. Notice the header section says include windows.h.

    I think the issue is that there is nowhere which outright says you must include windows.h but pick it up from examples and documentation which all include windows.h.

    In the end, if you are using Windows functions just including the windows header is the best way to go. If you are not using Windows functions but just the CRT functions then include tchar.h. You can use TCHAR through this means too. As an example.

    #include <tchar.h>
    #include <stdio.h>
    
    int _tmain()
    {
      TCHAR outstr[] = _TEXT("Hello world!");
    
      _tprintf(_TEXT("%s\n"), outstr);
    
      return 0;
    }
    
    Notice that I used TCHAR? Whats more it works? So as I said, if you don't need the Windows header, you can just use tchar.h to get what you want, otherwise you must use it.
    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
    Visit my (not very good) blog at
    http://ccprogramming.wordpress.com/
    • Marked as answer by kennyzx Thursday, December 9, 2010 1:45 AM
    Wednesday, December 8, 2010 3:32 PM
  • Thank you for your detailed explanation. Now I can see that Windows APIs on MSDN all have a "Header" requirement that indicates Windows.h is the one to include. 

    Now I guess, since I prefer Windows Data Types whenever possible (WCHAR instead of wchar_t), then Windows.h is the ESSENTIAL header I should include first.

    Thursday, December 9, 2010 2:03 AM