Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Microsoft®’s Excellence in Desinformation and Incompetence

Purpose
Case 1
Falsification
Case 2
Falsification
Case 3
Falsification
Case 4
Falsification
Case 5
Falsification
Case 6
Case 7
Falsification
Case 8
Demonstration
Case 9
Demonstration
Case 10
Case 11
Case 12
Case 13
Case 14
Falsification

Purpose

Present multiple cases of Microsoft’s Art of Computer Programming Excellence in Desinformation and Incompetence.

Note: some cases of desinformation presented below were published 25 (in words: twenty-five) years ago and never corrected!

Case 1

The documentation for each of the Win32 functions NetAddServiceAccount(), NetEnumerateServiceAccounts(), NetIsServiceAccount(), NetQueryServiceAccount() and NetRemoveServiceAccount() states since 2009:
This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Logoncli.dll.

[…]

Requirement Value
Header lmaccess.h
DLL Netapi32.dll
Note: while the Requirements sections name Netapi32.dll, all texts but specify Logoncli.dll!

Falsification

Perform the following 12 simple steps to prove the documentation cited above wrong.
  1. Determine which of the 2 DLLs Logoncli.dll and Netapi32.dll provides the 5 functions:

    FOR %? IN (Logoncli.dll) DO SET LOGONCLI=%~$PATH:?
    LINK.EXE /DUMP /EXPORTS /OUT:logoncli.txt "%LOGONCLI%"
    FOR %? IN (Netapi32.dll) DO SET NETAPI32=%~$PATH:?
    LINK.EXE /DUMP /EXPORTS /OUT:netapi32.txt "%NETAPI32%"
    FIND.EXE "ServiceAccount" logoncli.txt netapi32.txt
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    SET LOGONCLI=C:\Windows\System32\logoncli.dll
    
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    SET NETAPI32=C:\Windows\System32\netapi32.dll
    
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ---------- LOGONCLI.TXT
             61   3C 0000F520 NetAddServiceAccount
             62   3D 0000F5AC NetEnumerateServiceAccounts
             66   41 0000F64C NetIsServiceAccount
             69   44 0000F6AC NetQueryServiceAccount
             70   45 0000F568 NetRemoveServiceAccount
    
    ---------- NETAPI32.TXT
             98   61          NetAddServiceAccount (forwarded to LOGONCLI.NetAddServiceAccount)
            142   8D          NetEnumerateServiceAccounts (forwarded to LOGONCLI.NetEnumerateServiceAccounts)
            164   A3          NetIsServiceAccount (forwarded to LOGONCLI.NetIsServiceAccount)
            186   B9          NetQueryServiceAccount (forwarded to LOGONCLI.NetQueryServiceAccount)
            191   BE          NetRemoveServiceAccount (forwarded to LOGONCLI.NetRemoveServiceAccount)
    Logoncli.dll exports the 5 functions; Netapi32.dll exports them too, but as forwarders to the functions implemented in Logoncli.dll, i.e. either DLL can be linked!
  2. Determine whether the highlighted claim This function has no associated import library. holds – or not:

    FOR %? IN (Logoncli.lib) DO SET LOGONCLI=%~$LIB:?
    FOR %? IN (Netapi32.lib) DO SET NETAPI32=%~$LIB:?
    LINK.EXE /DUMP /EXPORTS /OUT:netapi32.txt "%NETAPI32%"
    FIND.EXE "ServiceAccount" netapi32.txt
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    SET LOGONCLI=
    SET NETAPI32=C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\NetAPI32.Lib
    
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ---------- NETAPI32.TXT
                      _NetAddServiceAccount@16
                      _NetEnumerateServiceAccounts@16
                      _NetIsServiceAccount@12
                      _NetQueryServiceAccount@16
                      _NetRemoveServiceAccount@12
    OUCH¹: contrary to the statements in all 5 MSDN articles cited above there exists but an associated import library NetAPI32.lib in Windows’ Software Development Kit!
  3. Create the text file lmaccess.c with the following content in an arbitrary, preferably empty directory:

    // Copyleft © 2009-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <lmaccess.h>
    
    #define STATUS_SUCCESS	0L
    
    __declspec(noreturn)
    VOID	WINAPI	mainCRTStartup(VOID)
    {
    #ifndef WTF
    	DWORD	dwCount;
    	LPWSTR	*lpArray;
    	LONG	ntStatus = NetEnumerateServiceAccounts((LPWSTR) NULL,
    		                                       0UL,
    		                                       &dwCount,
    		                                       &lpArray);
    #elif WTF == 1
    	BOOL	wtf;
    	LPBYTE	lpBuffer;
    	LONG	ntStatus = -NetIsServiceAccount((LPWSTR) NULL,
    		                                (LPWSTR) NULL,
    		                                &wtf);
    	if (ntStatus == -STATUS_SUCCESS)
    		ntStatus = NetQueryServiceAccount((LPWSTR) NULL,
    		                                  (LPWSTR) NULL,
    		                                  0UL,
    		                                  &lpBuffer);
    #else
    	LONG	ntStatus = NetAddServiceAccount((LPWSTR) NULL,
    		                                L"",
    		                                (LPWSTR) NULL,
    		                                SERVICE_ACCOUNT_FLAG_LINK_TO_HOST_ONLY);
    	if (ntStatus == STATUS_SUCCESS)
    		ntStatus = -NetRemoveServiceAccount((LPWSTR) NULL,
    		                                    L"",
    		                                    SERVICE_ACCOUNT_FLAG_UNLINK_FROM_HOST_ONLY);
    #endif
    	ExitProcess(ntStatus);
    }
  4. Compile and link the source file lmaccess.c created in step 3. to test whether the associated import library Netapi32.lib can be linked statically – or not:

    SET CL=/W4 /Zl
    SET LINK=/DEFAULTLIB:kernel32.lib /DEFAULTLIB:netapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    CL.EXE lmaccess.c
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    lmaccess.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:netapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:lmaccess.exe
    lmaccess.obj
    lmaccess.obj : error LNK2019: unresolved external symbol _NetEnumerateServiceAccounts referenced in function _mainCRTStartup@0
    lmaccess.exe : fatal error LNK1120: 1 unresolved externals
    OUCH²: most obviously nobody at Microsoft tests or uses their own products crap with the default settings of their own development tools – and their quality miserability assurance is sound asleep!

    The undecorated symbol name _NetEnumerateServiceAccounts in the error message indicates 2 omissions bugs in the declaration of the function prototype for NetEnumerateServiceAccounts() in the header file lmaccess.h: the mandatory calling convention __stdcall and the (optional) storage class attribute __declspec(dllimport) are missing!

    Note: without the optional __declspec(dllimport) the Visual C compiler generates a CALL ‹function name› that the linker needs to resolve with a stub function, an indirect JMP through the Import Address Table; with __declspec(dllimport) it just generates an indirect CALL through the Import Address Table.

    Note: properly declared, the symbol name would be __imp__NetEnumerateServiceAccounts@16; see the MSDN article Decorated Names for details.

  5. Repeat the previous step 4., now with the /Gz compiler option:

    CL.EXE /Gz lmaccess.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    lmaccess.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:netapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:lmaccess.exe
    lmaccess.obj
  6. Execute the console application lmaccess.exe built in step 5. and evaluate its exit code:

    .\lmaccess.exe
    CERTUTIL.EXE /ERROR %ERRORLEVEL%
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    0xc0020012 (NT: 0xc0020012 RPC_NT_UNKNOWN_IF) -- 3221356562 (-1073610734)
    Error message text: The interface is unknown.
    CertUtil: -error command completed successfully.
    OUCH³: WTF?
  7. Repeat step 4., but with the preprocessor macro WTF defined:

    CL.EXE /DWTF lmaccess.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    lmaccess.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:netapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:lmaccess.exe
    lmaccess.obj
    lmaccess.obj : error LNK2019: unresolved external symbol _NetIsServiceAccount referenced in function _mainCRTStartup@0
    lmaccess.obj : error LNK2019: unresolved external symbol _NetQueryServiceAccount referenced in function _mainCRTStartup@0
    lmaccess.exe : fatal error LNK1120: 2 unresolved externals
    OUCH⁴: the declarations of the function prototypes for NetIsServiceAccount() and NetQueryServiceAccount() are as faulty as that for NetEnumerateServiceAccounts()!
  8. Repeat the previous step 7., now with the /Gz compiler option too:

    CL.EXE /DWTF /Gz lmaccess.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    lmaccess.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:netapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:lmaccess.exe
    lmaccess.obj
  9. Execute the console application lmaccess.exe built in step 8. and evaluate its exit code:

    .\lmaccess.exe
    CERTUTIL.EXE /ERROR %ERRORLEVEL%
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    0xc0030009 (NT: 0xc0030009 RPC_NT_NULL_REF_POINTER) -- 3221422089 (-1073545207)
    Error message text: A null reference pointer was passed to the stub.
    CertUtil: -error command completed successfully.
    OUCH⁵: while the NetIsServiceAccount() function accepts a NULL pointer for the AccountName parameter, the NetQueryServiceAccount() function rejects it with NTSTATUS 0xC0030009 alias RPC_NT_NULL_REF_POINTER!
  10. Repeat step 7., now with the preprocessor macro WTF defined as 0:

    CL.EXE /DWTF=0 lmaccess.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    lmaccess.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:netapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:lmaccess.exe
    lmaccess.obj
    lmaccess.obj : error LNK2019: unresolved external symbol _NetAddServiceAccount referenced in function _mainCRTStartup@0
    lmaccess.obj : error LNK2019: unresolved external symbol _NetRemoveServiceAccount referenced in function _mainCRTStartup@0
    lmaccess.exe : fatal error LNK1120: 2 unresolved externals
    OUCH⁶: the declarations of the function prototypes for NetAddServiceAccount() and NetRemoveServiceAccount() are as faulty as these for NetEnumerateServiceAccounts(), NetIsServiceAccount() and NetQueryServiceAccount()!
  11. Repeat the previous step 10., now with the /Gz compiler option too:

    CL.EXE /DWTF=0 /Gz lmaccess.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    lmaccess.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:netapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:lmaccess.exe
    lmaccess.obj
  12. Finally execute the console application lmaccess.exe built in step 11. and evaluate its exit code:

    .\lmaccess.exe
    CERTUTIL.EXE /ERROR %ERRORLEVEL%
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    0xc0020012 (NT: 0xc0020012 RPC_NT_UNKNOWN_IF) -- 3221356562 (-1073610734)
    Error message text: The interface is unknown.
    CertUtil: -error command completed successfully.
    OUCH⁷: WTF?
Note: the repetition of this falsification in the 64-bit execution environment is left as an exercise to the reader.

Case 2

The documentation for the Win32 function RtlDecryptMemory() states since 2001:
Note This function has no associated import library. This function is available as a resource named SystemFunction041 in Advapi32.dll. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Advapi32.dll.
[…]
NTSTATUS RtlDecryptMemory(
  PVOID Memory,
  ULONG MemorySize,
  ULONG OptionFlags
);

[…]

Requirement Value
Header ntsecapi.h
DLL Advapi32.dll
Ouch¹: a function is not a (named) resource; see the MSDN article Menus and Other Resources for their definition!

The documentation for the Win32 function RtlEncryptMemory() states since 2001:

Note This function has no associated import library. This function is available as a resource named SystemFunction040 in Advapi32.dll. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Advapi32.dll.
[…]
NTSTATUS RtlEncryptMemory(
  PVOID Memory,
  ULONG MemorySize,
  ULONG OptionFlags
);

[…]

Requirement Value
Header ntsecapi.h
DLL Advapi32.dll
Ouch²: a function is not a (named) resource; see the MSDN article Menus and Other Resources for their definition!

The documentation for the Win32 function RtlGenRandom() states since 2001:

Note This function has no associated import library. This function is available as a resource named SystemFunction036 in Advapi32.dll. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Advapi32.dll.
[…]
BOOLEAN RtlGenRandom(
  PVOID RandomBuffer,
  ULONG RandomBufferLength
);

[…]

Requirement Value
Header ntsecapi.h
DLL Advapi32.dll
Ouch³: a function is not a (named) resource; see the MSDN article Menus and Other Resources for their definition!

Falsification

Perform the following 5 simple steps to prove the documentation cited above wrong.
  1. Determine whether the highlighted claim This function has no associated import library. holds – or not:

    FOR %? IN (Advapi32.lib) DO SET ADVAPI32=%~$LIB:?
    LINK.EXE /DUMP /EXPORTS /OUT:advapi32.txt "%ADVAPI32%"
    FIND.EXE "SystemFunction0" advapi32.txt
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    SET ADVAPI32=C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\Advapi32.Lib
    
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ---------- ADVAPI32.TXT
                      _SystemFunction001@12
                      _SystemFunction002@12
                      _SystemFunction003@8
                      _SystemFunction004@12
                      _SystemFunction005@12
                      _SystemFunction006@8
                      _SystemFunction007@8
                      _SystemFunction008@12
                      _SystemFunction009@12
                      _SystemFunction010@12
                      _SystemFunction011@12
                      _SystemFunction012@12
                      _SystemFunction013@12
                      _SystemFunction014@12
                      _SystemFunction015@12
                      _SystemFunction016@12
                      _SystemFunction017@12
                      _SystemFunction018@12
                      _SystemFunction019@12
                      _SystemFunction020@12
                      _SystemFunction021@12
                      _SystemFunction022@12
                      _SystemFunction023@12
                      _SystemFunction024@12
                      _SystemFunction025@12
                      _SystemFunction026@12
                      _SystemFunction027@12
                      _SystemFunction028@8
                      _SystemFunction029@8
                      _SystemFunction030@8
                      _SystemFunction031@8
                      _SystemFunction032@8
                      _SystemFunction033@8
                      _SystemFunction034@12
                      _SystemFunction036@8
                      _SystemFunction040@12
                      _SystemFunction041@12
    OUCH¹: contrary to the statements in all 3 MSDN articles cited above there exists but an associated import library Advapi32.lib in Windows’ Software Development Kit!
  2. Create the text file ntsecapi.c with the following content in an arbitrary, preferably empty directory:

    // Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <ntsecapi.h>
    
    #define STATUS_SUCCESS		0L
    #define STATUS_UNSUCCESSFUL	0xC0000001L
    
    __declspec(noreturn)
    VOID	WINAPI	mainCRTStartup(VOID)
    {
    	BYTE	cbMemory[RTL_ENCRYPT_MEMORY_SIZE];
    	LONG	ntStatus;
    
    	if (RtlGenRandom(cbMemory, sizeof(cbMemory)))
    	{
    		ntStatus = RtlEncryptMemory(cbMemory, sizeof(cbMemory), 0UL);
    
    		if (ntStatus == STATUS_SUCCESS)
    			ntStatus = RtlDecryptMemory(cbMemory, sizeof(cbMemory), 0UL);
    	}
    	else
    		ntStatus = STATUS_UNSUCCESSFUL;
    
    	ExitProcess(ntStatus);
    }
  3. Compile and link the source file ntsecapi.c created in step 2. to test whether the associated import library Advapi32.lib can be linked statically – or not:

    SET CL=/W4 /Zl
    SET LINK=/DEFAULTLIB:kernel32.lib /DEFAULTLIB:advapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    CL.EXE ntsecapi.c
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ntsecapi.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:advapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:ntsecapi.exe
    ntsecapi.obj
    ntsecapi.obj : error LNK2019: unresolved external symbol _SystemFunction041 referenced in function _mainCRTStartup@0
    ntsecapi.obj : error LNK2019: unresolved external symbol _SystemFunction040 referenced in function _mainCRTStartup@0
    ntsecapi.obj : error LNK2019: unresolved external symbol _SystemFunction036 referenced in function _mainCRTStartup@0
    ntsecapi.exe : fatal error LNK1120: 3 unresolved externals
    OUCH²: the undecorated symbol names _SystemFunction036, _SystemFunction040 and _SystemFunction041 in the error messages indicate 2 omissions bugs in the declarations of the function prototypes for RtlDecryptMemory(), RtlEncryptMemory() and RtlGenRandom() in the header file ntsecapi.h: the mandatory calling convention __stdcall and the (optional) storage class attribute __declspec(dllimport) are missing!

    Note: properly declared, the symbol names were but __imp__SystemFunction036@8, __imp__SystemFunction040@12 and __imp__SystemFunction041@12; see the MSDN article Decorated Names for details.

  4. Repeat the previous step 3., now with the /Gz compiler option:

    CL.EXE /Gz ntsecapi.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ntsecapi.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:kernel32.lib /DEFAULTLIB:advapi32.lib /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE
    /out:ntsecapi.exe
    ntsecapi.obj
  5. Finally execute the console application ntsecapi.exe built in step 4. and evaluate its exit code:

    .\ntsecapi.exe
    CERTUTIL.EXE /ERROR %ERRORLEVEL%
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    0x0 (WIN32: 0) -- 0 (0)
    Error message text: The operation completed successfully.
    CertUtil: -error command completed successfully.
Note: the repetition of this falsification in the 64-bit execution environment is left as an exercise to the reader.

Case 3

The documentation for both of the Win32 functions InstallPerfDllA() and InstallPerfDllW() states since 1999:
This function has no associated import library; you must call it using the LoadLibrary and GetProcAddress functions.

[…]

Requirement Value
Header Loadperf.h
DLL Loadperf.dll

Falsification

Perform the following 3 simple steps to prove the documentation cited above wrong.
  1. Determine whether the highlighted claim This function has no associated import library. holds – or not:

    FOR %? IN (Loadperf.lib) DO SET LOADPERF=%~$LIB:?
    LINK.EXE /DUMP /EXPORTS /OUT:loadperf.txt "%LOADPERF%"
    FIND.EXE "InstallPerfDll" loadperf.txt
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    SET LOADPERF=C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\LoadPerf.Lib
    
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ---------- LOADPERF.TXT
                      _InstallPerfDllA@12
                      _InstallPerfDllW@12
  2. Create the text file loadperf.c with the following content in an arbitrary, preferably empty directory:

    // Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <loadperf.h>
    
    FARPROC	loadperf[] = {InstallPerfDllA,
    	              InstallPerfDllW};
  3. Compile and link the source file loadperf.c created in step 2. to show that the associated import library Loadperf.lib can be linked statically:

    SET CL=/W4 /Zl
    SET LINK=/DEFAULTLIB:loadperf.lib /DLL /NOENTRY
    CL.EXE loadperf.c
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    loadperf.c
    loadperf.c(9) : warning C4232: nonstandard extension used : 'loadperf' : address of dllimport 'InstallPerfDllA' is not static, identity not guaranteed
            C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\loadperf.h(49) : see declaration of 'InstallPerfDllA'
    loadperf.c(9) : warning C4057: 'initializing' : 'FARPROC' differs in indirection to slightly different base types from 'DWORD (__stdcall *)(LPCSTR,LPCSTR,ULONG_PTR)'
    loadperf.c(10) : warning C4232: nonstandard extension used : 'loadperf' : address of dllimport 'InstallPerfDllW' is not static, identity not guaranteed
            C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\loadperf.h(42) : see declaration of 'InstallPerfDllW'
    loadperf.c(10) : warning C4057: 'initializing' : 'FARPROC' differs in indirection to slightly different base types from 'DWORD (__stdcall *)(LPCWSTR,LPCWSTR,ULONG_PTR)'
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:loadperf.lib /DLL /NOENTRY
    /out:loadperf.exe
    loadperf.obj
    OOPS: contrary to their documentation all functions can be linked statically with their import library loadperf.lib!
Note: the repetition of this falsification in the 64-bit execution environment is left as an exercise to the reader.

Case 4

The documentation for each of the Win32 functions CryptCATAdminAcquireContext(), CryptCATAdminAcquireContext2(), CryptCATAdminAddCatalog(), CryptCATAdminCalcHashFromFileHandle(), CryptCATAdminCalcHashFromFileHandle2(), CryptCATAdminReleaseCatalogContext(), CryptCATAdminReleaseContext(), CryptCATAdminRemoveCatalog(), CryptCATCatalogInfoFromContext(), CryptCATClose(), CryptCATEnumerateAttr(), CryptCATEnumerateCatAttr() and CryptCATGetMemberInfo() states since 2001:
This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Wintrust.dll.

[…]

Requirement Value
Header mscat.h
Library Wintrust.lib
DLL Wintrust.dll
Ouch: the highlighted reference to the import library Wintrust.lib in the Requirements section but contradicts the highlighted claim This function has no associated import library. from the text!

The documentation for both of the Win32 functions CryptCATAdminResolveCatalogPath() and IsCatalogFile() states since 2001:

Note This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Wintrust.dll.

[…]

Requirement Value
Header mscat.h
DLL Wintrust.dll
The documentation for the Win32 function CryptCATOpen() states since 2001:
Note Some older versions of Wintrust.lib do not contain the export information for this function. In this case, you must use the LoadLibrary and GetProcAddress functions to dynamically link to Wintrust.dll.

[…]

Requirement Value
Header mscat.h
Library Wintrust.lib
DLL Wintrust.dll
The documentation for both of the Win32 functions CryptCATCDFEnumAttributesWithCDFTag() and CryptCATCDFEnumMembersByCDFTagEx() states since 2001:
Note This function has no associated header file or import library. To call this function, you must create a user-defined header file and use the LoadLibrary and GetProcAddress functions to dynamically link to Mssign32.dll.

[…]

Requirement Value
DLL Wintrust.dll
Ouch: the highlighted reference to Wintrust.dll in the Requirements section but contradicts the highlighted claim dynamically link to Mssign32.dll. from the text!

Falsification

Perform the following 3 simple steps to prove the documentation cited above wrong.
  1. Determine whether the highlighted claim This function has no associated import library. holds – or not:

    FOR %? IN (Wintrust.lib) DO SET WINTRUST=%~$LIB:?
    LINK.EXE /DUMP /EXPORTS /OUT:wintrust.txt "%WINTRUST%"
    FIND.EXE "CryptCAT" wintrust.txt
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    SET WINTRUST=C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\Wintrust.Lib
    
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ---------- WINTRUST.TXT
                      ?CryptCATVerifyMember@@YGHPAXPAUCRYPTCATMEMBER_@@0@Z (int __stdcall CryptCATVerifyMember(void *,struct CRYPTCATMEMBER_ *,void *))
                      _CryptCATAdminAcquireContext@12
                      _CryptCATAdminAddCatalog@16
                      _CryptCATAdminCalcHashFromFileHandle@16
                      _CryptCATAdminEnumCatalogFromHash@20
                      _CryptCATAdminPauseServiceForBackup@8
                      _CryptCATAdminReleaseCatalogContext@12
                      _CryptCATAdminReleaseContext@8
                      _CryptCATAdminRemoveCatalog@12
                      _CryptCATAdminResolveCatalogPath@16
                      _CryptCATAllocSortedMemberInfo@8
                      _CryptCATCDFClose@4
                      _CryptCATCDFEnumAttributes@16
                      _CryptCATCDFEnumAttributesWithCDFTag@20
                      _CryptCATCDFEnumCatAttributes@12
                      _CryptCATCDFEnumMembers@12
                      _CryptCATCDFEnumMembersByCDFTag@16
                      _CryptCATCDFEnumMembersByCDFTagEx@24
                      _CryptCATCDFOpen@8
                      _CryptCATCatalogInfoFromContext@12
                      _CryptCATClose@4
                      _CryptCATEnumerateAttr@12
                      _CryptCATEnumerateCatAttr@8
                      _CryptCATEnumerateMember@8
                      _CryptCATFreeSortedMemberInfo@8
                      _CryptCATGetAttrInfo@12
                      _CryptCATGetCatAttrInfo@8
                      _CryptCATGetMemberInfo@8
                      _CryptCATHandleFromStore@4
                      _CryptCATOpen@20
                      _CryptCATPersistStore@4
                      _CryptCATPutAttrInfo@24
                      _CryptCATPutCatAttrInfo@20
                      _CryptCATPutMemberInfo@28
                      _CryptCATStoreFromHandle@4
    OUCH: contrary to the statements in all 16 MSDN articles cited above there exists but an associated import library Wintrust.lib in Windows’ Software Development Kit!
  2. Create the text file mscat.c with the following content in an arbitrary, preferably empty directory:

    // Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <wintrust.h>
    #include <mscat.h>
    
    CRYPTCATATTRIBUTE* WINAPI CryptCATCDFEnumAttributesWithCDFTag(
      _In_ CRYPTCATCDF                  *pCDF,
      _In_ LPWSTR                       pwszMemberTag,
      _In_ CRYPTCATMEMBER               *pMember,
      _In_ CRYPTCATATTRIBUTE            *pPrevAttr,
      _In_ PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError
    );
    
    LPWSTR WINAPI CryptCATCDFEnumMembersByCDFTagEx(
      _In_    CRYPTCATCDF                  *pCDF,
      _Inout_ LPWSTR                       pwszPrevCDFTag,
      _In_    PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError,
      _In_    CRYPTCATMEMBER               **ppMember,
      _In_    BOOL                         fContinueOnError,
      _In_    LPVOID                       pvReserved
    );
    
    FARPROC	mscat[] = {CryptCATAdminAcquireContext,
    #if _WIN32_WINNT >= 0x0602
    	           CryptCATAdminAcquireContext2,
    #endif
    	           CryptCATAdminAddCatalog,
    	           CryptCATAdminCalcHashFromFileHandle,
    #if _WIN32_WINNT >= 0x0602
    	           CryptCATAdminCalcHashFromFileHandle2,
    #endif
    	           CryptCATAdminReleaseCatalogContext,
    	           CryptCATAdminReleaseContext,
    	           CryptCATAdminRemoveCatalog,
    	           CryptCATAdminResolveCatalogPath,
    	           CryptCATCatalogInfoFromContext,
    	           CryptCATCDFEnumAttributesWithCDFTag,
    	           CryptCATCDFEnumMembersByCDFTagEx,
    	           CryptCATClose,
    	           CryptCATEnumerateAttr,
    	           CryptCATEnumerateCatAttr,
    	           CryptCATGetMemberInfo,
    	           CryptCATOpen,
    	           IsCatalogFile};
  3. Compile and link the source file mscat.c created in step 2. to show that the associated import library Wintrust.lib can be linked statically:

    SET CL=/W4 /Zl
    SET LINK=/DEFAULTLIB:wintrust.lib /DLL /NOENTRY
    CL.EXE mscat.c
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    mscat.c
    c:\program files\microsoft sdks\windows\v7.1\include\mssip.h(92) : warning C4201 : nonstandard extension used : nameless struct/union
    mscat.c(31) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'HCATINFO (__stdcall *)(HCATADMIN,PWSTR,PWSTR,DWORD)'
    mscat.c(44) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'CRYPTCATATTRIBUTE *(__stdcall *)(HANDLE,CRYPTCATMEMBER *,CRYPTCATATTRIBUTE *)'
    mscat.c(45) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'CRYPTCATATTRIBUTE *(__stdcall *)(HANDLE,CRYPTCATATTRIBUTE *)'
    mscat.c(46) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'CRYPTCATMEMBER *(__stdcall *)(HANDLE,LPWSTR)'
    mscat.c(47) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'HANDLE (__stdcall *)(LPWSTR,DWORD,HCRYPTPROV,DWORD,DWORD)'
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:wintrust.lib /DLL /NOENTRY
    /out:mscat.exe
    mscat.obj
    OOPS: contrary to their documentation all functions can be linked statically with their import library wintrust.lib!
Note: the repetition of this falsification in the 64-bit execution environment is left as an exercise to the reader.

Case 5

The documentation for both of the Win32 functions OpenPersonalTrustDBDialog() and OpenPersonalTrustDBDialogEx() states since 2003:
Note This function has no associated header file or import library. You must define the function yourself and use the LoadLibrary and GetProcAddress functions to dynamically link to Wintrust.dll.

[…]

Requirement Value
Header wintrust.h
DLL Wintrust.dll
Ouch¹: the highlighted reference to the header file wintrust.h in the Requirements section but contradicts the highlighted claim This function has no associated header file or import library. from the text!

The documentation for both of the Win32 functions WintrustGetRegPolicyFlags() and WintrustSetRegPolicyFlags() states since 2001:

Note This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Wintrust.dll.

[…]

Requirement Value
Header wintrust.h
DLL Wintrust.dll
The documentation for the Win32 function WTHelperCertFindIssuerCertificate() states since 2001:

Note

This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Wintrust.dll.

[…]

Requirement Value
DLL Wintrust.dll
Ouch²: no header file is specified in the Requirements section!

The documentation for each of the Win32 functions WintrustAddActionID(), WintrustLoadFunctionPointers(), WintrustRemoveActionID(), WintrustSetDefaultIncludePEPageHashes() WTHelperCertIsSelfSigned(), WTHelperGetProvCertFromChain(), WTHelperGetProvPrivateDataFromChain(), WTHelperGetProvSignerFromChain() and WTHelperProvDataFromStateData() states since 2001:

This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Wintrust.dll.

[…]

Requirement Value
Header wintrust.h
Library Wintrust.lib
DLL Wintrust.dll
Ouch³: the highlighted reference to the import library Wintrust.lib in the Requirements section but contradicts the highlighted claim This function has no associated import library. from the text!

Falsification

Perform the following 3 simple steps to prove the documentation cited above wrong.
  1. Determine whether the highlighted claim This function has no associated import library. holds – or not:

    FOR %? IN (Wintrust.lib) DO SET WINTRUST=%~$LIB:?
    LINK.EXE /DUMP /EXPORTS /OUT:wintrust.txt "%WINTRUST%"
    FIND.EXE "OpenPersonalTrustDBDialog" wintrust.txt
    FIND.EXE "Wintrust" wintrust.txt
    FIND.EXE "WTHelper" wintrust.txt
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    SET WINTRUST=C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\Wintrust.Lib
    
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ---------- WINTRUST.TXT
                      _OpenPersonalTrustDBDialog@4
                      _OpenPersonalTrustDBDialogEx@12
    
    ---------- WINTRUST.TXT
                      _WintrustAddActionID@12
                      _WintrustAddDefaultForUsage@8
                      _WintrustCertificateTrust@4
                      _WintrustGetDefaultForUsage@12
                      _WintrustGetRegPolicyFlags@4
                      _WintrustLoadFunctionPointers@8
                      _WintrustRemoveActionID@4
                      _WintrustSetDefaultIncludePEPageHashes@4
                      _WintrustSetRegPolicyFlags@4
    
    ---------- WINTRUST.TXT
                      _WTHelperCertCheckValidSignature@4
                      _WTHelperCertIsSelfSigned@8
                      _WTHelperCheckCertUsage@8
                      _WTHelperGetAgencyInfo@12
                      _WTHelperGetFileHandle@4
                      _WTHelperGetFileHash@24
                      _WTHelperGetFileName@4
                      _WTHelperGetKnownUsages@8
                      _WTHelperGetProvCertFromChain@8
                      _WTHelperGetProvPrivateDataFromChain@8
                      _WTHelperGetProvSignerFromChain@16
                      _WTHelperIsInRootStore@8
                      _WTHelperOpenKnownStores@4
                      _WTHelperProvDataFromStateData@4
    OUCH: contrary to the statements in all 13 MSDN articles cited above there exists but an associated import library Wintrust.lib in Windows’ Software Development Kit!
  2. Create the text file wintrust.c with the following content in an arbitrary, preferably empty directory:

    // Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <wintrust.h>
    
    FARPROC	wintrust[] = {OpenPersonalTrustDBDialog,
    	              OpenPersonalTrustDBDialogEx,
    	              WintrustAddActionID,
    	              WintrustGetRegPolicyFlags,
    	              WintrustLoadFunctionPointers,
    	              WintrustRemoveActionID,
    	              WintrustSetDefaultIncludePEPageHashes,
    	              WintrustSetRegPolicyFlags,
    	              WTHelperCertIsSelfSigned,
    	              WTHelperGetProvCertFromChain,
    	              WTHelperGetProvPrivateDataFromChain,
    	              WTHelperGetProvSignerFromChain,
    	              WTHelperProvDataFromStateData};
  3. Compile and link the source file wintrust.c created in step 2. to show that the associated import library Wintrust.lib can be linked statically:

    SET CL=/W4 /Zl
    SET LINK=/DEFAULTLIB:wintrust.lib /DLL /NOENTRY
    CL.EXE wintrust.c
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wintrust.c
    wintrust.c(12) : warning C4133: 'initializing' : incompatible types - from 'void (__stdcall *)(DWORD *)' to 'FARPROC'
    wintrust.c(15) : warning C4133: 'initializing' : incompatible types - from 'void (__stdcall *)(BOOL)' to 'FARPROC'
    wintrust.c(18) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'CRYPT_PROVIDER_CERT *(__stdcall *)(CRYPT_PROVIDER_SGNR *,DWORD)'
    wintrust.c(19) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'CRYPT_PROVIDER_PRIVDATA *(__stdcall *)(CRYPT_PROVIDER_DATA *,GUID *)'
    wintrust.c(20) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'CRYPT_PROVIDER_SGNR *(__stdcall *)(CRYPT_PROVIDER_DATA *,DWORD,BOOL,DWORD)'
    wintrust.c(21) : warning C4047: 'initializing' : 'FARPROC' differs in levels of indirection from 'CRYPT_PROVIDER_DATA *(__stdcall *)(HANDLE)'
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DEFAULTLIB:wintrust.lib /DLL /NOENTRY
    /out:wintrust.exe
    wintrust.obj
    OOPS: contrary to their documentation all functions can be linked statically with their import library wintrust.lib!
Note: the repetition of this falsification in the 64-bit execution environment is left as an exercise to the reader.

Case 6

The documentation for the Visual C compiler helper routine _chkstk() states since more than 20 years:
_chkstk Routine is a helper routine for the C compiler. For x86 compilers, _chkstk Routine is called when the local variables exceed 4K bytes; for x64 compilers it is 8K.
OUCH: the correct value for x64 alias AMD64 compilers is but 4096 too; 8192 is was used only by compilers for IA64 alias Itanium® processors!

The documentation for the /Gs compiler option states:

A stack probe is a sequence of code that the compiler inserts at the beginning of a function call. When initiated, a stack probe reaches benignly into memory by the amount of space required to store the function's local variables. This probe causes the operating system to transparently page in more stack memory if necessary, before the rest of the function runs.

By default, the compiler generates code that initiates a stack probe when a function requires more than one page of stack space. This default is equivalent to a compiler option of /Gs4096 for x86, x64, ARM, and ARM64 platforms. This value allows an application and the Windows memory manager to increase the amount of memory committed to the program stack dynamically at run time.

Case 7

The documentation for the Visual C compiler helper routine _alloca() states since more than 20 years:
Allocates memory on the stack. […]

The _alloca routine returns a void pointer to the allocated space, which is guaranteed to be suitably aligned for storage of any type of object. […]

Falsification

Perform the following 3 simple steps to prove the highlighted claim of the documentation cited above wrong.
  1. Create the text file alloca.c with the following content in an arbitrary, preferably empty directory:

    // Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    void	*mainCRTStartup(void)
    {
    	return _alloca(42);
    }
  2. Compile and link the source file alloca.c created in step 1.:

    SET CL=/GAFS- /Oisy /W4 /Zl
    SET LINK=/ENTRY:mainCRTStartup /MACHINE:I386 /SUBSYSTEM:CONSOLE
    CL.EXE alloca.c
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    alloca.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /ENTRY:mainCRTStartup /MACHINE:I386 /SUBSYSTEM:CONSOLE
    /out:alloca.exe
    alloca.obj
  3. Execute the console application alloca.exe built in step 2. to prove the documentation cited above wrong:

    .\alloca.exe
    ECHO %ERRORLEVEL%
    SET /A %ERRORLEVEL% % 16
    3733996
    12
    OUCH: memory objects referenced by SSE instructions require but a 16 byte alignment!

Case 8

Demonstration

Perform the following 6 (plus 1 optional) simple steps to show that even Microsoft’s kernel developers can’t tell 0 from 231 or 263.
  1. Create the text file wtf.asm with the following content in an arbitrary, preferably empty directory:

    ; Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    	.386
    	.model	flat, stdcall
    	.code
    
    wtf	proc	public
    
    	mov	ecx, 1 shl 31	; ecx = divisor = 0x80000000,
    				; edx:eax = arbitrary dividend
    	div	ecx		; eax = arbitrary quotient,
    				; edx = arbitrary remainder
    				;     < divisor
    	not	edx		; edx:eax = dividend
    				;         = divisor << 32 | arbitrary quotient
    				;         > divisor << 32
    	div	ecx		; raise #DE (divide error exception) via
    				;  quotient overflow
    ;;	ret
    
    wtf	endp
    	end	wtf		; emits "/ENTRY:wtf@0" in '.drectve' section
  2. Assemble and link the source file wtf.asm created in step 1.:

    SET ML=/W3 /X
    SET LINK=/SUBSYSTEM:CONSOLE
    ML.EXE wtf.asm
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) Macro Assembler Version 10.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
     Assembling: wtf.asm
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /SUBSYSTEM:CONSOLE
    /OUT:wtf.exe
    wtf.obj
  3. Execute the console application wtf.exe built in step 2. to show that 231 is equal 0:

    VER
    .\wtf.exe
    CERTUTIL.EXE /ERROR %ERRORLEVEL%
    Microsoft Windows [Version 6.1.7601]
    
    0xc0000094 (NT: 0xc0000094 STATUS_INTEGER_DIVIDE_BY_ZERO) -- 3221225620 (-1073741676)
    Error message text: {EXCEPTION}
    Integer division by zero
    CertUtil: -error command completed successfully.
    OUCH: (at least) for the divisor 231, which most obviously differs from 0, Windows’ kernel maps the processor’s #DE to the wrong NTSTATUS 0xC0000094 alias STATUS_INTEGER_DIVIDE_BY_ZERO instead to the correct 0xC0000095 alias STATUS_INTEGER_OVERFLOW!
  4. Overwrite the text file wtf.asm created in step 1. with the following content:

    ; Copyleft © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    	.code
    
    wtf	proc	public
    
    	mov	rcx, 1 shl 63	; rcx = divisor = 0x8000000000000000,
    				; rdx:rax = arbitrary dividend
    	div	rcx		; rax = arbitrary quotient,
    				; rdx = arbitrary remainder
    				;     < divisor
    	not	rdx		; rdx:rax = dividend
    				;         = divisor << 64 | arbitrary quotient
    				;         > divisor << 64
    	div	rcx		; raise #DE (divide error exception) via
    				;  quotient overflow
    ;;	ret
    
    wtf	endp
    	end
  5. Assemble and link the source file wtf.asm modified in step 4.:

    SET ML=/W3 /X
    SET LINK=/ENTRY:wtf /SUBSYSTEM:CONSOLE
    ML64.EXE wtf.asm
    Note: the command lines can be copied and pasted as block into a Command Processor window!
    Microsoft (R) Macro Assembler (x64) Version 10.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
     Assembling: wtf.asm
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /ENTRY:wtf /SUBSYSTEM:CONSOLE
    /OUT:wtf.exe
    wtf.obj
  6. Execute the console application wtf.exe built in step 5. to show that 263 is equal 0:

    VER
    .\wtf.exe
    CERTUTIL.EXE /ERROR %ERRORLEVEL%
    Microsoft Windows [Version 6.1.7601]
    
    0xc0000094 (NT: 0xc0000094 STATUS_INTEGER_DIVIDE_BY_ZERO) -- 3221225620 (-1073741676)
    Error message text: {EXCEPTION}
    Integer division by zero
    CertUtil: -error command completed successfully.
    OUCH: (at least) for the divisor 263, which most obviously differs from 0, Windows’ kernel maps the processor’s #DE to the wrong NTSTATUS 0xC0000094 alias STATUS_INTEGER_DIVIDE_BY_ZERO instead to the correct 0xC0000095 alias STATUS_INTEGER_OVERFLOW!
  7. If you have the Debugging Tools for Windows installed, execute the console applications wtf.exe built in step 1. and step 5. under the debugger:

    NTSD.EXE .\wtf.exe
    Note: if necessary, see the MSDN article Debugging Using CDB and NTSD for an introduction.
    Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
    Copyright (c) Microsoft Corporation. All rights reserved.
    
    CommandLine: .\wtf.exe
    Symbol search path is: srv*
    Executable search path is: 
    ModLoad: 00ee0000 00ee2000   image00ee0000
    ModLoad: 779c0000 77b40000   ntdll.dll
    ModLoad: 774d0000 775e0000   C:\Windows\syswow64\kernel32.dll
    ModLoad: 76080000 760c7000   C:\Windows\syswow64\KERNELBASE.dll
    ModLoad: 75790000 75831000   C:\Windows\syswow64\ADVAPI32.DLL
    ModLoad: 75fd0000 7607c000   C:\Windows\syswow64\msvcrt.dll
    ModLoad: 75e70000 75e89000   C:\Windows\SysWOW64\sechost.dll
    ModLoad: 75ed0000 75fc0000   C:\Windows\syswow64\RPCRT4.dll
    ModLoad: 750e0000 75140000   C:\Windows\syswow64\SspiCli.dll
    ModLoad: 750d0000 750dc000   C:\Windows\syswow64\CRYPTBASE.dll
    (22f0.26a0): Break instruction exception - code 80000003 (first chance)
    eax=00000000 ebx=00000000 ecx=ed9b0000 edx=0022e038 esi=fffffffe edi=00000000
    eip=77a610a6 esp=001bf414 ebp=001bf440 iopl=0         nv up ei pl zr na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
    ntdll!LdrpDoDebuggerBreak+0x2c:
    77a610a6 cc              int     3
    0:000> g
    (22f0.26a0): Integer divide-by-zero - code c0000094 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=01dc2000 ebx=7efde000 ecx=80000000 edx=88b1cbd4 esi=00000000 edi=00000000
    eip=00ee1009 esp=001bf898 ebp=001bf8a0 iopl=0         nv up ei pl zr na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
    *** WARNING: Unable to verify checksum for image00ee0000
    *** ERROR: Module load completed but symbols could not be loaded for image00ee0000
    image00ee0000+0x1009:
    00ee1009 f7f1            div     eax,ecx
    0:000> q
    quit:
    Oops: also notice the slew of unreferenced DLLs loaded with the debuggee every application!

Case 9

Starting with Windows 2000, the Command Processor Cmd.exe supports arithmetic operations with its builtin Set command.

Demonstration

Perform the following 2 simple steps to show 2 most stupid, at least 25 (in words: twenty-five) year old bugs which crash the Command Processor.
  1. Start the Command Processor and execute the following 4 command lines to show the first stupid bug:

    SET /A -2147483648
    SET /A ~2147483647
    SET /A ~2147483647 / -1
    SET /A ~2147483647 % -1
    Invalid number. Numbers are limited to 32-bits of precision.
    -2147483648
    Invalid number. Numbers are limited to 32-bits of precision.
    Oops: although valid, a literal −2147483648, the smallest signed 32-bit integer, is reported as invalid number.

    OUCH¹: on systems with i386 or AMD64 processor, the Command Processor crashes computing the modulus of −2147483648 ÷ −1 (which happens to be 0, the only number smaller in magnitude than the divisor −1)!

    Note: dividing −2147483648, the smallest signed 32-bit integer, by −1 yields the quotient 2147483648, which is but not representable as signed 32-bit integer and therefore produces an overflow (really: raises a divide error exception alias #DE) that the Command Processor fails to handle, i.e. neither prevents nor catches for the modulus operator, while it does so for the division operator!

    Note: integer overflow and failure to catch the eventually resulting exception are well-known weaknesses, documented as CWE-190: Integer Overflow or Wraparound and CWE-248: Uncaught Exception in the CWE; they allow well-known attacks like CAPEC-92: Forced Integer Overflow documented in the CAPEC.

  2. Start the Command Processor and execute the following 8 command lines to show surprising behaviour as well as the second stupid bug:

    SET COMSPEC=.
    EXIT | EXIT
    SET COMSPEC=wtf
    EXIT | EXIT
    SET PATHEXT=
    EXIT | EXIT
    SET COMSPEC=
    EXIT | EXIT
    '.' is not recognized as an internal or external command,
    operable program or batch file.
    '.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC' is not recognized as an internal or external command,
    operable program or batch file.
    '' is not recognized as an internal or external command,
    operable program or batch file.
    OUCH²: the Command Processor crashes with an access violation reading address 0x00000000 when an arbitrary builtin command is run in a pipeline and the environment variable COMSPEC is missing!

    Note: properly implemented, the Command Processor would not (ab)use the value of the environment variable COMSPEC to execute builtin commands in the child processes of pipelines, but evaluate its own path name with the Win32 function GetModuleFileName() instead!

    Note: (ab)using environment variables to locate executables is a well-known weakness, documented as CWE-73: External Control of File Name or Path in the CWE; it allows well-known attacks like CAPEC-13: Subverting Environment Variable Values documented in the CAPEC.

    Note: the crash induced by the absence of the environment variable COMSPEC is a well-known weakness too, documented as CWE-248: Uncaught Exception and CWE-476: NULL Pointer Dereference in the CWE.

Case 10

The specification of the PE Format states under the heading The .tls section:
The .tls section provides direct PE and COFF support for static thread local storage (TLS). […] a static TLS variable can be defined as follows, without using the Windows API:

__declspec (thread) int tlsFlag = 1;

To support this programming construct, the PE and COFF .tls section specifies the following information: initialization data, callback routines for per-thread initialization and termination, and the TLS index, which are explained in the following discussion.

Note

Statically declared TLS data objects can be used only in statically loaded image files. This fact makes it unreliable to use static TLS data in a DLL unless you know that the DLL, or anything statically linked with it, will never be loaded dynamically with the LoadLibrary API function.

Executable code accesses a static TLS data object through the following steps:

  1. At link time, the linker sets the Address of Index field of the TLS directory. This field points to a location where the program expects to receive the TLS index.

    The Microsoft run-time library facilitates this process by defining a memory image of the TLS directory and giving it the special name "__tls_used" (Intel x86 platforms) or "_tls_used" (other platforms). The linker looks for this memory image and uses the data there to create the TLS directory. Other compilers that support TLS and work with the Microsoft linker must use this same technique.

  2. When a thread is created, the loader communicates the address of the thread's TLS array by placing the address of the thread environment block (TEB) in the FS register. A pointer to the TLS array is at the offset of 0x2C from the beginning of TEB. This behavior is Intel x86-specific.

  3. The loader assigns the value of the TLS index to the place that was indicated by the Address of Index field.

  4. The executable code retrieves the TLS index and also the location of the TLS array.

  5. The code uses the TLS index and the TLS array location (multiplying the index by 4 and using it as an offset to the array) to get the address of the TLS data area for the given program and module. Each thread has its own TLS data area, but this is transparent to the program, which does not need to know how data is allocated for individual threads.

  6. An individual TLS data object is accessed as some fixed offset into the TLS data area.

Ouch: even the very first (highlighted) sentence is wrong; the IMAGE_TLS_DIRECTORY provides the TLS support.

Note: the .tls section is required only when TLS data is initialised, it is not needed when data is just declared.

Ouch: the initial note is but obsolete and wrong; Windows Vista and later versions of Windows NT support static TLS data in dynamically loaded DLLs!

Note: the multiplier 4 is of course only correct for 32-bit platforms; 64-bit platforms require the multiplier 8.

The documentation misses the following part for the x64 alias AMD64 processor architecture (and corresponding parts for other processor architectures as well):

  1. When a thread is created, the loader communicates the address of the thread's TLS array by placing the address of the thread environment block (TEB) in the GS register. A pointer to the TLS array is at the offset of 0x58 from the beginning of the TEB. This behavior is Intel x64-specific.

Note: despite the fixed value of this offset, the Visual C compiler references the address of the external symbol __tls_array on the i386 alias x86 platform.

The MSDN article PE Format continues:

The TLS directory has the following format:
Offset (PE32/PE32+) Size (PE32/PE32+) Field Description
0 4/8 Raw Data Start VA The starting address of the TLS template. The template is a block of data that is used to initialize TLS data. The system copies all of this data each time a thread is created, so it must not be corrupted. Note that this address is not an RVA; it is an address for which there should be a base relocation in the .reloc section.
4/8 4/8 Raw Data End VA The address of the last byte of the TLS, except for the zero fill. As with the Raw Data Start VA field, this is a VA, not an RVA.
8/16 4/8 Address of Index The location to receive the TLS index, which the loader assigns. This location is in an ordinary data section, so it can be given a symbolic name that is accessible to the program.
12/24 4/8 Address of Callbacks The pointer to an array of TLS callback functions. The array is null-terminated, so if no callback function is supported, this field points to 4 bytes set to zero. For information about the prototype for these functions, see TLS Callback Functions.
16/32 4 Size of Zero Fill The size in bytes of the template, beyond the initialized data delimited by the Raw Data Start VA and Raw Data End VA fields. The total template size should be the same as the total size of TLS data in the image file. The zero fill is the amount of data that comes after the initialized nonzero data.
20/36 4 Characteristics The four bits [23:20] describe alignment info. Possible values are those defined as IMAGE_SCN_ALIGN_*, which are also used to describe alignment of section in object files. The other 28 bits are reserved for future use.
Note: the documentation lacks the information that the Visual C compiler puts all data for the TLS template in COFF sections .tls$‹suffix› – which it declares but writable instead of read-only, i.e. it fails to protect the template data against corruption, an easily avoidable safety hazard!

OOPS: the Raw Data End VA field contains the address of the first byte after the TLS template!

OUCH: the Size of Zero Fill field is not supported at all!

Note: if the size of the initialised data of the .tls section in the image file is less than the section size, the module loader fills the additional uninitialised data with zeroes, i.e. the Size of Zero Fill field is superfluous.

Case 11

The specification of the PE Format states under the heading The Load Configuration Structure (Image Only):
The load configuration structure (IMAGE_LOAD_CONFIG_DIRECTORY) was formerly used in very limited cases in the Windows NT operating system itself to describe various features too difficult or too large to describe in the file header or optional header of the image. Current versions of the Microsoft linker and Windows XP and later versions of Windows use a new version of this structure for 32-bit x86-based systems that include reserved SEH technology.
[…]
The Microsoft linker automatically provides a default load configuration structure to include the reserved SEH data. If the user code already provides a load configuration structure, it must include the new reserved SEH fields. Otherwise, the linker cannot include the reserved SEH data and the image is not marked as containing reserved SEH.
OUCH¹: the highlighted statement is but wrong, LINK.EXE neither provides an IMAGE_LOAD_CONFIG_DIRECTORY structure nor reports its omission with an error message!

The MSDN article /SAFESEH (Image has Safe Exception Handlers) gives the correct information:

If you link with /NODEFAULTLIB and you want a table of safe exception handlers, you need to supply a load config struct (…) that contains all the entries defined for Visual C++. For example:
#include <windows.h>
extern DWORD_PTR __security_cookie;  /* /GS security cookie */

/*
* The following two names are automatically created by the linker for any
* image that has the safe exception table present.
*/

extern PVOID __safe_se_handler_table[]; /* base of safe handler entry table */
extern BYTE  __safe_se_handler_count;  /* absolute symbol whose address is
                                           the count of table entries */

const IMAGE_LOAD_CONFIG_DIRECTORY32 _load_config_used = {
    sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32),
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    &__security_cookie,
    __safe_se_handler_table,
    (DWORD)(DWORD_PTR) &__safe_se_handler_count
};
The specification of the PE format continues with the following desinformation:
Load Configuration Layout

The load configuration structure has the following layout for 32-bit and 64-bit PE files:

Offset Size Field Description
0 4 Characteristics Flags that indicate attributes of the file, currently unused.
[…]
54/78 2 Reserved Must be zero.
OUCH²: the documentation for the IMAGE_LOAD_CONFIG_DIRECTORY structure but states that the field at offset 0 stores the size of the structure, and the field at offset 54 (for 32-bit images) or 78 (for 64-bit images) stores the /DEPENDENTLOADFLAG!

Case 12

The MSDN article /GS (Buffer Security Check) states:
The /GS compiler option requires that the security cookie be initialized before any function that uses the cookie is run. The security cookie must be initialized immediately on entry to an EXE or DLL. This is done automatically if you use the default VCRuntime entry points: mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup, or _DllMainCRTStartup. If you use an alternate entry point, you must manually initialize the security cookie by calling __security_init_cookie.
OOPS¹: contrary to the first highlighted statement, the code generated by the compiler requires only that the (arbitrary) value of the security cookie does not change between entry and exit of any function which uses it!

OOPS²: contrary to the second highlighted statement there is absolutely no need to call the __security_init_cookie() function to (re)initialise the security cookie!

OOPS³: the documentation cited above fails to provide the following (implementation) details:

Case 13

The MSDN article #pragma comment specifies:
Places a comment record into an object file or executable file.

Syntax

#pragma comment( comment-type [ , "comment-string" ] )

Remarks

The comment-type is one of the predefined identifiers, described below, that specifies the type of comment record. The optional comment-string is a string literal that provides additional information for some comment types. Because comment-string is a string literal, it obeys all the rules for string literals on use of escape characters, embedded quotation marks ("), and concatenation.

[…]

linker

Places a linker option in the object file. You can use this comment-type to specify a linker option instead of passing it to the command line or specifying it in the development environment. For example, you can specify the /include option to force the inclusion of a symbol:

#pragma comment(linker, "/include:__mySymbol")
Only the following (comment-type) linker options are available to be passed to the linker identifier:
OUCH: the highlighted statement is misleading and wrong, the compiler accepts arbitrary strings as linker options and writes them into the .drectve section of the object file; the linker but rejects all options except the 6 options cited above plus the 15 options enumerated below with warning LNK4229:
/ALIGN
/ALTERNATENAME
/ASSEMBLYMODULE
/BASE
/CLRTHREADATTRIBUTE
/DLL
/DISALLOWLIB
/ENTRY
/HEAP
/INCREMENTAL
/NODEFAULTLIB
/OUT
/STACK
/SUBSYSTEM
/VERSION

Case 14

Under the heading Remarks, the documentation of the linker option /ENTRY:‹symbol› states:
Remarks

The /ENTRY option specifies an entry point function as the starting address for an .exe file or DLL.

The function must be defined to use the __stdcall calling convention. The parameters and return value depend on if the program is a console application, a windows application or a DLL. It is recommended that you let the linker set the entry point so that the C run-time library is initialized correctly, and C++ constructors for static objects are executed.

By default, the starting address is a function name from the C run-time library. The linker selects it according to the attributes of the program, as shown in the following table.

Function name Default for
mainCRTStartup
(or wmainCRTStartup)
An application that uses /SUBSYSTEM:CONSOLE; calls main (or wmain)
WinMainCRTStartup
(or wWinMainCRTStartup)
An application that uses /SUBSYSTEM:WINDOWS; calls WinMain (or wWinMain), which must be defined to use __stdcall
_DllMainCRTStartup A DLL; calls DllMain if it exists, which must be defined to use __stdcall
If the /DLL or /SUBSYSTEM option is not specified, the linker selects a subsystem and entry point depending on whether main or WinMain is defined.

The functions main, WinMain, and DllMain are the three forms of the user-defined entry point.

Ouch: unfortunately, no prototypes for the entry point functions are given!

Falsification

Perform the following 3 simple steps to prove the highlighted statement of the documentation cited above wrong.
  1. Create the text file wtf.c with the following content in an arbitrary, preferable empty directory:

    // Copyleft © 2001-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define NULL	(void *) 0
    
    extern	struct	_IMAGE_DOS_HEADER	__ImageBase;
    
    typedef	unsigned short	wchar_t;
    
    #ifndef WTF
    #error
    #elif WTF == 0 // DLL
    int	DllMain(void *module, int reason, void *context)
    {
    	return (module != context), (reason == 0);
    }
    #elif WTF == 1 // DLL entry point function
    int	DllMain(void *module, int reason, void *context);
    
    int	_DllMainCRTStartup(void *module, int reason, void *context)
    {
    	return DllMain(module, reason, context);
    }
    #elif WTF == 2 // ANSI console program
    int	main(int argc, char *argv[], char *envp[])
    {
    	return (envp != argv), argc;
    }
    #elif WTF == 3 // ANSI console program entry point function
    int	__cdecl	main(int argc, char *argv[], char *envp[]);
    
    static	char	*argv[] = {"main.exe", "/?", NULL};
    static	char	*envp[] = {"name=value", NULL};
    
    int	mainCRTStartup(void)
    {
    	return main(sizeof(argv) / sizeof(*argv) - 1, argv, envp);
    }
    #elif WTF == 4 // UNICODE console program
    int	wmain(int argc, wchar_t *argv[], wchar_t *envp[])
    {
    	return (envp != argv), argc;
    }
    #elif WTF == 5 // UNICODE console program entry point function
    int	__cdecl	wmain(int argc, wchar_t *argv[], wchar_t *envp[]);
    
    static	wchar_t	*argv[] = {L"wmain.exe", L"/?", NULL};
    static	wchar_t	*envp[] = {L"name=value", NULL};
    
    int	wmainCRTStartup(void)
    {
    	return wmain(sizeof(argv) / sizeof(*argv) - 1, argv, envp);
    }
    #elif WTF == 6 // ANSI Windows program
    int	WinMain(void *current, void *previous, char cmdline[], int cmdshow)
    {
    	return (current != previous), (*cmdline != '\0'), cmdshow;
    }
    #elif WTF == 7 // ANSI Windows program entry point function
    int	WinMain(void *current, void *previous, char cmdline[], int cmdshow);
    
    int	WinMainCRTStartup(void)
    {
    	return WinMain(&__ImageBase, NULL, "/?", 0);
    }
    #elif WTF == 8 // UNICODE Windows program
    int	wWinMain(void *current, void *previous, wchar_t cmdline[], int cmdshow)
    {
    	return (current != previous), (*cmdline != L'\0'), cmdshow;
    }
    #elif WTF == 9 // UNICODE Windows program entry point function
    int	wWinMain(void *current, void *previous, wchar_t cmdline[], int cmdshow);
    
    int	wWinMainCRTStartup(void)
    {
    	return wWinMain(&__ImageBase, NULL, L"/?", 0);
    }
    #endif // WTF
  2. Start the command prompt of the Visual C development environment for the i386 platform, then execute the following 7 command lines to compile the source file wtf.c created in step 1. to generate the 5 object files dllmain.obj, main.obj, wmain.obj, winmain.obj plus wwinmain.obj with the entry point functions and put them into the new object library libcmt.lib:

    SET CL=/c /GAFyz /Oxy /W4 /Zl
    CL.EXE /DWTF=1 /Fodllmain.obj wtf.c
    CL.EXE /DWTF=3 /Fomain.obj wtf.c
    CL.EXE /DWTF=5 /Fowmain.obj wtf.c
    CL.EXE /DWTF=7 /Fowinmain.obj wtf.c
    CL.EXE /DWTF=9 /Fowwinmain.obj wtf.c
    LINK.EXE /LIB /OUT:libcmt.lib dllmain.obj main.obj wmain.obj winmain.obj wwinmain.obj
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) Library Manager Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
  3. Execute the following 6 command lines to compile and (try to) link the source file wtf.c created in step 1. 5 times with the entry point functions from the object library in libcmt.lib created step 2.:

    SET CL=/GAFy /Oxy /W4
    CL.EXE /DWTF=0 /Gz /LD wtf.c
    CL.EXE /DWTF=2 /Gd wtf.c
    CL.EXE /DWTF=4 /Gd wtf.c
    CL.EXE /DWTF=6 /Gz wtf.c
    CL.EXE /DWTF=8 /Gz wtf.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.01
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:wtf.dll
    /dll
    /implib:wtf.lib
    wtf.obj
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:wtf.exe
    wtf.obj
    LINK : error LNK2001: unresolved external symbol _mainCRTStartup
    wtf.exe : fatal error LNK1120: 1 unresolved externals
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:wtf.exe
    wtf.obj
    LINK : error LNK2001: unresolved external symbol _wmainCRTStartup
    wtf.exe : fatal error LNK1120: 1 unresolved externals
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:wtf.exe
    wtf.obj
    LINK : error LNK2001: unresolved external symbol _WinMainCRTStartup
    wtf.exe : fatal error LNK1120: 1 unresolved externals
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    wtf.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:wtf.exe
    wtf.obj
    LINK : error LNK2001: unresolved external symbol _wWinMainCRTStartup
    wtf.exe : fatal error LNK1120: 1 unresolved externals
    OUCH: contrary to the documentation cited above, the linker expects the entry point functions for applications to be defined using the __cdecl calling and naming convention!

Contact

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2024 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>