Search code examples
c++windowsvisual-studio-2010visual-studiobinary-compatibility

_WIN32_WINNT definition changed in header, does this cause a binary incompatibility?


In VS2010, I'm working on updating an application to a new version of a third party library that requires _WIN32_WINNT to be at least 0x501 but another third party shared library that provides binary shared libraries defines it as 0x500 in a header that is included in the application.

If this is modified, can there be a binary incompatibility or is this an insignificant change? Will I have to request new binaries from the library that defines it as 0x500? I'm not sure how to tell if this requires new bins -- I would think if any classes/structs change in size or naming, or any method/function signatures change then a new compile is necessary.


Solution

  • Short answer: Probably not, but if it does you're in a pretty pickle.

    Long answer:

    _WIN32_WINNT controls the version of the WinAPI (and related libraries such as MFC) that your code is going to use. The intent is to ensure that compiler errors are generated if you use Windows features that were introduced after the Windows version you're targeting.

    Mostly this controls which functions, structs etc. are visible to you. This part cannot cause binary incompatibilities except with the Windows versions you're not targeting. However...

    There are some structs in the WinAPI that were extended over the life of Windows. Take a look, for example, at the definition of OPENFILENAME:

    typedef struct tagOFN {
      DWORD         lStructSize;
      HWND          hwndOwner;
      HINSTANCE     hInstance;
      LPCTSTR       lpstrFilter;
      LPTSTR        lpstrCustomFilter;
      DWORD         nMaxCustFilter;
      DWORD         nFilterIndex;
      LPTSTR        lpstrFile;
      DWORD         nMaxFile;
      LPTSTR        lpstrFileTitle;
      DWORD         nMaxFileTitle;
      LPCTSTR       lpstrInitialDir;
      LPCTSTR       lpstrTitle;
      DWORD         Flags;
      WORD          nFileOffset;
      WORD          nFileExtension;
      LPCTSTR       lpstrDefExt;
      LPARAM        lCustData;
      LPOFNHOOKPROC lpfnHook;
      LPCTSTR       lpTemplateName;
    #if (_WIN32_WINNT >= 0x0500)
      void          *pvReserved;
      DWORD         dwReserved;
      DWORD         FlagsEx;
    #endif 
    } OPENFILENAME, *LPOPENFILENAME;
    

    See that last bit at the end? That spells potential trouble -- one part of your code is going to assume that this struct is smaller than the other if one is compiled with _WIN32_WINNT set to 0x400 and the other to 0x500.

    The WinAPI designers did think about this problem. You will notice that the first member of OPENFILE is lStructSize; you are supposed to initialize this with sizeof(OPENFILE). For you, sizeof(OPENFILE) is a compile time constant, for functions in the Windows runtime library, it's the tag by which they decide which version of the OPENSTRUCT struct you're passing into them.

    This spells potential trouble in one scenario: If the binary library and the rest of your code exchange WinAPI types or pointers to such types, and if those types were extended between 0x500 and 0x501, then things are going to explode. Happily, I don't expect there to be many such structs because the version range is very narrow. If this is a worry, however, then you should definitely request new binaries because working around it is going to be difficult and tedious with many opportunities to make mistakes.

    Other than that, I think you're (probably) safe.