Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Windows® interfaces with weird behaviour

Purpose

Document functions of Microsoft® Windows NT which exhibit odd, surprising or weird behaviour.

Example 1

Win32 function GetFileMUIInfo():
BOOL GetFileMUIInfo(
  DWORD        dwFlags,
  PCWSTR       pcwszFilePath,
  PFILEMUIINFO pFileMUIInfo,
  DWORD        *pcbFileMUIInfo
);

pFileMUIInfo

Alternatively, the application can set this parameter to NULL if pcbFileMUIInfo is set to 0. In this case, the function retrieves the required size for the information buffer in pcbFileMUIInfo.

pcbFileMUIInfo

Alternatively, the application can set this parameter to 0 if it sets NULL in pFileMUIInfo. In this case, the function retrieves the required file information buffer size in pcbFileMUIInfo. To allocate the correct amount of memory, this value should be added to the size of the FILEMUIINFO structure itself.

This documentation is but wrong and misleading!

The initial call of GetFileMUIInfo() for any module, with address and size of the buffer given as NULL and 0, fails (expected) with error 122 alias ERROR_INSUFFICIENT_BUFFER, but always returns 84 as (additional) buffer size; subsequent calls then return the full buffer size.
The returned (additional or full) buffer size is but not always sufficient; subsequent calls can fail again with error 122 alias ERROR_INSUFFICIENT_BUFFER, so additional calls with the buffer size returned from the previous call are then necessary until the call finally succeeds!

Note: implemented properly, the first call would return the correct (full) buffer size and grant a successful second call, as documented (for example) in the MSDN article Retrieving Data of Unknown Length!

Demonstration

  1. Create the text file example1.c with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2009-2018, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #pragma comment(compiler)
    #pragma comment(linker, "/DEFAULTLIB:KERNEL32.LIB")
    #pragma comment(linker, "/DEFAULTLIB:USER32.LIB")
    #pragma comment(linker, "/ENTRY:wmainCRTStartup")
    #pragma comment(linker, "/SUBSYSTEM:CONSOLE")
    #pragma comment(user, __TIMESTAMP__)
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    __declspec(safebuffers)
    BOOL	PrintConsole(LPCWSTR lpFormat, ...)
    {
    	WCHAR	szBuffer[1025];
    	DWORD	dwBuffer;
    	DWORD	dwWritten;
    
    	va_list	vaInserts;
    	va_start(vaInserts, lpFormat);
    
    	dwBuffer = wvsprintf(szBuffer, lpFormat, vaInserts);
    
    	va_end(vaInserts);
    
    	if (dwBuffer == 0L)
    		return FALSE;
    
    	if (!WriteConsole(GetStdHandle(STD_ERROR_HANDLE), szBuffer, dwBuffer, &dwWritten, NULL))
    		return FALSE;
    
    	return dwWritten == dwBuffer;
    }
    
    const	WCHAR	szModule[] = L"C:\\Windows\\RegEdit.exe";
    
    __declspec(noreturn)
    VOID	WINAPI	wmainCRTStartup(VOID)
    {
    	PFILEMUIINFO	lpFileMUIInfo = NULL;
    	DWORD		dwFileMUIInfo = 0L;
    	DWORD		dwError = ERROR_SUCCESS;
    
    	if (GetFileMUIInfo(MUI_QUERY_CHECKSUM | MUI_QUERY_LANGUAGE_NAME | MUI_QUERY_RESOURCE_TYPES | MUI_QUERY_TYPE,
    	                   szModule, lpFileMUIInfo, &dwFileMUIInfo))
    		PrintConsole(L"GetFileMUIInfo() returned success %lu and buffer size %lu for module \'%ls\'\n",
    		             dwError = GetLastError(), dwFileMUIInfo, szModule);
    	else
    	{
    		PrintConsole(L"GetFileMUIInfo() returned error %lu and buffer size %lu for module \'%ls\'\n",
    		             dwError = GetLastError(), dwFileMUIInfo, szModule);
    
    		dwFileMUIInfo += sizeof(FILEMUIINFO);
    
    		while (dwError == ERROR_INSUFFICIENT_BUFFER)
    		{
    			lpFileMUIInfo = LocalAlloc(LPTR, dwFileMUIInfo);
    
    			if (lpFileMUIInfo == NULL)
    				PrintConsole(L"LocalAlloc() returned error %lu\n",
    				             dwError = GetLastError());
    			else
    			{
    				lpFileMUIInfo->dwSize = dwFileMUIInfo;
    				lpFileMUIInfo->dwVersion = MUI_FILEINFO_VERSION;
    
    				if (GetFileMUIInfo(MUI_QUERY_CHECKSUM | MUI_QUERY_LANGUAGE_NAME | MUI_QUERY_RESOURCE_TYPES | MUI_QUERY_TYPE,
    				                   szModule, lpFileMUIInfo, &dwFileMUIInfo))
    					PrintConsole(L"GetFileMUIInfo() returned success %lu and buffer size %lu for module \'%ls\'\n",
    					             dwError = GetLastError(), dwFileMUIInfo, szModule);
    				else
    					PrintConsole(L"GetFileMUIInfo() returned error %lu and buffer size %lu for module \'%ls\'\n",
    					             dwError = GetLastError(), dwFileMUIInfo, szModule);
    
    				if (LocalFree(lpFileMUIInfo) != NULL)
    					PrintConsole(L"LocalFree() returned error %lu\n",
    					             GetLastError());
    			}
    		}
    	}
    
    	ExitProcess(dwError);
    }
    
  2. Build the application example1.exe from the source file example1.c created in step 1.:

    CL.EXE /GA /GF /Tcexample1.c /W4 /Zl
    Note: the application builds without the MSVCRT libraries.
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    example1.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:example1.exe
    example1.obj
    
  3. Execute the application example1.exe built in step 2. to demonstrate the weird behaviour of the Win32 function GetFileMUIInfo():

    example1.exe
    GetFileMUIInfo() returned error 122 and buffer size 84 for module 'C:\Windows\RegEdit.exe'
    GetFileMUIInfo() returned error 122 and buffer size 166 for module 'C:\Windows\RegEdit.exe'
    GetFileMUIInfo() returned error 122 and buffer size 180 for module 'C:\Windows\RegEdit.exe'
    GetFileMUIInfo() returned success 0 and buffer size 180 for module 'C:\Windows\RegEdit.exe'

Contact

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, errors, inaccuracies, omissions, 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.

Notes: 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!
Emails in weird formats and without a proper sender name are likely to be discarded.
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 data and sets no cookies.

The service provider for *.homepage.t-online.de, Deutsche Telekom AG,


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