Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Tidbits – Tiny Console Applications plus some Scripts

Click the appropriate button to select and display your tidbit, or the last (empty) button to reset your selection and hide the tidbit.

All console applications are presented with their (self-contained) ANSI C source code and build without the MSVCRT runtime library.

Group Policy Scripts Client Registration

Privileged Process Launcher Interactive SYSTEM Process Launcher Privilege Twiddler

Really Known SIDs Enumerator Security Descriptor Definition Language Decoder

Security Descriptor Inspector 8.3 File and Directory Name Changer Directory Change Notifier

Debug String Monitor Non-interactive Symbolic Debugger Shim Database Decoder

Registry Policy Reader Registry INF Dumper Offline Registry Reader

Portable Executable Version Information Reader Portable Executable Resource Enumerator

Portable Executable Metadata Reader Product Key Validator

UU Encoder Base64 Encoder

MSVC Helper Library  • 

Privileged Process Launcher

Purpose
Background Information
Demonstration

Purpose

Launch an arbitrary process with arbitrary command line, customised environment variables and arbitrary privileges enabled in an arbitrary working directory.

Note: only privileges already assigned to a user account can be enabled!

Background Information

The TechNet articles User Rights and Configuring User Rights as well as the MSDN article Privileges provide background information.

Demonstration

Perform the following two simple steps to launch the Command Processor Cmd.exe with the privileges SeAuditPrivilege, SeBackupPrivilege, SeDebugPrivilege, SeRestorePrivilege, SeSecurityPrivilege and SeTakeOwnershipPrivilege enabled in the directory C:\System Volume Information\ and list its contents.
  1. Create the text file PROCESS.VBS with the following content in an arbitrary directory:

    Rem Copyright © 1999-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    Rem * The software is provided "as is" without any warranty, neither express
    Rem   nor implied.
    Rem * In no event will the author be held liable for any damage(s) arising
    Rem   from the use of the software.
    Rem * Redistribution of the software is allowed only in unmodified form.
    Rem * Permission is granted to use the software solely for personal private
    Rem   and non-commercial purposes.
    Rem * An individuals use of the software in his or her capacity or function
    Rem   as an agent, (independent) contractor, employee, member or officer of
    Rem   a business, corporation or organization (commercial or non-commercial)
    Rem   does not qualify as personal private and non-commercial purpose.
    Rem * Without written approval from the author the software must not be used
    Rem   for a business, for commercial, corporate, governmental, military or
    Rem   organizational purposes of any kind, or in a commercial, corporate,
    Rem   governmental, military or organizational environment of any kind.
    
    Option Explicit
    
    Const strCommandLine = "C:\Windows\System32\Cmd.exe /D /K DIR /A"
    Const strCurrentDirectory = "C:\System Volume Information"
    
    Dim arrEnvironment(10)
    arrEnvironment(0) = "NoDefaultCurrentDirectoryInExePath=*"
    
    With WScript.CreateObject("Scripting.FileSystemObject")
    	Const fsoWindowsFolder   = 0
    	Const fsoSystemFolder    = 1
    	Const fsoTemporaryFolder = 2
    
    	arrEnvironment(1) = "SYSTEMDRIVE=" & .GetSpecialFolder(fsoWindowsFolder).Drive
    	arrEnvironment(2) = "SYSTEMROOT=" & .GetSpecialFolder(fsoWindowsFolder).Path
    	arrEnvironment(3) = "PATH=" & .GetSpecialFolder(fsoSystemFolder).Path & ";" & .GetSpecialFolder(fsoWindowsFolder).Path
    	arrEnvironment(4) = "TEMP=" & .GetSpecialFolder(fsoTemporaryFolder).Path
    	arrEnvironment(5) = "LOCALAPPDATA=" & .GetSpecialFolder(fsoTemporaryFolder).ParentFolder.Path
    	arrEnvironment(6) = "USERPROFILE=" & .GetSpecialFolder(fsoTemporaryFolder).ParentFolder.ParentFolder.ParentFolder.Path
    End With
    
    With WScript.CreateObject("WScript.Network")
    	arrEnvironment(7) = "COMPUTERNAME=" & .ComputerName
    	arrEnvironment(8) = "USERDOMAIN=" & .UserDomain
    	arrEnvironment(9) = "USERNAME=" & .UserName
    End With
    
    With GetObject("WinMgmts:{impersonationLevel=Impersonate, (Audit, Backup, Debug, Restore, Security, TakeOwnership)}!\\.\Root\CIMv2")
    	Dim objProcessStartup
    	Set objProcessStartup = .Get("Win32_ProcessStartup").SpawnInstance_
    	With objProcessStartup
    	'	.CreateFlags = 8	' Detached_Process
    		.EnvironmentVariables = arrEnvironment
    		.ErrorMode = 2		' Fail_Critical_Errors
    		.FillAttribute = 240	' Black on White
    		.PriorityClass = 32	' Normal
    		.ShowWindow = 1		' SW_NORMAL
    		.Title = vbNullString
    		.WinstationDesktop = vbNullString
    	'	.X = 0
    		.XCountChars = 80
    	'	.XSize = 640
    	'	.Y = 240
    		.YCountChars = 50
    	'	.YSize = 480
    	End With
    
    	Dim intReturn, intProcessID
    	intReturn = .Get("Win32_Process").Create(strCommandLine, strCurrentDirectory, objProcessStartup, intProcessID)
    	If intReturn <> 0 Then
    		WScript.Echo "Error " & intReturn
    	Else
    		WScript.Echo "Process " & intProcessID & " created"
    	End If
    End With
  2. Execute the VBScript PROCESS.VBS created in step 1. per double-click.

    Note: PROCESS.VBS must be run under a user account which has the privileges to enable assigned, typically any member of the BUILTIN\Administrators user group!

Group Policy Scripts

Purpose
Operation

Purpose

Add startup, shutdown, logon and logoff scripts (really: arbitrary command lines, which are executed during shutdown, startup, logoff and logon) programmatically, without a Group Policy, using just what’s already installed with Windows NT.

Note: startup and shutdown scripts run under the NT AUTHORITY\SYSTEM alias LocalSystem account; logon and logoff scripts run under the current user account.

Operation

Download the setup script SCRIPTS.INF and save it in an arbitrary directory, then right-click the downloaded file to display its context menu and click Install to run it.

Note: on Windows Vista and newer versions of Windows NT, InfDefaultInstall.exe, the application registered for the Install verb of *.inf files, requests administrative privileges and access rights.

Client Registration

Purpose
Background Information
Operation

Purpose

Demonstrate how to add an additional WWW browser, an additional USENET news reader, an additional mail client and an additional calendar with all bells and whistles so that Windows 2000 and newer versions of Windows NT recognise them as fully functional client programs which can be selected by every user as the default program for their associated file types and URL protocols.

Background Information

The MSDN article Default Programs provides background information.

Operation

Download the setup script CLIENTS.INF and save it in an arbitrary directory, then right-click the downloaded file to display its context menu and click Install to run it.

Note: on Windows Vista and newer versions of Windows NT, InfDefaultInstall.exe, the application registered for the Install verb of *.inf files, requests administrative privileges.

Shim Database Decoder

Purpose
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Decode an Application Compatibility Shim Database (.sdb) file and print its contents in UTF-16LE encoding on standard output (which must be redirected to a file or piped into an application that reads from standard input, like Clip, Find or More).

Synopsis

APPHELP.COM ‹input file name› >‹output file name›
APPHELP.COM ‹input file name› | CLIP.COM
APPHELP.COM ‹input file name› | MORE.COM

Downloads

The console application is available in two functional identical forms: APPHELP.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and APPHELP.COM, a small form without these extras.

Implementation and Build Details

Shim Database Decoder is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following three simple steps to build the console application Shim Database Decoder from the source presented hereafter.
  1. Create the text file APPHELP.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #ifndef _DLL
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    typedef	enum	_PATH_TYPE
    {
    	DOS_PATH,
    	NT_PATH
    } PATH_TYPE;
    
    #define PATCH_STOP	0UL
    #define PATCH_REPLACE	2UL
    #define PATCH_MATCH	4UL
    
    typedef	struct	_PATCH_ACTION
    {
    	DWORD	Opcode;
    	DWORD	ActionSize;		// size of structure
    	DWORD	PatternSize;
    	DWORD	RVA;
    	DWORD	Reserved;
    	WCHAR	ModuleName[32];
    	BYTE	Pattern[ANYSIZE_ARRAY];
    } PATCH_ACTION, *LPPATCH_ACTION;
    
    typedef	LPVOID	PDB;
    
    typedef	ULONGLONG	QWORD;
    
    typedef WORD	TAG;
    
    #define TAG_TYPE_NULL		0x1000	// no value associated with the TAG
    #define TAG_TYPE_BYTE		0x2000	// BYTE value
    #define TAG_TYPE_WORD		0x3000	// WORD value
    #define TAG_TYPE_DWORD		0x4000	// DWORD value
    #define TAG_TYPE_QWORD		0x5000	// ULONGLONG value
    #define TAG_TYPE_STRINGREF	0x6000	// tokenized string value
    #define TAG_TYPE_LIST		0x7000	// list of TAG values
    #define TAG_TYPE_STRING		0x8000	// UNICODE string value
    #define TAG_TYPE_BINARY		0x9000	// binary value
    #define TAG_TYPE_MASK		0xF000
    
    #define TAG_LINK_DATE			(TAG_TYPE_DWORD | 0x001D)	// link date attribute of a file
    #define TAG_UPTO_LINK_DATE		(TAG_TYPE_DWORD | 0x001E)	// link date attribute of a file; matching is done up to and including this link date
    #define TAG_APP_NAME_RC_ID		(TAG_TYPE_DWORD | 0x0024)	// application name resource identifier attribute for AppHelp entries
    #define TAG_VENDOR_NAME_RC_ID		(TAG_TYPE_DWORD | 0x0025)	// vendor name resource identifier attribute for AppHelp entries
    #define TAG_SUMMARY_MSG_RC_ID		(TAG_TYPE_DWORD | 0x0026)	// summary message resource identifier attribute for AppHelp entries
    #define TAG_DESCRIPTION_RC_ID		(TAG_TYPE_DWORD | 0x0028)	// description resource identifier attribute for AppHelp entries
    #define TAG_PARAMETER1_RC_ID		(TAG_TYPE_DWORD | 0x0029)	// parameter1 resource identifier attribute for AppHelp entries
    
    #define TAG_TIME			(TAG_TYPE_QWORD | 0x0001)	// time attribute
    #define TAG_BIN_FILE_VERSION		(TAG_TYPE_QWORD | 0x0002)	// bin file version attribute for file entries
    #define TAG_BIN_PRODUCT_VERSION		(TAG_TYPE_QWORD | 0x0003)	// bin product version attribute for file entries
    #define TAG_UPTO_BIN_PRODUCT_VERSION	(TAG_TYPE_QWORD | 0x0006)	// bin product version attribute of a file; matching is done up to and including this product version
    #define TAG_UPTO_BIN_FILE_VERSION	(TAG_TYPE_QWORD | 0x000D)	// bin file version attribute of a file; matching is done up to and including this file version
    
    #define TAG_PATCH_BITS			(TAG_TYPE_BINARY | 0x0002)	// patch file bits attribute
    #define TAG_EXE_ID			(TAG_TYPE_BINARY | 0x0004)	// GUID attribute of an executable entry
    #define TAG_MSI_PACKAGE_ID		(TAG_TYPE_BINARY | 0x0006)	// MSI package identifier attribute of an MSI package
    #define TAG_DATABASE_ID			(TAG_TYPE_BINARY | 0x0007)	// GUID attribute of a database
    #define TAG_CONTEXT_PLATFORM_ID		(TAG_TYPE_BINARY | 0x0008)
    #define TAG_CONTEXT_BRANCH_ID		(TAG_TYPE_BINARY | 0x0009)
    #define TAG_FIX_ID			(TAG_TYPE_BINARY | 0x0010)
    #define TAG_APP_ID			(TAG_TYPE_BINARY | 0x0011)
    
    typedef DWORD	TAGID;
    
    #define TAGID_NULL	0UL
    #define TAGID_ROOT	0UL
    
    __declspec(dllimport)
    VOID	WINAPI	SdbCloseDatabase(PDB lpdb);
    
    __declspec(dllimport)
    LPVOID	WINAPI	SdbGetBinaryTagData(PDB   lpdb,
    		                    TAGID tiWhich);
    
    __declspec(dllimport)
    BOOL	WINAPI	SdbGetDatabaseVersion(LPCWSTR lpwszFileName,
    		                      LPDWORD dwMajorversion,
    		                      LPDWORD dwMinorversion);
    
    __declspec(dllimport)
    TAGID	WINAPI	SdbGetFirstChild(PDB   lpdb,
    		                 TAGID tiParent);
    
    __declspec(dllimport)
    TAGID	WINAPI	SdbGetNextChild(PDB   lpdb,
    		                TAGID tiParent,
    		                TAGID tiPrevious);
    
    __declspec(dllimport)
    LPWSTR	WINAPI	SdbGetStringTagPtr(PDB   lpdb,
    		                   TAGID tiWhich);
    
    __declspec(dllimport)
    DWORD	WINAPI	SdbGetTagDataSize(PDB   lpdb,
    		                  TAGID tiWhich);
    
    __declspec(dllimport)
    TAG	WINAPI	SdbGetTagFromTagID(PDB   lpdb,
    		                   TAGID tiWhich);
    
    __declspec(dllimport)
    BOOL	WINAPI	SdbGUIDToString(GUID   *lpGuid,
    		                LPWSTR lpwszGuidString);
    
    __declspec(dllimport)
    PDB	WINAPI	SdbOpenDatabase(LPCWSTR   lpwszPath,
    		                PATH_TYPE eType);
    
    __declspec(dllimport)
    DWORD	WINAPI	SdbReadDWORDTag(PDB   lpdb,
    		                TAGID tiWhich,
    		                DWORD dwDefault);
    
    __declspec(dllimport)
    QWORD	WINAPI	SdbReadQWORDTag(PDB   lpdb,
    		                TAGID tiWhich,
    		                QWORD qwDefault);
    
    __declspec(dllimport)
    WORD	WINAPI	SdbReadWORDTag(PDB   lpdb,
    		               TAGID tiWhich,
    		               WORD  wDefault);
    
    __declspec(dllimport)
    LPCWSTR	WINAPI	SdbTagToString(TAG tag);
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	LPBYTE	lpOutput;
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	dwOutput *= sizeof(*szOutput);
    	lpOutput = (LPBYTE) szOutput;
    
    	do
    	{
    		if (!WriteFile(hFile, lpOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpOutput += dwFile;
    		dwOutput -= dwFile;
    	} while (dwOutput != 0);
    
    	return TRUE;
    }
    
    #define PrintString(HANDLE, LITERAL)	PrintDirect(HANDLE, LITERAL, sizeof(LITERAL) / sizeof(*LITERAL) - 1)
    
    __inline
    BOOL	WINAPI	PrintDirect(HANDLE hFile, LPCWSTR lpString, DWORD dwString)
    {
    	DWORD	dwFile;
    
    	dwString *= sizeof(*lpString);
    
    	do
    	{
    		if (!WriteFile(hFile, lpString, dwString, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpString = (LPCWSTR) ((LPBYTE) lpString + dwFile);
    		dwString -= dwFile;
    	} while (dwString != 0);
    
    	return TRUE;
    }
    
    const	LPCWSTR	szDayOfWeek[7] = {L"Sunday",
    		                  L"Monday",
    		                  L"Tuesday",
    		                  L"Wednesday",
    		                  L"Thursday",
    		                  L"Friday",
    		                  L"Saturday"};
    
    __declspec(safebuffers)
    VOID	WINAPI	Children(HANDLE hConsole, HANDLE hOutput, PDB lpdb, TAGID tiParent, DWORD dwLevel)
    {
    	SYSTEMTIME	st;
    	PATCH_ACTION	*lpPatch;
    
    	BOOL	bOutput = TRUE;
    	DWORD	dw;
    	LPBYTE	lpData;
    	WORD	wData;
    	DWORD	dwData;
    	QWORD	qwData;
    	WCHAR	szGUID[sizeof("{00000000-0000-0000-0000-000000000000}")];
    	TAG	tChild;
    	TAGID	tiChild = SdbGetFirstChild(lpdb, tiParent);
    
    	while (tiChild != TAGID_NULL)
    	{
    		tChild = SdbGetTagFromTagID(lpdb, tiChild);
    
    		bOutput &= PrintFormat(hOutput,
    		                       L"0x%08lX%ls0x%04hX = %ls",
    		                       tiChild,
    		                       L"\t\t\t\t\t\t\t\t\t\t" + 9 - dwLevel,
    		                       tChild,
    		                       SdbTagToString(tChild));
    
    		switch (tChild & TAG_TYPE_MASK)
    		{
    		case TAG_TYPE_NULL:
    
    			bOutput &= PrintString(hOutput, L"\r\n");
    
    			break;
    
    		case TAG_TYPE_WORD:
    
    			wData = SdbReadWORDTag(lpdb, tiChild, ~0U);
    
    			if (wData == ~0U)
    				bOutput &= PrintString(hOutput, L"\r\n");
    			else
    				bOutput &= PrintFormat(hOutput, L": 0x%04hX\r\n", wData);
    			break;
    
    		case TAG_TYPE_DWORD:
    
    			dwData = SdbReadDWORDTag(lpdb, tiChild, ~0UL);
    
    			if (dwData == ~0UL)
    				bOutput &= PrintString(hOutput, L"\r\n");
    			else
    				if ((tChild == TAG_LINK_DATE)
    				 || (tChild == TAG_UPTO_LINK_DATE))
    				{
    					qwData = __emulu(dwData, 10000000)	// seconds since 1970-01-01 to
    					       + 116444736000000000;		//  100 nano-seconds since 1601-01-01
    
    					if (!FileTimeToSystemTime((LPFILETIME) &qwData, &st))
    						PrintConsole(hConsole,
    						             L"FileTimeToSystemTime() returned error %lu\n",
    						             GetLastError());
    					else
    						bOutput &= PrintFormat(hOutput,
    						                       L": %ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu.%03hu UTC\r\n",
    						                       szDayOfWeek[st.wDayOfWeek],
    						                       st.wYear, st.wMonth, st.wDay, st.wHour,
    						                       st.wMinute, st.wSecond, st.wMilliseconds);
    				}
    #if 0	// NOTE: Windows Vista or newer!
    				else if ((tChild == TAG_APP_NAME_RC_ID)
    				      || (tChild == TAG_VENDOR_NAME_RC_ID)
    				      || (tChild == TAG_SUMMARY_MSG_RC_ID)
    				      || (tChild == TAG_DESCRIPTION_RC_ID)
    				      || (tChild == TAG_PARAMETER1_RC_ID))
    					bOutput &= PrintFormat(hOutput, L": 0x%08lX\r\n", dwData);
    #endif
    				else
    					bOutput &= PrintFormat(hOutput, L": 0x%08lX\r\n", dwData);
    			break;
    
    		case TAG_TYPE_QWORD:
    
    			qwData = SdbReadQWORDTag(lpdb, tiChild, ~0ULL);
    
    			if (qwData == ~0ULL)
    				bOutput &= PrintString(hOutput, L"\r\n");
    			else
    				if ((tChild == TAG_BIN_FILE_VERSION)
    				 || (tChild == TAG_BIN_PRODUCT_VERSION)
    				 || (tChild == TAG_UPTO_BIN_PRODUCT_VERSION)
    				 || (tChild == TAG_UPTO_BIN_FILE_VERSION))
    					bOutput &= PrintFormat(hOutput,
    					                       L": %hu.%hu.%hu.%hu\r\n",
    					                       (WORD) (qwData >> 48), (WORD) (qwData >> 32), (WORD) (qwData >> 16), (WORD) qwData);
    				else if (tChild != TAG_TIME)
    					bOutput &= PrintFormat(hOutput, L": 0x%016I64X\r\n", qwData);
    				else
    					if (!FileTimeToSystemTime((LPFILETIME) &qwData, &st))
    						PrintConsole(hConsole,
    						             L"FileTimeToSystemTime() returned error %lu\n",
    						             GetLastError());
    					else
    						bOutput &= PrintFormat(hOutput,
    						                       L": %ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu.%03hu UTC\r\n",
    						                       szDayOfWeek[st.wDayOfWeek],
    						                       st.wYear, st.wMonth, st.wDay, st.wHour,
    						                       st.wMinute, st.wSecond, st.wMilliseconds);
    			break;
    
    		case TAG_TYPE_STRING:
    		case TAG_TYPE_STRINGREF:
    
    			bOutput &= PrintFormat(hOutput,
    			                       L": %ls\r\n",
    			                       SdbGetStringTagPtr(lpdb, tiChild));
    			break;
    
    		case TAG_TYPE_BYTE:
    		case TAG_TYPE_BINARY:
    
    			lpData = SdbGetBinaryTagData(lpdb, tiChild);
    			dwData = SdbGetTagDataSize(lpdb, tiChild);
    
    			if ((dwData == sizeof(GUID))
    			 && ((tChild == TAG_EXE_ID)
    			  || (tChild == TAG_MSI_PACKAGE_ID)
    			  || (tChild == TAG_DATABASE_ID)
    			  || (tChild == TAG_CONTEXT_PLATFORM_ID)
    			  || (tChild == TAG_CONTEXT_BRANCH_ID)
    			  || (tChild == TAG_FIX_ID)
    			  || (tChild == TAG_APP_ID)))
    				if (!SdbGUIDToString((LPGUID) lpData, szGUID))
    					PrintConsole(hConsole,
    					             L"SdbGUIDToString() failed!\n");
    				else
    					bOutput &= PrintFormat(hOutput, L": %ls\r\n", szGUID);
    			else if (tChild == TAG_PATCH_BITS)
    			{
    				bOutput &= PrintString(hOutput, L":\r\n");
    
    				while (dwData > 0)
    				{
    					lpPatch = (LPPATCH_ACTION) lpData;
    
    					if ((lpPatch->Opcode == PATCH_STOP)
    					 && (lpPatch->ActionSize == 0))
    						break;
    
    					dwData -= lpPatch->ActionSize;
    					lpData += lpPatch->ActionSize;
    
    					if ((lpPatch->Opcode != PATCH_REPLACE)
    					 && (lpPatch->Opcode != PATCH_MATCH))
    						continue;
    
    					bOutput &= PrintFormat(hOutput,
    					                       L"%ls Action  = %lu (%ls)\r\n"
    					                       L"%ls Module  = %.32ls\r\n"
    					                       L"%ls RVA     = 0x%08lX\r\n"
    					                       L"%ls Length  = %lu\r\n"
    					                       L"%ls Pattern = 0x",
    					                       L"\t\t\t\t\t\t\t\t\t\t" + 7 - dwLevel,
    					                       lpPatch->Opcode,
    					                       lpPatch->Opcode == PATCH_MATCH ? L"MATCH" : L"REPLACE",
    					                       L"\t\t\t\t\t\t\t\t\t\t" + 7 - dwLevel,
    					                       lpPatch->ModuleName,
    					                       L"\t\t\t\t\t\t\t\t\t\t" + 7 - dwLevel,
    					                       lpPatch->RVA,
    					                       L"\t\t\t\t\t\t\t\t\t\t" + 7 - dwLevel,
    					                       lpPatch->PatternSize,
    					                       L"\t\t\t\t\t\t\t\t\t\t" + 7 - dwLevel);
    
    					for (dw = 0; dw < lpPatch->PatternSize; dw++)
    						bOutput &= PrintFormat(hOutput, L"%02X", lpPatch->Pattern[dw]);
    
    					bOutput &= PrintFormat(hOutput,
    					                       L"\r\n"
    					                       L"%ls Unknown = 0x%08lX\r\n",
    					                       L"\t\t\t\t\t\t\t\t\t\t" + 7 - dwLevel,
    					                       lpPatch->Reserved);
    				}
    #if 0
    				if (dwData != 8)
    					PrintConsole(hConsole,
    					             L"Sequence of \'PATCH_ACTION\' structures not properly terminated!\n");
    #endif
    			}
    			else
    			{
    				if (dwData > 0)
    					bOutput &= PrintString(hOutput, L": 0x");
    
    				for (dw = 0; dw < dwData; dw++)
    					bOutput &= PrintFormat(hOutput, L"%02X", lpData[dw]);
    
    				bOutput &= PrintString(hOutput, L"\r\n");
    			}
    
    			break;
    
    		case TAG_TYPE_LIST:
    
    			bOutput &= PrintString(hOutput, L"\r\n");
    
    			Children(hConsole, hOutput, lpdb, tiChild, dwLevel + 1);
    
    			break;
    
    		default:
    			bOutput &= PrintString(hOutput, L"\r\n");
    
    			PrintConsole(hConsole,
    			             L"Undefined TAG_TYPE 0x%04hX for TAGID 0x%08lX\n",
    			             tChild, tiChild);
    		}
    
    		tiChild = SdbGetNextChild(lpdb, tiParent, tiChild);
    	}
    
    	if (!bOutput)
    		PrintConsole(hConsole,
    		             L"WriteFile() returned error %lu for level %lu\n",
    		             GetLastError(), dwLevel);
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	PDB	lpdb;
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwMajor, dwMinor;
    	HANDLE	hOutput;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments != 2)
    				PrintConsole(hConsole,
    				             L"Bad arguments: a single file or path name of a shim database must be given!\n");
    			else
    			{
    				hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    				if (hOutput == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"GetStdHandle() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!FlushFileBuffers(hOutput))
    						PrintConsole(hConsole,
    						             L"FlushFileBuffers() returned error %lu: standard output is not redirected to a file!\n",
    						             dwError = GetLastError());
    					else
    					{
    						dwError = ERROR_SUCCESS;
    
    						if (SdbGetDatabaseVersion(lpArguments[1], &dwMajor, &dwMinor))
    							PrintConsole(hConsole,
    							             L"Shim database version: %lu.%lu\n",
    							             dwMajor, dwMinor);
    
    						lpdb = SdbOpenDatabase(lpArguments[1], DOS_PATH);
    
    						if (lpdb == NULL)
    							PrintConsole(hConsole,
    							             L"SdbOpenDatabase() returned NULL for file \'%ls\'\n",
    							             lpArguments[1]);
    						else
    						{
    							if (!PrintFormat(hOutput,
    							                 L"\xFEFF"	// UTF-16LE BOM
    							                 L"Shim database file:\t%ls\r\n"
    							                 L"Shim database version:\t%lu.%lu\r\n"
    							                 L"\r\n"
    							                 L"TAGID\t\tTAG    = TAGSTRING: TAGVALUE\r\n"
    							                 L"\r\n",
    							                 lpArguments[1],
    							                 dwMajor, dwMinor))
    								PrintConsole(hConsole,
    								             L"WriteFile() returned error %lu\n",
    								             dwError = GetLastError());
    
    							Children(hConsole, hOutput, lpdb, TAGID_ROOT, 0);
    
    							SdbCloseDatabase(lpdb);
    						}
    					}
    
    					if (!CloseHandle(hOutput))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
    #else // _DLL
    __declspec(dllexport)
    long	SdbCloseDatabase(void *_1)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGetBinaryTagData(void *_1, long _2)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGetDatabaseVersion(void *_1, void *_2, void *_3)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGetFirstChild(void *_1, long _2)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGetNextChild(void *_1, long _2, long _3)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGetStringTagPtr(void *_1, long _2)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGetTagDataSize(void *_1, long _2)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGetTagFromTagID(void *_1, long _2)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbGUIDToString(void *_1, void *_2)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbOpenDatabase(void *_1, long _2)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbReadDWORDTag(void *_1, long _2, long _3)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbReadQWORDTag(void *_1, long _2, long long _3)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbReadWORDTag(void *_1, long _2, short _3)
    { return 0; }
    
    __declspec(dllexport)
    long	SdbTagToString(short _1)
    { return 0; }
    #endif // _DLL
  2. Run the following four command lines to compile the source file APPHELP.C created in step 1. a first time, generate the import library APPHELP.LIB from the compiled object file APPHELP.OBJ and cleanup afterwards:

    SET CL=/Gz /LD /MD /W4 /wd4100 /X /Zl
    SET LINK=/EXPORT:SdbCloseDatabase /EXPORT:SdbGetBinaryTagData /EXPORT:SdbGetDatabaseVersion /EXPORT:SdbGetFirstChild /EXPORT:SdbGetNextChild /EXPORT:SdbGetStringTagPtr /EXPORT:SdbGetTagDataSize /EXPORT:SdbGetTagFromTagID /EXPORT:SdbGUIDToString /EXPORT:SdbOpenDatabase /EXPORT:SdbReadDWORDTag /EXPORT:SdbReadQWORDTag /EXPORT:SdbReadWORDTag /EXPORT:SdbTagToString /NODEFAULTLIB /NOENTRY
    CL.EXE APPHELP.C
    ERASE APPHELP.DLL APPHELP.EXP APPHELP.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    APPHELP.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …
       Creating library APPHELP.lib and object APPHELP.exp
  3. Run the following four command lines to compile the source file APPHELP.C created in step 1. a second time, link the compiled object file APPHELP.OBJ with the import library APPHELP.LIB generated in step 2. and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.1 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeAPPHELP.COM APPHELP.C APPHELP.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE APPHELP.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    APPHELP.C
    APPHELP.C(222) : warning C4213: nonstandard extension used : cast on l-value
    APPHELP.C(274) : warning C4310: cast truncates constant value
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Non-interactive Symbolic Debugger

Purpose
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Execute another Win32 application as debuggee and log all Debugging Events encountered during its run.

Synopsis

DEBUGGER.COM [ ‹debuggee› ] ‹quoted command line›
Note: the optional first argument is the absolute or relative path name of the debuggee; when omitted, the first token of the then first and only argument, a properly quoted command line, is used as file name of the debuggee and searched in the PATH.

Demonstration

Execute the Command Processor Cmd.exe as debuggee and use a 28 (in words: twenty-eight) year old bug to let it crash with an unhandled integer overflow exception raised from the division ~2147483647 ÷ ~0 = −2147483648 ÷ −1 = 2147483648:
VER
.\DEBUGGER.COM "%COMSPEC%" "CMD /E:ON /D /C SET /A ~2147483647 % ~0"
Microsoft Windows [Version 10.0.19044.2486]

Command line:     'CMD /E:ON /D /C SET /A ~2147483647 % ~0'
Application name: 'C:\Windows\system32\cmd.exe'
Application type: 0 = 32-bit Windows

DbgHelp API:
	Version  = 4.0
	Revision = 5
	Reserved = 0

Debuggee process loaded from image file 'C:\Windows\SysWOW64\cmd.exe'
Debuggee process version is 10.0
Debuggee process 14052 with primary thread 11164 created

Process 14052 created with primary thread 11164:
Symbol search path: .
	Process filename = C:\Windows\SysWOW64\cmd.exe
	Base address     = 0x00220000
	Start address    = 0x00236B20
	TEB address      = 0x02A5F000

DLL loaded in process 14052 by thread 11164:
SymRefreshModuleList() returned error 0x8000000D
ReadProcessMemory() returned error 299
	Base address   = 0x77AF0000

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\KERNEL32.DLL
	Base address   = 0x75B80000	KERNEL32

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\KERNELBASE.dll
	Base address   = 0x77890000	KERNELBASE

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\ADVAPI32.DLL
	Base address   = 0x76AF0000	ADVAPI32

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\msvcrt.dll
	Base address   = 0x77710000	msvcrt

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\sechost.dll
	Base address   = 0x77480000	sechost

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\RPCRT4.dll
	Base address   = 0x75DC0000	RPCRT4

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\combase.dll
	Base address   = 0x75F10000	combase

DLL loaded in process 14052 by thread 11164:
	DLL filename   = C:\Windows\SysWOW64\ucrtbase.dll
	Base address   = 0x75C70000	ucrtbase

Thread 9304 created in process 14052:
	Start address = 0x77B259C0	ntdll!TpCallbackIndependent+0x140
	TEB address   = 0x02A62000

Thread 8732 created in process 14052:
	Start address = 0x77B259C0	ntdll!TpCallbackIndependent+0x140
	TEB address   = 0x02A65000

First chance exception in thread 11164 of process 14052:
	Description       = Breakpoint
	Code              = 0x80000003
	Flags             = 0x00000000 (continuable)
	Address           = 0x77BA1EE2	ntdll!LdrInitShimEngineDynamic+0x6E2
	Parameters[1]     = 0x00000000
	Call stack:
		Address   = 0x77BA1EE3	ntdll!LdrInitShimEngineDynamic+0x6E3
		Address   = 0x77B9C431	ntdll!RtlCaptureStackContext+0x23501
		Address   = 0x77B56551	ntdll!LdrInitializeThunk+0x121
		Address   = 0x77B56441	ntdll!LdrInitializeThunk+0x11

First chance exception in thread 11164 of process 14052:
	Description       = Integer overflow
	Code              = 0xC0000095
	Flags             = 0x00000000 (continuable)
	Address           = 0x0023F6C7
	Call stack:
		Address   = 0x00233063
		Address   = 0x00232E3D
		Address   = 0x00232D7C
		Address   = 0x00232D20
		Address   = 0x00232CC4
		Address   = 0x00232C68
		Address   = 0x00232F8F
		Address   = 0x00232DE4
		Address   = 0x00233366
		Address   = 0x0022AB45
		Address   = 0x0023C9F0
		Address   = 0x0022AFC9
		Address   = 0x0022E4F6
		Address   = 0x00230B09
		Address   = 0x00236A0A
		Address   = 0x75BA00F9	KERNEL32!BaseThreadInitThunk+0x19
		Address   = 0x77B57BBE	ntdll!RtlGetAppContainerNamedObjectPath+0x11E
		Address   = 0x77B57B8E	ntdll!RtlGetAppContainerNamedObjectPath+0xEE

Last chance exception in thread 11164 of process 14052:
	Description       = Integer overflow
	Code              = 0xC0000095
	Flags             = 0x00000000 (continuable)
	Address           = 0x0023F6C7

Thread 9304 exited from process 14052:
	Exit code = 0xC0000095

Thread 11164 exited from process 14052:
	Exit code = 0xC0000095

Process 14052 exited with thread 8732:
	Exit code = 0xC0000095

Primary thread 11164 of debuggee process 14052 exited with code 0xC0000095
Primary thread times:
	Real   =          3.5438404 s
	Kernel =          0.0156250 s
	User   =          0.0000000 s
Debuggee process 14052 exited with code 0xC0000095
Debuggee process times:
	Real   =          3.5712333 s
	Kernel =          0.0156250 s
	User   =          0.0000000 s

Downloads

The console application is available in two functional identical forms: DEBUGGER.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and DEBUGGER.COM, a small form without these extras.

Implementation and Build Details

Non-interactive Symbolic Debugger is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Non-interactive Symbolic Debugger from the source presented hereafter.
  1. Create the text file DEBUGGER.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #define wmemcpy	__movsw
    
    #if _MSC_VER < 1500 // MSC 9.0 alias 2008
    #include <crt\delayimp.h>
    #else
    #include <delayimp.h>
    #endif
    
    #ifdef SYMBOLS
    #ifdef UNICODE
    #define DBGHELP_TRANSLATE_TCHAR
    #endif
    #include <dbghelp.h>
    #ifdef DBGHELP_TRANSLATE_TCHAR
    #undef IMAGEHLP_CBA_EVENT
    #undef SymLoadModuleEx
    #endif
    #endif // SYMBOLS
    
    #define DELPHI_RUNTIME_EXCEPTION		0x0EEDFADEL
    
    #ifndef EXCEPTION_SEGMENT_NOTIFICATION
    #define EXCEPTION_SEGMENT_NOTIFICATION		0x40000005L
    #endif
    
    #ifndef EXCEPTION_FATAL_APP_EXIT
    #define EXCEPTION_FATAL_APP_EXIT		0x40000015L
    #endif
    
    #ifndef EXCEPTION_WX86_SINGLE_STEP
    #define EXCEPTION_WX86_SINGLE_STEP		0x4000001EL
    #endif
    
    #ifndef EXCEPTION_WX86_BREAKPOINT
    #define EXCEPTION_WX86_BREAKPOINT		0x4000001FL
    #endif
    
    #ifndef DBG_PRINTEXCEPTION_C
    #define DBG_PRINTEXCEPTION_C			0x40010006L
    #endif
    
    #ifndef DBG_RIPEXCEPTION
    #define DBG_RIPEXCEPTION			0x40010007L
    #endif
    
    #ifndef DBG_PRINTEXCEPTION_WIDE_C
    #define DBG_PRINTEXCEPTION_WIDE_C		0x4001000AL
    #endif
    
    #ifndef EXCEPTION_CPP_EXCEPTION
    #define EXCEPTION_CPP_EXCEPTION			0x406D1388L
    #endif
    
    #ifndef EXCEPTION_INVALID_PARAMETER
    #define EXCEPTION_INVALID_PARAMETER		0xC000000DL
    #endif
    
    #ifndef EXCEPTION_NO_MEMORY
    #define EXCEPTION_NO_MEMORY			0xC0000017L
    #endif
    
    #ifndef EXCEPTION_ACCESS_DENIED
    #define EXCEPTION_ACCESS_DENIED			0xC0000022L
    #endif
    
    #ifndef EXCEPTION_OBJECT_NAME_NOT_FOUND
    #define EXCEPTION_OBJECT_NAME_NOT_FOUND		0xC0000034L
    #endif
    
    #ifndef EXCEPTION_OBJECT_PATH_NOT_FOUND
    #define EXCEPTION_OBJECT_PATH_NOT_FOUND		0xC000003AL
    #endif
    
    #ifndef EXCEPTION_PROCEDURE_NOT_FOUND
    #define EXCEPTION_PROCEDURE_NOT_FOUND		0xC000007AL
    #endif
    
    #ifndef EXCEPTION_INSTRUCTION_MISALIGNMENT
    #define EXCEPTION_INSTRUCTION_MISALIGNMENT	0xC00000AAL
    #endif
    
    #ifndef EXCEPTION_DLL_NOT_FOUND
    #define EXCEPTION_DLL_NOT_FOUND			0xC0000135L
    #endif
    
    #ifndef EXCEPTION_ORDINAL_NOT_FOUND
    #define EXCEPTION_ORDINAL_NOT_FOUND		0xC0000138L
    #endif
    
    #ifndef EXCEPTION_ENTRYPOINT_NOT_FOUND
    #define EXCEPTION_ENTRYPOINT_NOT_FOUND		0xC0000139L
    #endif
    
    #ifndef EXCEPTION_DLL_INIT_FAILED
    #define EXCEPTION_DLL_INIT_FAILED		0xC0000142L
    #endif
    
    #ifndef EXCEPTION_UNHANDLED_EXCEPTION
    #define EXCEPTION_UNHANDLED_EXCEPTION		0xC0000144L
    #endif
    
    #ifndef EXCEPTION_ILLEGAL_FLOAT_CONTEXT
    #define EXCEPTION_ILLEGAL_FLOAT_CONTEXT		0xC000014AL
    #endif
    
    #ifndef STATUS_POSSIBLE_DEADLOCK
    #define STATUS_POSSIBLE_DEADLOCK		0xC0000194L
    #endif
    
    #ifndef EXCEPTION_HANDLE_NOT_CLOSABLE
    #define EXCEPTION_HANDLE_NOT_CLOSABLE		0xC0000235L
    #endif
    
    #ifndef EXCEPTION_FLOAT_MULTIPLE_FAULTS
    #define EXCEPTION_FLOAT_MULTIPLE_FAULTS		0xC00002B4L
    #endif
    
    #ifndef EXCEPTION_FLOAT_MULTIPLE_TRAPS
    #define EXCEPTION_FLOAT_MULTIPLE_TRAPS		0xC00002B5L
    #endif
    
    #ifndef EXCEPTION_DATATYPE_MISALIGNMENT_ERROR
    #define EXCEPTION_DATATYPE_MISALIGNMENT_ERROR	0xC00002C5L
    #endif
    
    #ifndef EXCEPTION_REG_NAT_CONSUMPTION
    #define EXCEPTION_REG_NAT_CONSUMPTION		0xC00002C9L
    #endif
    
    #ifndef EXCEPTION_INVALID_IMAGE_WIN_32
    #define EXCEPTION_INVALID_IMAGE_WIN_32		0xC0000359L
    #endif
    
    #ifndef EXCEPTION_INVALID_IMAGE_WIN_64
    #define EXCEPTION_INVALID_IMAGE_WIN_64		0xC000035AL
    #endif
    
    #ifndef EXCEPTION_HEAP_CORRUPTION
    #define EXCEPTION_HEAP_CORRUPTION		0xC0000374L
    #endif
    
    #ifndef EXCEPTION_STACK_BUFFER_OVERRUN
    #define EXCEPTION_STACK_BUFFER_OVERRUN		0xC0000409L
    #endif
    
    #ifndef EXCEPTION_INVALID_CRUNTIME_PARAMETER
    #define EXCEPTION_INVALID_CRUNTIME_PARAMETER	0xC0000417L
    #endif
    
    #ifndef EXCEPTION_FATAL_USER_CALLBACK_EXCEPTION
    #define EXCEPTION_FATAL_USER_CALLBACK_EXCEPTION	0xC000041DL
    #endif
    
    #ifndef EXCEPTION_ASSERTION_FAILURE
    #define EXCEPTION_ASSERTION_FAILURE		0xC0000420L
    #endif
    
    #ifndef EXCEPTION_VERIFIER_STOP
    #define EXCEPTION_VERIFIER_STOP			0xC0000421L
    #endif
    
    #ifndef EXCEPTION_FAIL_FAST_EXCEPTION
    #define EXCEPTION_FAIL_FAST_EXCEPTION		0xC0000602L
    #endif
    
    #ifndef EXCEPTION_DISK_QUOTA_EXCEEDED
    #define EXCEPTION_DISK_QUOTA_EXCEEDED		0xC0000802L
    #endif
    
    #ifndef EXCEPTION_DELAY_LOAD_INVALID_PARAMETER
    #define EXCEPTION_DELAY_LOAD_INVALID_PARAMETER	0xC06D0057L
    #endif
    
    #ifndef EXCEPTION_DELAY_LOAD_MODULE_NOT_FOUND
    #define EXCEPTION_DELAY_LOAD_MODULE_NOT_FOUND	0xC06D007EL
    #endif
    
    #ifndef EXCEPTION_DELAY_LOAD_ENTRY_NOT_FOUND
    #define EXCEPTION_DELAY_LOAD_ENTRY_NOT_FOUND	0xC06D007FL
    #endif
    
    #ifndef EXCEPTION_APPLICATION_HANG
    #define EXCEPTION_APPLICATION_HANG		0xCFFFFFFFL
    #endif
    
    #ifndef EXCEPTION_CLR_CCR_EXCEPTION
    #define EXCEPTION_CLR_CCR_EXCEPTION		0xE0434352L	// = 0xE0000000L + 'CCR'
    #endif
    
    #ifndef EXCEPTION_CLR_COM_EXCEPTION
    #define EXCEPTION_CLR_COM_EXCEPTION		0xE0434F4DL	// = 0xE0000000L + 'COM'
    #endif
    
    #ifndef EXCEPTION_CLR_SOFT_STACK_OVERFLOW
    #define EXCEPTION_CLR_SOFT_STACK_OVERFLOW	0xE053534FL	// = 0xE0000000L + 'SSO'
    #endif
    
    #ifndef EXCEPTION_SEH_VERIFICATION_EXCEPTION
    #define EXCEPTION_SEH_VERIFICATION_EXCEPTION	0xE0564552L	// = 0xE0000000L + 'VER'
    #endif
    
    #ifndef EXCEPTION_CLR_INTERNAL_ASSERTION
    #define EXCEPTION_CLR_INTERNAL_ASSERTION	0xE0584D4EL	// = 0xE0000000L + 'XMN'
    #endif
    
    #ifndef EXCEPTION_CPP_EH_EXCEPTION
    #define EXCEPTION_CPP_EH_EXCEPTION		0xE06D7363L	// = 0xE0000000L + 'msc'
    #endif
    
    typedef	struct	_THREADNAME_INFO
    {
    	DWORD	dwType;		// = 0x00001000UL
    	LPCSTR	szName;		// thread name to assign
    	DWORD	dwThreadId;	// thread id (~0UL = caller thread)
    	DWORD	dwFlags;	// reserved for future use (must be 0UL)
    } THREADNAME_INFO;
    
    __forceinline
    LPCWSTR	WINAPI	ExceptionAccess(DWORD_PTR dwAccess)
    {
    	switch (dwAccess)
    	{
    	case EXCEPTION_READ_FAULT:
    		return L"reading";
    
    	case EXCEPTION_WRITE_FAULT:
    		return L"writing";
    
    	case EXCEPTION_EXECUTE_FAULT:
    		return L"executing";
    
    	default:
    		return L"accessing";
    	}
    }
    
    LPCWSTR	WINAPI	ExceptionName(WCHAR szBuffer[1024], EXCEPTION_RECORD *ExceptionRecord)
    {
    	switch (ExceptionRecord->ExceptionCode)
    	{
    	case RPC_S_INVALID_BINDING:			// 0x000006A6
    	case __HRESULT_FROM_WIN32(RPC_S_INVALID_BINDING):
    		return L"RPC binding handle invalid";
    
    	case RPC_S_UNKNOWN_IF:				// 0x000006B5L
    	case __HRESULT_FROM_WIN32(RPC_S_UNKNOWN_IF):
    		return L"RPC interface unknown";
    
    	case RPC_S_SERVER_UNAVAILABLE:			// 0x000006BA
    	case __HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE):
    		return L"RPC server unavailable";
    
    	case RPC_S_INVALID_BOUND:			// 0x000006C6
    	case __HRESULT_FROM_WIN32(RPC_S_INVALID_BOUND):
    		return L"RPC array bounds invalid";
    
    	case EPT_S_NOT_REGISTERED:			// 0x000006D9
    	case __HRESULT_FROM_WIN32(EPT_S_NOT_REGISTERED):
    		return L"RPC endpoint not registered";
    
    	case RPC_S_CANNOT_SUPPORT:			// 0x000006E4
    	case __HRESULT_FROM_WIN32(RPC_S_CANNOT_SUPPORT):
    		return L"RPC operation not supported";
    
    	case RPC_X_SS_IN_NULL_CONTEXT:			// 0x000006EF
    	case __HRESULT_FROM_WIN32(RPC_X_SS_IN_NULL_CONTEXT):
    		return L"RPC null context handle";
    
    	case RPC_X_BAD_STUB_DATA:			// 0x000006F7
    	case __HRESULT_FROM_WIN32(RPC_X_BAD_STUB_DATA):
    		return L"RPC stub received bad data";
    
    	case DELPHI_RUNTIME_EXCEPTION:			// 0x0EEDFADE
    		return L"Delphi runtime exception";
    
    	case EXCEPTION_SEGMENT_NOTIFICATION:		// 0x40000005
    		return L"Segment notification";
    
    	case EXCEPTION_FATAL_APP_EXIT:			// 0x40000015
    		return L"Fatal application exit";
    
    	case EXCEPTION_WX86_SINGLE_STEP:		// 0x4000001E
    		return L"WoW64 single-step";
    
    	case EXCEPTION_WX86_BREAKPOINT:			// 0x4000001F
    		return L"WoW64 breakpoint";
    
    	case DBG_TERMINATE_THREAD:			// 0x40010003
    		return L"Debugger terminate thread";
    
    	case DBG_TERMINATE_PROCESS:			// 0x40010004
    		return L"Debugger terminate process";
    
    	case DBG_CONTROL_C:				// 0x40010005
    		return L"Ctrl-C";
    
    	case DBG_PRINTEXCEPTION_C:			// 0x40010006
    	case DBG_PRINTEXCEPTION_WIDE_C:			// 0x4001000A
    		return L"Debugger print exception";
    
    	case DBG_RIPEXCEPTION:				// 0x40010007
    		return L"Debugger RIP exception";
    
    	case DBG_CONTROL_BREAK:				// 0x40010008
    		return L"Ctrl-Break";
    
    	case DBG_COMMAND_EXCEPTION:			// 0x40010009
    		return L"Debugger command";
    
    	case EXCEPTION_CPP_EXCEPTION:			// 0x406D1388
    		return L"Assign thread name";
    
    	case EXCEPTION_GUARD_PAGE:			// 0x80000001
    		return L"Guard page access";
    
    	case EXCEPTION_DATATYPE_MISALIGNMENT:		// 0x80000002
    		return L"Data misalignment";
    
    	case EXCEPTION_BREAKPOINT:			// 0x80000003
    		return L"Breakpoint";
    
    	case EXCEPTION_SINGLE_STEP:			// 0x80000004
    		return L"Single-step";
    
    	case EXCEPTION_ACCESS_VIOLATION:		// 0xC0000005
    
    		if (wsprintf(szBuffer,
    		             L"Access violation %ls 0x%p",
    		             ExceptionAccess(ExceptionRecord->ExceptionInformation[0]),
    		             ExceptionRecord->ExceptionInformation[1]) > 0)
    			return szBuffer;
    
    		return L"Access violation";
    
    	case EXCEPTION_IN_PAGE_ERROR:			// 0xC0000006
    
    		if (wsprintf(szBuffer,
    #ifdef _WIN64
    		             L"In-page error %ls 0x%p (0x%016I64X)",
    #else
    		             L"In-page error %ls 0x%p (0x%08lX)",
    #endif
    		             ExceptionAccess(ExceptionRecord->ExceptionInformation[0]),
    		             ExceptionRecord->ExceptionInformation[1],
    		             ExceptionRecord->ExceptionInformation[2]) > 0)
    			return szBuffer;
    
    		return L"In-page error";
    
    	case EXCEPTION_INVALID_HANDLE:			// 0xC0000008
    		return L"Invalid handle";
    
    	case EXCEPTION_INVALID_PARAMETER:		// 0xC000000D
    		return L"Invalid parameter";
    
    	case EXCEPTION_NO_MEMORY:			// 0xC0000017
    		return L"Not enough quota (no virtual memory)";
    
    	case EXCEPTION_ILLEGAL_INSTRUCTION:		// 0xC000001D
    		return L"Illegal instruction";
    
    	case EXCEPTION_ACCESS_DENIED:			// 0xC0000022
    		return L"Access denied";
    
    	case EXCEPTION_NONCONTINUABLE_EXCEPTION:	// 0xC0000025
    		return L"Non-continuable";
    
    	case EXCEPTION_INVALID_DISPOSITION:		// 0xC0000026
    		return L"Invalid disposition";
    
    	case EXCEPTION_OBJECT_NAME_NOT_FOUND:		// 0xC0000034
    		return L"Object name not found";
    
    	case EXCEPTION_OBJECT_PATH_NOT_FOUND:		// 0xC000003A
    		return L"Object path not found";
    
    	case EXCEPTION_PROCEDURE_NOT_FOUND:		// 0xC000007A
    		return L"Procedure not found";
    
    	case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:		// 0xC000008C
    		return L"Array bounds exceeded";
    
    	case EXCEPTION_FLT_DENORMAL_OPERAND:		// 0xC000008D
    		return L"Denormal floating-point operand";
    
    	case EXCEPTION_FLT_DIVIDE_BY_ZERO:		// 0xC000008E
    		return L"Floating-point divide-by-zero";
    
    	case EXCEPTION_FLT_INEXACT_RESULT:		// 0xC000008F
    		return L"Inexact floating-point result";
    
    	case EXCEPTION_FLT_INVALID_OPERATION:		// 0xC0000090
    		return L"Invalid floating-point operation";
    
    	case EXCEPTION_FLT_OVERFLOW:			// 0xC0000091
    		return L"Floating-point overflow";
    
    	case EXCEPTION_FLT_STACK_CHECK:			// 0xC0000092
    		return L"Floating-point stack check";
    
    	case EXCEPTION_FLT_UNDERFLOW:			// 0xC0000093
    		return L"Floating-point underflow";
    
    	case EXCEPTION_INT_DIVIDE_BY_ZERO:		// 0xC0000094
    		return L"Integer divide-by-zero";
    
    	case EXCEPTION_INT_OVERFLOW:			// 0xC0000095
    		return L"Integer overflow";
    
    	case EXCEPTION_PRIV_INSTRUCTION:		// 0xC0000096
    		return L"Privileged instruction";
    
    	case EXCEPTION_INSTRUCTION_MISALIGNMENT:	// 0xC00000AA
    		return L"Instruction misalignment";
    
    	case EXCEPTION_STACK_OVERFLOW:			// 0xC00000FD
    		return L"Stack overflow";
    
    	case EXCEPTION_DLL_NOT_FOUND:			// 0xC0000135
    		return L"DLL not found";
    
    	case EXCEPTION_ORDINAL_NOT_FOUND:		// 0xC0000138
    		return L"Ordinal not found";
    
    	case EXCEPTION_ENTRYPOINT_NOT_FOUND:		// 0xC0000139
    		return L"Entrypoint not found";
    
    	case CONTROL_C_EXIT:				// 0xC000013A
    		return L"Ctrl-C";
    
    	case EXCEPTION_DLL_INIT_FAILED:			// 0xC0000142
    		return L"DLL initialisation failed";
    
    	case EXCEPTION_UNHANDLED_EXCEPTION:		// 0xC0000144
    		return L"Unhandled exception";
    
    	case EXCEPTION_ILLEGAL_FLOAT_CONTEXT:		// 0xC000014A
    		return L"No floating-point hardware";
    
    	case EXCEPTION_POSSIBLE_DEADLOCK:		// 0xC0000194
    		return L"Possible deadlock";
    
    	case EXCEPTION_HANDLE_NOT_CLOSABLE:		// 0xC0000235
    		return L"Close protected handle";
    
    	case EXCEPTION_FLOAT_MULTIPLE_FAULTS:		// 0xC00002B4
    		return L"Multiple floating-point faults";
    
    	case EXCEPTION_FLOAT_MULTIPLE_TRAPS:		// 0xC00002B5
    		return L"Multiple floating-point traps";
    
    	case EXCEPTION_DATATYPE_MISALIGNMENT_ERROR:	// 0xC00002C5
    		return L"Alignment error";
    
    	case EXCEPTION_REG_NAT_CONSUMPTION:		// 0xC00002C9
    		return L"Register NaT consumption fault";
    
    	case EXCEPTION_INVALID_IMAGE_WIN_32:		// 0xC0000359
    		return L"32-bit image in 64-bit process";
    
    	case EXCEPTION_INVALID_IMAGE_WIN_64:		// 0xC000035A
    		return L"64-bit image in 32-bit process";
    
    	case EXCEPTION_HEAP_CORRUPTION:			// 0xC0000374
    		return L"Heap corruption";
    
    	case EXCEPTION_STACK_BUFFER_OVERRUN:		// 0xC0000409
    		return L"Buffer overrun on stack (stack corruption)";
    
    	case EXCEPTION_INVALID_CRUNTIME_PARAMETER:	// 0xC0000417
    		return L"C runtime exception (invalid parameter)";
    
    	case EXCEPTION_FATAL_USER_CALLBACK_EXCEPTION:	// 0xC000041D
    		return L"Unhandled exception during user callback";
    
    	case EXCEPTION_ASSERTION_FAILURE:		// 0xC0000420
    		return L"Assertion failed";
    
    	case EXCEPTION_VERIFIER_STOP:			// 0xC0000421
    		return L"Application verifier stop";
    
    	case EXCEPTION_FAIL_FAST_EXCEPTION:		// 0xC0000602
    		return L"Fail-fast exception";
    
    	case EXCEPTION_DISK_QUOTA_EXCEEDED:		// 0xC0000802
    		return L"Disk quota exceeded";
    
    	case EXCEPTION_DELAY_LOAD_INVALID_PARAMETER:	// 0xC06D0057
    		return L"Delay-load exception (invalid parameter)";
    
    	case EXCEPTION_DELAY_LOAD_MODULE_NOT_FOUND:	// 0xC06D007E
    #ifdef DELAYLOADINFO
    		if (wsprintf(szBuffer,
    		             L"Delay-load exception (module %hs not found; 0x%08lX)",
    		             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->szDll,
    		             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->dwLastError) > 0)
    			return szBuffer;
    #else
    		return L"Delay-load exception (module not found)";
    #endif
    	case EXCEPTION_DELAY_LOAD_ENTRY_NOT_FOUND:	// 0xC06D007F
    
    		if (((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->dlp.fImportByName)
    #ifdef DELAYLOADINFO
    			if (wsprintf(szBuffer,
    			             L"Delay-load exception (entry %hs not found in module %hs; 0x%08lX)",
    			             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->dlp.szProcName,
    			             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->szDll,
    			             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->dwLastError) > 0)
    				return szBuffer;
    			else
    #endif
    			return L"Delay-load exception (entry not found)";
    		else
    #ifdef DELAYLOADINFO
    			if (wsprintf(szBuffer,
    			             L"Delay-load exception (ordinal %lu not found in module %hs; 0x%08lX)",
    			             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->dlp.dwOrdinal,
    			             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->szDll,
    			             ((DelayLoadInfo *) (ExceptionRecord->ExceptionInformation[0]))->dwLastError) > 0)
    				return szBuffer;
    			else
    #endif
    			return L"Delay-load exception (ordinal not found)";
    
    	case EXCEPTION_APPLICATION_HANG:		// 0xCFFFFFFF
    		return L"Application hang";
    
    	case EXCEPTION_CLR_CCR_EXCEPTION:		// 0xE0434352 = 0xE0000000 + 'CCR'
    	case EXCEPTION_CLR_COM_EXCEPTION:		// 0xE0434F4D = 0xE0000000 + 'COM'
    	case EXCEPTION_CLR_SOFT_STACK_OVERFLOW:		// 0xE053534F = 0xE0000000 + 'SSO'
    	case EXCEPTION_CLR_INTERNAL_ASSERTION:		// 0xE0584D4E = 0xE0000000 + 'XMN'
    		return L".NET CLR exception";
    
    	case EXCEPTION_SEH_VERIFICATION_EXCEPTION:	// 0xE0564552 = 0xE0000000 + 'VER'
    		return L"SEH verification exception";
    
    	case EXCEPTION_CPP_EH_EXCEPTION:		// 0xE06D7363 = 0xE0000000 + 'msc'
    		return L"C++ exception";
    
    	default:
    		return L"<not available>";
    	}
    }
    
    #ifdef SYMBOLS
    typedef	struct	_siplus
    {
    	SYMBOL_INFO	si;
    	WCHAR		name[MAX_SYM_NAME + sizeof("+0x0123456789ABCDEF")];
    } SYMBOL_INFO_PLUS;
    
    LPCWSTR	WINAPI	NameLookup(HANDLE            hProcess,
    		           DWORD64           ullAddress,
    		           IMAGEHLP_MODULE64 *mi,
    		           SYMBOL_INFO_PLUS  *siplus)
    {
    	DWORD64	ullDisplacement;
    	SIZE_T	usModule;
    	LPWSTR	lpModule;
    
    	if (!SymFromAddr(hProcess,
    	                 ullAddress,
    	                 &ullDisplacement,
    	                 &siplus->si))
    	{
    #if 0
    		PrintConsole(hConsole,
    		             L"SymFromAddr() returned error %lu\n",
    		             GetLastError());
    		return L"";
    #else
    		if (!SymGetModuleInfo64(hProcess,
    		                        ullAddress,
    		                        mi))
    		{
    		//	PrintConsole(hConsole,
    		//	             L"SymGetModuleInfo64() returned error %lu\n",
    		//	             GetLastError());
    			return L"";
    		}
    		else
    		{
    			mi->ModuleName[sizeof(mi->ModuleName)] = L'\0';
    
    			usModule = wcslen(mi->ModuleName);
    
    			if (usModule == 0)
    				return L"";
    
    			mi->ModuleName[-1] = L'\t';
    
    			ullDisplacement = ullAddress - mi->BaseOfImage;
    
    			if (ullDisplacement != 0)
    				wsprintf(mi->ModuleName + usModule,
    				         L"+0x%I64X",
    				         ullDisplacement);
    
    			return mi->ModuleName - 1;
    		}
    	}
    #endif
    	else
    	{
    	//	siplus->si.Name[0] = L'\0';
    
    		if (ullDisplacement == 0)
    			siplus->si.Name[siplus->si.NameLen] = L'\0';
    		else
    			wsprintf(siplus->si.Name + siplus->si.NameLen,
    			         L"+0x%I64X",
    			         ullDisplacement);
    
    		if (!SymGetModuleInfo64(hProcess,
    		                        ullAddress,
    		                        mi))
    		{
    		//	PrintConsole(hConsole,
    		//	             L"SymGetModuleInfo64() returned error %lu\n",
    		//	             GetLastError());
    
    			siplus->si.Name[-1] = L'\t';
    
    			return siplus->si.Name - 1;
    		}
    		else
    		{
    			mi->ModuleName[sizeof(mi->ModuleName)] = L'\0';
    
    			if (ullDisplacement == ~0ULL)
    			{
    				mi->ModuleName[-1] = L'\t';
    
    				return mi->ModuleName - 1;
    			}
    			else
    			{
    				usModule = wcslen(mi->ModuleName);
    
    				lpModule = siplus->si.Name - 1 - usModule;
    #if 0
    				wcscpy(lpModule, mi->ModuleName);
    #else
    				wmemcpy(lpModule, mi->ModuleName, usModule);
    #endif
    				siplus->si.Name[-1] = L'!';
    				lpModule[-1] = L'\t';
    
    				return lpModule - 1;
    			}
    		}
    	}
    }
    
    #ifdef VERBOSE
    LPCSTR	WINAPI	CallbackAction(DWORD  ActionCode,
    		               LPVOID CallbackData)
    {
    	switch (ActionCode)
    	{
    	case CBA_DEFERRED_SYMBOL_LOAD_START:
    		return "DbgHelp: Deferred symbol load has started\n";
    
    	case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
    		return "DbgHelp: Deferred symbol load has completed\n";
    
    	case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
    		return "DbgHelp: Deferred symbol load has failed\n";
    
    	case CBA_SYMBOLS_UNLOADED:
    		return "DbgHelp: Symbols have been unloaded\n";
    
    	case CBA_DUPLICATE_SYMBOL:
    		return "DbgHelp: Duplicate symbols were found\n";
    
    	case CBA_READ_MEMORY:
    		return "DbgHelp: The loaded image has been read\n";
    
    	case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
    		return "DbgHelp: Deferred symbol loading has started\n";
    
    	case CBA_SET_OPTIONS:
    		return "DbgHelp: Symbol options have been updated\n";
    
    	case CBA_EVENT:
    #if 0
    		return "DbgHelp: Display verbose information\n";
    #else
    		return ((IMAGEHLP_CBA_EVENT *) CallbackData)->desc;
    #endif
    		break;
    
    	case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
    		return "DbgHelp: Deferred symbol load has partially completed; "
    		       "the symbol loader is unable to read the image header "
    		       "from either the image file or the specified module\n";
    
    	case CBA_DEBUG_INFO:
    		return (LPCSTR) CallbackData;
    
    #ifdef CBA_SRCSRV_INFO
    	case CBA_SRCSRV_INFO:
    #if 0
    		return "DbgHelp: Display verbose information for source server\n";
    #else
    		return (LPCSTR) CallbackData;
    #endif
    #endif // CBA_SRCSRV_INFO
    #ifdef CBA_SRCSRV_EVENT
    	case CBA_SRCSRV_EVENT:
    #if 0
    		return "DbgHelp: Display verbose information for source server\n";
    #else
    		return ((IMAGEHLP_CBA_EVENT *) CallbackData)->desc;
    #endif
    #endif // CBA_SRCSRV_EVENT
    	default:
    		return "DbgHelp: Unknown action code\n";
    	}
    }
    
    #ifdef _WIN64
    BOOL	WINAPI	SymRegisterCallbackProc(HANDLE  hProcess,
    		                        ULONG   ActionCode,
    		                        ULONG64 CallbackData,
    		                        ULONG64 UserContext)
    #else
    BOOL	WINAPI	SymRegisterCallbackProc(HANDLE  hProcess,
    		                        ULONG   ActionCode,
    		                        LPVOID  CallbackData,
    		                        LPVOID  UserContext)
    #endif
    {
    	LPCSTR	lpString = CallbackAction(ActionCode, CallbackData);
    	DWORD	dwString = strlen(lpString);
    
    	WriteConsoleA((HANDLE) UserContext, lpString, dwString, &dwString, NULL);
    
    	return (ActionCode == CBA_EVENT)
    	     | (ActionCode == CBA_DEBUG_INFO);
    }
    #endif // VERBOSE
    #endif // SYMBOLS
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    #if _WIN32_WINNT < 0x0600
    __declspec(dllimport)
    DWORD	WINAPI	GetMappedFileNameA(HANDLE hProcess,
    		                   LPVOID lpv,
    		                   LPSTR  lpFileName,
    		                   DWORD  dwSize);
    
    __declspec(dllimport)
    DWORD	WINAPI	GetMappedFileNameW(HANDLE hProcess,
    		                   LPVOID lpv,
    		                   LPWSTR lpFileName,
    		                   DWORD  dwSize);
    
    #ifndef UNICODE
    #define GetMappedFileName	GetMappedFileNameA
    #else
    #define GetMappedFileName	GetMappedFileNameW
    #endif
    
    LPCWSTR	WINAPI	GetFileNameFromHandle(HANDLE hConsole,
    		                      HANDLE hFile,
    		                      WCHAR  szFileName[MAX_PATH])
    {
    	LPCWSTR	lpFileName = NULL;
    	DWORD	dwFileName;
    	DWORD	dwDeviceName;
    	WCHAR	szDeviceName[MAX_PATH];
    	WCHAR	szDrive[] = L"@:";
    	DWORD	dwDrive;
    	DWORD	dwDrives;
    	LPVOID	lpMapping;
    	HANDLE	hMapping = CreateFileMapping(hFile,
    		                             (LPSECURITY_ATTRIBUTES) NULL,
    		                             PAGE_READONLY,
    		                             0, 1,
    		                             (LPCWSTR) NULL);
    
    	if (hMapping == NULL)
    		PrintConsole(hConsole,
    		             L"CreateFileMapping() returned error %lu\n",
    		             GetLastError());
    	else
    	{
    		lpMapping = MapViewOfFile(hMapping,
    		                          FILE_MAP_READ,
    		                          0, 0,
    		                          (SIZE_T) 1);
    
    		if (lpMapping == NULL)
    			PrintConsole(hConsole,
    			             L"MapViewOfFile() returned error %lu\n",
    			             GetLastError());
    		else
    		{
    			dwFileName = GetMappedFileName(GetCurrentProcess(),
    			                               lpMapping,
    			                               szFileName,
    			                               MAX_PATH);
    
    			if (dwFileName == 0)
    				PrintConsole(hConsole,
    				             L"GetMappedFileName() returned error %lu\n",
    				             GetLastError());
    			else
    			{
    				dwDrives = GetLogicalDrives();
    
    				if (dwDrives == 0)
    					PrintConsole(hConsole,
    					             L"GetLogicalDrives() returned error %lu\n",
    					             GetLastError());
    				else
    					while (_BitScanForwardd(&dwDrive, dwDrives))
    					{
    						dwDrives &= dwDrives - 1;
    						szDrive[0] = L'A' + dwDrive;
    
    						if (QueryDosDevice(szDrive,
    						                   szDeviceName,
    						                   sizeof(szDeviceName) / sizeof(*szDeviceName)) == 0)
    							PrintConsole(hConsole,
    							             L"QueryDosDevice() returned error %lu\n",
    							             GetLastError());
    						else
    						{
    							dwDeviceName = wcslen(szDeviceName);
    #ifndef _WIN64
    							if ((dwFileName > dwDeviceName)
    							 && (szFileName[dwDeviceName] == L'\\')
    #if 0
    							 && (wmemcmp(szFileName, szDeviceName, dwDeviceName) == 0))
    else
    							 && (memcmp(szFileName, szDeviceName, dwDeviceName * sizeof(*szDeviceName)) == 0))
    #endif
    							{
    								szFileName[--dwDeviceName] = L':';
    								szFileName[--dwDeviceName] = L'A' + dwDrive;
    
    								lpFileName = szFileName + dwDeviceName;
    							}
    #else // _WIN64
    							if ((dwFileName > dwDeviceName)
    							 && (szFileName[dwDeviceName] == L'\\'))
    							{
    								szFileName[dwDeviceName] = L'\0';
    
    								if (wcscmp(szFileName, szDeviceName) == 0)
    								{
    									szFileName[dwDeviceName--] = L'\\';
    									szFileName[dwDeviceName--] = L':';
    									szFileName[dwDeviceName] = L'A' + dwDrive;
    
    									lpFileName = szFileName + dwDeviceName;
    								}
    								else
    									szFileName[dwDeviceName] = L'\\';
    							}
    #endif // _WIN64
    						}
    					}
    			}
    
    			if (!UnmapViewOfFile(lpMapping))
    				PrintConsole(hConsole,
    				             L"UnmapViewOfFile() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hMapping))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	return lpFileName;
    }
    #endif // _WIN32_WINNT
    
    const	LPCWSTR	szBinaryType[7] = {L"32-bit Windows",
    		                   L"MS-DOS",
    		                   L"16-bit Windows",
    		                   L".PIF for MS-DOS",
    		                   L"POSIX",
    		                   L"16-bit OS/2",
    		                   L"64-bit Windows"};
    #ifdef VERBOSE
    const	LPCWSTR	szDirectories[3] = {L"Home   ",		// hdBase
    		                    L"Symbols",		// hdSym
    		                    L"Sources"};	// hdSrc
    
    const	LPCWSTR	szDayOfWeek[7] = {L"Sunday",
    		                  L"Monday",
    		                  L"Tuesday",
    		                  L"Wednesday",
    		                  L"Thursday",
    		                  L"Friday",
    		                  L"Saturday"};
    #endif
    const	LPCWSTR	szTimes[4] = {NULL,
    		              L"Real  ",
    		              L"Kernel",
    		              L"User  "};
    
    const	STARTUPINFO	si = {sizeof(si)};
    
    #ifdef _M_IX86
    __forceinline
    struct
    {
    	DWORD	dwQuotient, dwRemainder;
    }	WINAPI	SplitFileTime(DWORD dwLow, DWORD dwHigh)
    {
    	__asm	// returns quotient in eax and remainder in edx
    	{
    		mov	eax, dwLow
    		mov	edx, dwHigh
    		mov	ecx, 10000000
    		div	ecx
    	}
    }
    #endif
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    #ifdef _WIN64
    	BOOL	bWow64 = FALSE;
    
    	WOW64_CONTEXT	wow64_context;
    #endif
    	CONTEXT	context;
    
    	PEXCEPTION_RECORD	lpExceptionRecord;
    
    	PROCESS_INFORMATION	pi;
    
    	ULARGE_INTEGER	uli[4];
    
    	DEBUG_EVENT	de;
    #ifdef SYMBOLS
    	LPAPI_VERSION	lpApiVersion = ImagehlpApiVersion();
    #ifdef VERBOSE // DBGHELP >= 6.1
    	DWORD	dwDirectory;
    	LPWSTR	lpDirectory;
    	WCHAR	szDirectory[MAX_PATH];
    
    	SYSTEMTIME	st;
    
    	DWORD64	ull;
    #endif // VERBOSE
    	DWORD64	ullBaseOfModule;
    
    	IMAGEHLP_MODULE64	mi;
    	SYMBOL_INFO_PLUS	siplus;
    
    	STACKFRAME64	sf;
    #endif // SYMBOLS
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	WCHAR	szBuffer[1024];
    	WCHAR	szImageName[MAX_PATH];
    	DWORD	dwImageName = MAX_PATH;
    	LPBYTE	lpImageName;
    	LPBYTE	lpString;
    	DWORD	dwString;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwBinaryType;
    	DWORD	dwVersion;
    	DWORD	dwParameter;
    	DWORD	dwThread;
    	DWORD	dwProcess;
    	HANDLE	hProcess;
    	HANDLE	hThread;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if ((nArguments < 2)
    			 || (*lpArguments[1] == L'\0')
    			 || (nArguments > 3))
    				PrintConsole(hConsole,
    				             L"Bad arguments: either a (properly quoted) command line\n"
    				             L"               or the (absolute or relative) path name of an application\n"
    				             L"               followed by a (properly quoted) command line must be given!\n");
    			else
    			{
    				PrintConsole(hConsole,
    				             L"Command line:     \'%ls\'\n"
    				             L"Application name: \'%ls\'\n",
    				             lpArguments[nArguments - 1],
    				             lpArguments[4 - nArguments]);
    
    				if (nArguments == 3)
    					if (!GetBinaryType(lpArguments[1], &dwBinaryType))
    						PrintConsole(hConsole,
    						             L"GetBinaryType() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						PrintConsole(hConsole,
    						             L"Application type: %lu = %ls\n",
    						             dwBinaryType, szBinaryType[dwBinaryType]);
    #ifdef SYMBOLS
    				PrintConsole(hConsole,
    				             L"\n"
    				             L"DbgHelp API:\n"
    				             L"\tVersion  = %hu.%hu\n"
    				             L"\tRevision = %hu\n"
    				             L"\tReserved = %hu\n",
    				             lpApiVersion->MajorVersion, lpApiVersion->MinorVersion,
    				             lpApiVersion->Revision,
    				             lpApiVersion->Reserved);
    #ifdef VERBOSE // DBGHELP >= 6.1
    				PrintConsole(hConsole,
    				             L"DbgHelp Directories:\n");
    
    				for (dwDirectory = 0; dwDirectory < sizeof(szDirectories) / sizeof(*szDirectories); dwDirectory++)
    				{
    					lpDirectory = SymGetHomeDirectory(dwDirectory,
    					                                  szDirectory,
    					                                  sizeof(szDirectory));
    
    					if (lpDirectory == NULL)
    						PrintConsole(hConsole,
    						             L"SymGetHomeDirectory() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						PrintConsole(hConsole,
    						             L"\t%ls = %ls\n",
    						             szDirectories[dwDirectory], lpDirectory);
    				}
    #endif // VERBOSE
    				SymSetOptions(SymGetOptions() | SYMOPT_DEBUG | SYMOPT_INCLUDE_32BIT_MODULES);
    #endif // SYMBOLS
    				if (!CreateProcess(lpArguments[4 - nArguments],
    				                   lpArguments[nArguments - 1],
    				                   (SECURITY_ATTRIBUTES *) NULL,
    				                   (SECURITY_ATTRIBUTES *) NULL,
    				                   FALSE,
    				                   CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT | DEBUG_ONLY_THIS_PROCESS | NORMAL_PRIORITY_CLASS,
    #if 1
    				                   NULL,		// current environment block
    #elif 1
    				                   L"",			// empty environment block
    #else
    				                   L"__COMPAT_LAYER=RunAsInvoker\0_NO_DEBUG_HEAP=1\0DBGENG_NO_DEBUG_PRIVILEGE=1\0TMP=NUL:\0",
    #endif
    				                   (LPCWSTR) NULL,
    				                   &si,
    				                   &pi))
    					PrintConsole(hConsole,
    					             L"CreateProcess() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					dwError = ERROR_SUCCESS;
    #if _WIN32_WINNT < 0x0600
    					dwImageName = GetModuleFileNameEx(pi.hProcess,
    					                                  (HMODULE) NULL,
    					                                  szImageName,
    					                                  sizeof(szImageName) / sizeof(*szImageName));
    					if (dwImageName == 0)
    						PrintConsole(hConsole,
    						             L"GetModuleFileNameEx() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						PrintConsole(hConsole,
    						             L"Debuggee process loaded from image file \'%ls\'\n",
    						             szImageName);
    #else // _WIN32_WINNT
    					if (!QueryFullProcessImageName(pi.hProcess,
    					                               0,
    					                               szImageName,
    					                               &dwImageName))
    						PrintConsole(hConsole,
    						             L"QueryFullProcessImageName() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						PrintConsole(hConsole,
    						             L"Debuggee process loaded from image file \'%ls\'\n",
    						             szImageName);
    #endif // _WIN32_WINNT
    					dwVersion = GetProcessVersion(pi.dwProcessId);
    
    					if (dwVersion == 0)
    						PrintConsole(hConsole,
    						             L"GetProcessVersion() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						PrintConsole(hConsole,
    						             L"Debuggee process version is %hu.%hu\n",
    						             HIWORD(dwVersion), LOWORD(dwVersion));
    
    					PrintConsole(hConsole,
    					             L"\n"
    					             L"Debuggee process %lu with primary thread %lu created\n",
    					             pi.dwProcessId, pi.dwThreadId);
    
    					if (!DebugSetProcessKillOnExit(FALSE))
    						PrintConsole(hConsole,
    						             L"DebugSetProcessKillOnExit() returned error %lu\n",
    						             dwError = GetLastError());
    #ifdef SYMBOLS
    					mi.SizeOfStruct = sizeof(mi);
    					siplus.si.SizeOfStruct = sizeof(siplus.si);
    					siplus.si.MaxNameLen = MAX_SYM_NAME;
    				//	siplus.si.Name[0] = L'\0';
    #endif
    					context.ContextFlags = CONTEXT_CONTROL;
    #ifdef _WIN64
    					wow64_context.ContextFlags = WOW64_CONTEXT_CONTROL;
    #endif
    					do
    					{
    						if (!WaitForDebugEvent(&de, INFINITE))
    						{
    							PrintConsole(hConsole,
    							             L"WaitForDebugEvent() returned error %lu\n",
    							             dwError = GetLastError());
    							break;
    						}
    
    						switch (de.dwDebugEventCode)
    						{
    						case CREATE_PROCESS_DEBUG_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"Process %lu created with primary thread %lu:\n",
    							             de.dwProcessId, de.dwThreadId);
    
    							hProcess = de.u.CreateProcessInfo.hProcess;
    
    							if (de.u.CreateProcessInfo.hProcess != NULL)
    							{
    #ifdef _WIN64
    								if (!IsWow64Process(de.u.CreateProcessInfo.hProcess, &bWow64))
    									PrintConsole(hConsole,
    									             L"IsWow64Process() returned error %lu\n",
    									             dwError = GetLastError());
    #endif
    #ifdef SYMBOLS
    								// NOTE: on Windows 7, SymInitialize() abuses HRESULT as error code!
    
    								if (!SymInitialize(de.u.CreateProcessInfo.hProcess,
    								                   (LPCWSTR) NULL,	// evaluate _NT_SYMBOL_PATH environment variable
    								                   FALSE))
    								{
    									dwError = GetLastError();
    
    									if (dwError > 65535)
    										PrintConsole(hConsole,
    										             L"SymInitialize() returned error 0x%08lX\n",
    										             dwError);
    									else
    										PrintConsole(hConsole,
    										             L"SymInitialize() returned error %lu\n",
    										             dwError);
    								}
    								else
    								{
    #ifdef VERBOSE
    									if (!SymRegisterCallback(de.u.CreateProcessInfo.hProcess,
    									                         SymRegisterCallbackProc,
    									                         hConsole))
    										PrintConsole(hConsole,
    										             L"SymRegisterCallback() returned error %lu\n",
    										             dwError = GetLastError());
    #endif
    #if 0
    									if (!SymSetSearchPath(de.u.CreateProcessInfo.hProcess,
    									                      L".;SRV**https://msdl.microsoft.com/download/symbols"))
    										PrintConsole(hConsole,
    										             L"SymSetSearchPath() returned error %lu\n",
    										             dwError = GetLastError());
    #else
    									if (!SymGetSearchPath(de.u.CreateProcessInfo.hProcess,
    									                      szBuffer,
    									                      sizeof(szBuffer) / sizeof(*szBuffer)))
    										PrintConsole(hConsole,
    										             L"SymGetSearchPath() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    										PrintConsole(hConsole,
    										             L"Symbol search path: %ls\n",
    										             szBuffer);
    #endif
    								}
    
    								ullBaseOfModule = 0;
    #endif // SYMBOLS
    								if (de.u.CreateProcessInfo.lpImageName != NULL)
    									if (!ReadProcessMemory(de.u.CreateProcessInfo.hProcess,
    									                       de.u.CreateProcessInfo.lpImageName,
    									                       &lpImageName,
    									                       sizeof(lpImageName),
    									                       (SIZE_T *) NULL))
    										PrintConsole(hConsole,
    										             L"ReadProcessMemory() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    										if (lpImageName != NULL)
    											if (!ReadProcessMemory(de.u.CreateProcessInfo.hProcess,
    											                       lpImageName,
    											                       szImageName,
    											                       sizeof(szImageName),
    											                       (SIZE_T *) NULL))
    											{
    												dwError = GetLastError();
    
    												if (dwError != ERROR_PARTIAL_COPY)
    													PrintConsole(hConsole,
    													             L"ReadProcessMemory() returned error %lu\n",
    													             dwError);
    												else
    													goto FILENAME;
    											}
    											else
    											FILENAME:
    												if (de.u.CreateProcessInfo.fUnicode != 0)
    												{
    													PrintConsole(hConsole,
    													             L"\tProcess filename = %ls\n",
    													             szImageName);
    #ifdef SYMBOLS // DBGHELP >= 6.0
    													ullBaseOfModule = SymLoadModuleExW(de.u.CreateProcessInfo.hProcess,
    													                                   de.u.CreateProcessInfo.hFile,
    													                                   szImageName,
    													                                   (LPCWSTR) NULL,
    													                                   de.u.CreateProcessInfo.lpBaseOfImage,
    													                                   0,
    													                                   (MODLOAD_DATA *) NULL,
    													                                   0);
    													if (ullBaseOfModule == 0)
    													{
    														dwError = GetLastError();
    
    														if (dwError != ERROR_SUCCESS)
    															PrintConsole(hConsole,
    															             L"SymLoadModuleExW() returned error %lu\n",
    															             dwError);
    													}
    #endif // SYMBOLS
    												}
    												else
    												{
    													PrintConsole(hConsole,
    													             L"\tProcess filename = %hs\n",
    													             szImageName);
    #ifdef SYMBOLS
    													ullBaseOfModule = SymLoadModuleEx(de.u.CreateProcessInfo.hProcess,
    													                                  de.u.CreateProcessInfo.hFile,
    													                                  (LPCSTR) szImageName,
    													                                  (LPCSTR) NULL,
    													                                  de.u.CreateProcessInfo.lpBaseOfImage,
    													                                  0,
    													                                  (MODLOAD_DATA *) NULL,
    													                                  0);
    													if (ullBaseOfModule == 0)
    													{
    														dwError = GetLastError();
    
    														if (dwError != ERROR_SUCCESS)
    															PrintConsole(hConsole,
    															             L"SymLoadModuleEx() returned error %lu\n",
    															             dwError);
    													}
    #endif // SYMBOLS
    												}
    										else
    											goto NOFILENAME;
    								else
    								NOFILENAME:
    								{
    #if _WIN32_WINNT < 0x0600
    									dwImageName = GetModuleFileNameEx(de.u.CreateProcessInfo.hProcess,
    #if 0
    									                                  de.u.CreateProcessInfo.lpBaseOfImage,
    #else
    									                                  (HMODULE) NULL,
    #endif
    									                                  szImageName,
    									                                  sizeof(szImageName) / sizeof(*szImageName));
    									if (dwImageName == 0)
    									{
    										PrintConsole(hConsole,
    										             L"GetModuleFileNameEx() returned error %lu\n",
    										             dwError = GetLastError());
    
    										lpImageName = GetFileNameFromHandle(hConsole,
    										                                    de.u.CreateProcessInfo.hFile,
    										                                    szImageName);
    
    										if (lpImageName != NULL)
    											PrintConsole(hConsole,
    											             L"\tProcess filename = %ls\n",
    											             lpImageName);
    									}
    									else
    										PrintConsole(hConsole,
    										             L"\tProcess filename = %ls\n",
    										             szImageName);
    #else // _WIN32_WINNT
    									dwImageName = GetFinalPathNameByHandle(de.u.CreateProcessInfo.hFile,
    									                                       szImageName,
    									                                       sizeof(szImageName) / sizeof(*szImageName),
    									                                       FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
    									if (dwImageName == 0)
    										PrintConsole(hConsole,
    										             L"GetFinalPathNameByHandle() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    										PrintConsole(hConsole,
    										             L"\tProcess filename = %ls\n",
    										             szImageName + 4);
    #endif // _WIN32_WINNT
    #ifdef SYMBOLS
    									ullBaseOfModule = SymLoadModuleEx(de.u.CreateProcessInfo.hProcess,
    									                                  de.u.CreateProcessInfo.hFile,
    									                                  (LPCSTR) NULL,
    									                                  (LPCSTR) NULL,
    									                                  de.u.CreateProcessInfo.lpBaseOfImage,
    									                                  0,
    									                                  (MODLOAD_DATA *) NULL,
    									                                  0);
    									if (ullBaseOfModule == 0)
    									{
    										dwError = GetLastError();
    
    										if (dwError != ERROR_SUCCESS)
    											PrintConsole(hConsole,
    											             L"SymLoadModuleEx() returned error %lu\n",
    											             dwError);
    									}
    #endif // SYMBOLS
    								}
    #ifdef SYMBOLS
    								if (ullBaseOfModule != 0)
    									if (!SymGetModuleInfo64(de.u.CreateProcessInfo.hProcess,
    									                        ullBaseOfModule,
    									                        &mi))
    										PrintConsole(hConsole,
    										             L"SymGetModuleInfo64() returned error %lu\n",
    										             dwError = GetLastError());
    #ifdef VERBOSE
    									else
    									{
    										ull = __emulu(mi.TimeDateStamp, 10000000)	// seconds since 1970-01-01 to
    										    + 116444736000000000;			//  100 nano-seconds since 1601-01-01
    
    										if (!FileTimeToSystemTime((LPFILETIME) &ull, &st))
    											PrintConsole(hConsole,
    											             L"FileTimeToSystemTime() returned error %lu\n",
    											             dwError = GetLastError());
    
    										PrintConsole(hConsole,
    										             L"\tModule date      = 0x%08lX (%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu UTC)\n"
    										             L"\tModule size      = 0x%08lX\n"
    										             L"\tModule name      = %.32ls\n"
    										             L"\tImage name       = %.256ls\n"
    										             L"\tImage filename   = %.256ls\n"
    										             L"\tPDB filename     = %.256ls\n"
    										             L"\tSymbol count     = %lu\n",
    										             mi.TimeDateStamp,
    										             szDayOfWeek[st.wDayOfWeek],
    										             st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
    										             mi.ImageSize,
    										             mi.ModuleName,
    										             mi.ImageName,
    										             mi.LoadedImageName,
    										             mi.LoadedPdbName,
    										             mi.NumSyms);
    									}
    #endif // VERBOSE
    #endif // SYMBOLS
    							}
    #ifdef VERBOSE
    							PrintConsole(hConsole,
    							             L"\tFile handle      = 0x%p\n"
    							             L"\tProcess handle   = 0x%p\n"
    							             L"\tThread handle    = 0x%p\n",
    							             de.u.CreateProcessInfo.hFile,
    							             de.u.CreateProcessInfo.hProcess,
    							             de.u.CreateProcessInfo.hThread);
    #endif
    							PrintConsole(hConsole,
    							             L"\tBase address     = 0x%p\n"
    #ifndef SYMBOLS
    							             L"\tStart address    = 0x%p\n"
    #else
    							             L"\tStart address    = 0x%p%ls\n"
    #endif
    							             L"\tTEB address      = 0x%p\n",
    							             de.u.CreateProcessInfo.lpBaseOfImage,
    #ifndef SYMBOLS
    							             de.u.CreateProcessInfo.lpStartAddress,
    #else
    							             de.u.CreateProcessInfo.lpStartAddress,
    							             NameLookup(de.u.CreateProcessInfo.hProcess, de.u.CreateProcessInfo.lpStartAddress, &mi, &siplus),
    #endif
    							             de.u.CreateProcessInfo.lpThreadLocalBase);
    
    							if (de.u.CreateProcessInfo.hFile != INVALID_HANDLE_VALUE)
    								if (!CloseHandle(de.u.CreateProcessInfo.hFile))
    									PrintConsole(hConsole,
    									             L"CloseHandle() returned error %lu\n",
    									             dwError = GetLastError());
    							break;
    
    						case CREATE_THREAD_DEBUG_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"Thread %lu created in process %lu:\n"
    #ifdef VERBOSE
    							             L"\tThread handle = 0x%p\n"
    #endif
    #ifndef SYMBOLS
    							             L"\tStart address = 0x%p\n"
    #else
    							             L"\tStart address = 0x%p%ls\n"
    #endif
    							             L"\tTEB address   = 0x%p\n",
    							             de.dwThreadId, de.dwProcessId,
    #ifdef VERBOSE
    							             de.u.CreateThread.hThread,
    #endif
    #ifndef SYMBOLS
    							             de.u.CreateThread.lpStartAddress,
    #else
    							             de.u.CreateThread.lpStartAddress,
    							             NameLookup(hProcess, de.u.CreateThread.lpStartAddress, &mi, &siplus),
    #endif
    							             de.u.CreateThread.lpThreadLocalBase);
    							break;
    
    						case EXIT_PROCESS_DEBUG_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"Process %lu exited with thread %lu:\n"
    							             L"\tExit code = 0x%08lX\n",
    							             de.dwProcessId, de.dwThreadId,
    							             de.u.ExitProcess.dwExitCode);
    #ifdef SYMBOLS
    							if (!SymCleanup(hProcess))
    								PrintConsole(hConsole,
    								             L"SymCleanup() returned error %lu\n",
    								             dwError = GetLastError());
    #endif // SYMBOLS
    							hProcess = NULL;
    
    							break;
    
    						case EXIT_THREAD_DEBUG_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"Thread %lu exited from process %lu:\n"
    							             L"\tExit code = 0x%08lX\n",
    							             de.dwThreadId, de.dwProcessId,
    							             de.u.ExitThread.dwExitCode);
    							break;
    
    						case LOAD_DLL_DEBUG_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"DLL loaded in process %lu by thread %lu:\n",
    							             de.dwProcessId, de.dwThreadId);
    #ifdef SYMBOLS // DBGHELP >= 6.5
    							if (!SymRefreshModuleList(hProcess))
    							{
    								dwError = GetLastError();
    
    								if (dwError > 65535)
    									PrintConsole(hConsole,
    									             L"SymRefreshModuleList() returned error 0x%08lX\n",
    									             dwError);
    								else
    									PrintConsole(hConsole,
    									             L"SymRefreshModuleList() returned error %lu\n",
    									             dwError);
    							}
    
    							ullBaseOfModule = 0;
    #endif // SYMBOLS
    							if (de.u.LoadDll.lpImageName != NULL)
    								if (!ReadProcessMemory(hProcess,
    								                       de.u.LoadDll.lpImageName,
    								                       &lpImageName,
    								                       sizeof(lpImageName),
    								                       (SIZE_T *) NULL))
    									PrintConsole(hConsole,
    									             L"ReadProcessMemory() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    									if (lpImageName != NULL)
    									{
    										if (!ReadProcessMemory(hProcess,
    										                       lpImageName,
    										                       szImageName,
    										                       sizeof(szImageName),
    										                       (SIZE_T *) NULL))
    										{
    											dwError = GetLastError();
    
    											if (dwError != ERROR_PARTIAL_COPY)
    												PrintConsole(hConsole,
    												             L"ReadProcessMemory() returned error %lu\n",
    												             dwError);
    											else
    												goto DLLNAME;
    										}
    										else
    										DLLNAME:
    											if (de.u.LoadDll.fUnicode != 0)
    											{
    												PrintConsole(hConsole,
    												             L"\tDLL filename   = %ls\n",
    												             szImageName);
    #ifdef SYMBOLS // DBGHELP >= 6.0
    												ullBaseOfModule = SymLoadModuleExW(hProcess,
    												                                   de.u.LoadDll.hFile,
    												                                   szImageName,
    												                                   (LPCWSTR) NULL,
    												                                   de.u.LoadDll.lpBaseOfDll,
    												                                   0,
    												                                   (MODLOAD_DATA *) NULL,
    												                                   0);
    												if (ullBaseOfModule == 0)
    												{
    													dwError = GetLastError();
    
    													if (dwError != ERROR_SUCCESS)
    														PrintConsole(hConsole,
    														             L"SymLoadModuleExW() returned error %lu\n",
    														             dwError);
    												}
    #endif // SYMBOLS
    											}
    											else
    											{
    												PrintConsole(hConsole,
    												             L"\tDLL filename   = %hs\n",
    												             szImageName);
    #ifdef SYMBOLS
    												ullBaseOfModule = SymLoadModuleEx(hProcess,
    												                                  de.u.LoadDll.hFile,
    												                                  (LPCSTR) szImageName,
    												                                  (LPCSTR) NULL,
    												                                  de.u.LoadDll.lpBaseOfDll,
    												                                  0,
    												                                  (MODLOAD_DATA *) NULL,
    												                                  0);
    												if (ullBaseOfModule == 0)
    												{
    													dwError = GetLastError();
    
    													if (dwError != ERROR_SUCCESS)
    														PrintConsole(hConsole,
    														             L"SymLoadModuleEx() returned error %lu\n",
    														             dwError);
    												}
    #endif // SYMBOLS
    											}
    									}
    									else
    										goto NODLLNAME;
    							else
    							NODLLNAME:
    							{
    #if _WIN32_WINNT < 0x0600
    								dwImageName = GetModuleFileNameEx(hProcess,
    								                                  de.u.LoadDll.lpBaseOfDll,
    								                                  szImageName,
    								                                  sizeof(szImageName) / sizeof(*szImageName));
    								if (dwImageName == 0)
    								{
    									PrintConsole(hConsole,
    									             L"GetModuleFileNameEx() returned error %lu\n",
    									             dwError = GetLastError());
    
    									lpImageName = GetFileNameFromHandle(hConsole,
    									                                    de.u.LoadDll.hFile,
    									                                    szImageName);
    
    									if (lpImageName != NULL)
    										PrintConsole(hConsole,
    										             L"\tDLL filename   = %ls\n",
    										             lpImageName);
    
    								}
    								else
    									PrintConsole(hConsole,
    									             L"\tDLL filename   = %ls\n",
    									             szImageName);
    #else // _WIN32_WINNT
    								dwImageName = GetFinalPathNameByHandle(de.u.LoadDll.hFile,
    								                                       szImageName,
    								                                       sizeof(szImageName) / sizeof(*szImageName),
    								                                       FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
    								if (dwImageName == 0)
    									PrintConsole(hConsole,
    									             L"GetFinalPathNameByHandle() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    									PrintConsole(hConsole,
    									             L"\tDLL filename   = %ls\n",
    									             szImageName + 4);
    #endif // _WIN32_WINNT
    #ifdef SYMBOLS
    								ullBaseOfModule = SymLoadModuleEx(hProcess,
    								                                  de.u.LoadDll.hFile,
    								                                  (LPCSTR) NULL,
    								                                  (LPCSTR) NULL,
    								                                  de.u.LoadDll.lpBaseOfDll,
    								                                  0,
    								                                  (MODLOAD_DATA *) NULL,
    								                                  0);
    								if (ullBaseOfModule == 0)
    								{
    									dwError = GetLastError();
    
    									if (dwError != ERROR_SUCCESS)
    										PrintConsole(hConsole,
    										             L"SymLoadModuleEx() returned error %lu\n",
    										             dwError);
    								}
    #endif // SYMBOLS
    							}
    #ifdef SYMBOLS
    							if (ullBaseOfModule != 0)
    								if (!SymGetModuleInfo64(hProcess,
    								                        ullBaseOfModule,
    								                        &mi))
    									PrintConsole(hConsole,
    									             L"SymGetModuleInfo64() returned error %lu\n",
    									             dwError = GetLastError());
    #ifdef VERBOSE
    								else
    								{
    									ull = __emulu(mi.TimeDateStamp, 10000000)	// seconds since 1970-01-01 to
    									    + 116444736000000000;			//  100 nano-seconds since 1601-01-01
    
    									if (!FileTimeToSystemTime((LPFILETIME) &ull, &st))
    										PrintConsole(hConsole,
    										             L"FileTimeToSystemTime() returned error %lu\n",
    										             dwError = GetLastError());
    
    									PrintConsole(hConsole,
    									             L"\tModule date    = 0x%08lX (%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu UTC)\n"
    									             L"\tModule size    = 0x%08lX\n"
    									             L"\tModule name    = %.32ls\n"
    									             L"\tImage name     = %.256ls\n"
    									             L"\tImage filename = %.256ls\n"
    									             L"\tPDB filename   = %.256ls\n"
    									             L"\tSymbol count   = %lu\n",
    									             mi.TimeDateStamp,
    									             szDayOfWeek[st.wDayOfWeek],
    									             st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
    									             mi.ImageSize,
    									             mi.ModuleName,
    									             mi.ImageName,
    									             mi.LoadedImageName,
    									             mi.LoadedPdbName,
    									             mi.NumSyms);
    								}
    #endif // VERBOSE
    #endif // SYMBOLS
    							PrintConsole(hConsole,
    #ifdef VERBOSE
    							             L"\tFile handle    = 0x%p\n"
    #endif
    #ifndef SYMBOLS
    							             L"\tBase address   = 0x%p\n",
    #ifdef VERBOSE
    							             de.u.LoadDll.hFile,
    #endif
    							             de.u.LoadDll.lpBaseOfDll);
    #else // SYMBOLS
    							             L"\tBase address   = 0x%p%ls\n",
    #ifdef VERBOSE
    							             de.u.LoadDll.hFile,
    #endif
    							             de.u.LoadDll.lpBaseOfDll,
    							             NameLookup(hProcess, de.u.LoadDll.lpBaseOfDll, &mi, &siplus));
    #endif // SYMBOLS
    							if (de.u.LoadDll.hFile != INVALID_HANDLE_VALUE)
    								if (!CloseHandle(de.u.LoadDll.hFile))
    									PrintConsole(hConsole,
    									             L"CloseHandle() returned error %lu\n",
    									             dwError = GetLastError());
    							break;
    
    						case UNLOAD_DLL_DEBUG_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"DLL unloaded from process %lu by thread %lu:\n"
    #ifndef SYMBOLS
    							             L"\tBase address = 0x%p\n",
    #else
    							             L"\tBase address = 0x%p%ls\n",
    #endif
    							             de.dwProcessId, de.dwThreadId,
    #ifndef SYMBOLS
    							             de.u.UnloadDll.lpBaseOfDll);
    #else
    							             de.u.UnloadDll.lpBaseOfDll,
    							             NameLookup(hProcess, de.u.UnloadDll.lpBaseOfDll, &mi, &siplus));
    
    							if (!SymUnloadModule64(hProcess,
    							                       de.u.UnloadDll.lpBaseOfDll))
    								PrintConsole(hConsole,
    								             L"SymUnloadModule64() returned error %lu\n",
    								             dwError = GetLastError());
    #endif // SYMBOLS
    							break;
    
    						case OUTPUT_DEBUG_STRING_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"Output debug string in thread %lu of process %lu:\n"
    							             L"\tString length  = %hu\n"
    #ifndef SYMBOLS
    							             L"\tString address = 0x%p\n",
    #else
    							             L"\tString address = 0x%p%ls\n",
    #endif
    							             de.dwThreadId, de.dwProcessId,
    							             de.u.DebugString.nDebugStringLength - 1,
    #ifndef SYMBOLS
    							             de.u.DebugString.lpDebugStringData);
    #else
    							             de.u.DebugString.lpDebugStringData,
    							             NameLookup(hProcess, de.u.DebugString.lpDebugStringData, &mi, &siplus));
    #endif
    							dwString = de.u.DebugString.nDebugStringLength;
    #if 0	// NOTE: debug string is always ANSI!
    							if (de.u.CreateProcessInfo.fUnicode != 0)
    								dwString *= sizeof(L'\0');
    #endif
    							lpString = LocalAlloc(LPTR, dwString);
    
    							if (lpString == NULL)
    								PrintConsole(hConsole,
    								             L"LocalAlloc() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								if (!ReadProcessMemory(hProcess,
    								                       de.u.DebugString.lpDebugStringData,
    								                       lpString,
    								                       dwString,
    								                       (SIZE_T *) NULL))
    									PrintConsole(hConsole,
    									             L"ReadProcessMemory() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    #if 0	// NOTE: debug string is always ANSI!
    									if (de.u.CreateProcessInfo.fUnicode != 0)
    									{
    										dwString = wcslen((LPCWSTR) lpString);
    
    										while ((dwString-- > 0)
    										    && ((lpString[dwString] == L' ')
    										     || (lpString[dwString] == L'\a')
    										     || (lpString[dwString] == L'\b')
    										     || (lpString[dwString] == L'\f')
    										     || (lpString[dwString] == L'\n')
    										     || (lpString[dwString] == L'\r')
    										     || (lpString[dwString] == L'\t')
    										     || (lpString[dwString] == L'\v')))
    											/* lpString[dwString] = L'\0' */;
    
    										lpString[++dwString] = L'\0';
    
    										PrintConsole(hConsole,
    										             L"\tString value   = %ls\n",
    										             lpString);
    									}
    									else
    #endif
    								{
    									dwString = strlen((LPCSTR) lpString);
    
    									while ((dwString-- > 0)
    									    && ((lpString[dwString] == ' ')
    									     || (lpString[dwString] == '\a')
    									     || (lpString[dwString] == '\b')
    									     || (lpString[dwString] == '\f')
    									     || (lpString[dwString] == '\n')
    									     || (lpString[dwString] == '\r')
    									     || (lpString[dwString] == '\t')
    									     || (lpString[dwString] == '\v')))
    										/* lpString[dwString] = '\0' */;
    
    									lpString[++dwString] = '\0';
    
    									PrintConsole(hConsole,
    									             L"\tString value   = %hs\n",
    									             lpString);
    								}
    
    								if (LocalFree(lpString) != NULL)
    									PrintConsole(hConsole,
    									             L"LocalFree() returned error %lu\n",
    									             dwError = GetLastError());
    							}
    
    							break;
    
    						case RIP_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"RIP in thread %lu of process %lu:\n"
    							             L"\tError = %lu\n"
    							             L"\tType  = %lu\n",
    							             de.dwThreadId, de.dwProcessId,
    							             de.u.RipInfo.dwError,
    							             de.u.RipInfo.dwType);
    							break;
    
    						case EXCEPTION_DEBUG_EVENT:
    
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"%ls chance exception in thread %lu of process %lu:\n"
    							             L"\tDescription       = %ls\n"
    							             L"\tCode              = 0x%08lX\n"
    							             L"\tFlags             = 0x%08lX (%lscontinuable)\n"
    #ifndef SYMBOLS
    							             L"\tAddress           = 0x%p\n",
    #else
    							             L"\tAddress           = 0x%p%ls\n",
    #endif
    							             de.u.Exception.dwFirstChance != 0 ? L"First" : L"Last",
    							             de.dwThreadId, de.dwProcessId,
    							             ExceptionName(szBuffer, &de.u.Exception.ExceptionRecord),
    							             de.u.Exception.ExceptionRecord.ExceptionCode,
    							             de.u.Exception.ExceptionRecord.ExceptionFlags,
    							             de.u.Exception.ExceptionRecord.ExceptionFlags != 0 ? L"non-" : L"",
    #ifndef SYMBOLS
    							             de.u.Exception.ExceptionRecord.ExceptionAddress);
    #else
    							             de.u.Exception.ExceptionRecord.ExceptionAddress,
    							             NameLookup(hProcess, de.u.Exception.ExceptionRecord.ExceptionAddress, &mi, &siplus));
    #endif
    							if (de.u.Exception.dwFirstChance == 0)
    								break;
    
    							if (de.u.Exception.ExceptionRecord.NumberParameters > 0)
    							{
    								PrintConsole(hConsole,
    								             L"\tParameters[%lu]    %lc",
    								             de.u.Exception.ExceptionRecord.NumberParameters,
    								             de.u.Exception.ExceptionRecord.NumberParameters > 10 ? L'\0' : L' ');
    
    								for (dwParameter = 0; dwParameter < de.u.Exception.ExceptionRecord.NumberParameters; dwParameter++)
    									PrintConsole(hConsole,
    									             dwParameter == 0 ? L"= 0x%p" : L", 0x%p",
    									             de.u.Exception.ExceptionRecord.ExceptionInformation[dwParameter]);
    
    								PrintConsole(hConsole, L"\n");
    							}
    
    							for (lpExceptionRecord = de.u.Exception.ExceptionRecord.ExceptionRecord;
    							     lpExceptionRecord != NULL;
    							     lpExceptionRecord = lpExceptionRecord->ExceptionRecord)
    							{
    								PrintConsole(hConsole,
    								             L"\n"
    								             L"\tChained exception:\n"
    								             L"\t\tDescription       = %ls\n"
    								             L"\t\tCode              = 0x%08lX\n"
    								             L"\t\tFlags             = 0x%08lX (%lscontinuable)\n"
    #ifndef SYMBOLS
    								             L"\t\tAddress           = 0x%p\n",
    #else
    								             L"\t\tAddress           = 0x%p%ls\n",
    #endif
    								             ExceptionName(szBuffer, lpExceptionRecord),
    								             lpExceptionRecord->ExceptionCode,
    								             lpExceptionRecord->ExceptionFlags,
    								             lpExceptionRecord->ExceptionFlags != 0 ? L"non-" : L"",
    #ifndef SYMBOLS
    								             lpExceptionRecord->ExceptionAddress);
    #else
    								             lpExceptionRecord->ExceptionAddress,
    								             NameLookup(hProcess, lpExceptionRecord->ExceptionAddress, &mi, &siplus));
    #endif
    								if (lpExceptionRecord->NumberParameters > 0)
    								{
    									PrintConsole(hConsole,
    									             L"\t\tParameters[%lu]    %lc",
    									             lpExceptionRecord->NumberParameters,
    									             lpExceptionRecord->NumberParameters > 10 ? L'\0' : L' ');
    
    									for (dwParameter = 0; dwParameter < lpExceptionRecord->NumberParameters; dwParameter++)
    										PrintConsole(hConsole,
    										             dwParameter == 0 ? L"= 0x%p" : L", 0x%p",
    										             lpExceptionRecord->ExceptionInformation[dwParameter]);
    
    									PrintConsole(hConsole, L"\n");
    								}
    							}
    #ifdef SYMBOLS
    							hThread = OpenThread(THREAD_GET_CONTEXT,
    							                     FALSE,
    							                     de.dwThreadId);
    
    							if (hThread == NULL)
    								PrintConsole(hConsole,
    								             L"OpenThread() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    #if _M_IX86
    								if (!GetThreadContext(hThread, &context))
    									PrintConsole(hConsole,
    									             L"GetThreadContext() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    								{
    #ifdef VERBOSE
    									PrintConsole(hConsole, L"\tRegisters:\n");
    
    									if ((context.ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
    										PrintConsole(hConsole,
    										             L"\t\tEbp = 0x%08lX, Eip = 0x%08lX, Esp = 0x%08lX\n"
    										             L"\t\tCs  = 0x%08lX, Ss  = 0x%08lX\n"
    									                     L"\t\tEfl = 0x%08lX: Iopl %1lu,%ls%ls %ls %ls %ls %ls %ls %ls %ls %ls\n",
    										             context.Ebp, context.Eip, context.Esp,
    										             context.SegCs, context.SegSs,
    									                     context.EFlags,
    										             (context.EFlags >> 12) & 0x00000003,		//  IOPL level
    										             context.EFlags & 0x00100000 ? L" vip" : L"",	//  VIP (virtual interrupt pending)
    										             context.EFlags & 0x00080000 ? L" vif" : L"",	//  VIF (virtual interrupt flag)
    										             context.EFlags & 0x00000800 ? L"ov" : L"nv",	//  OF (overflow flag)
    										             context.EFlags & 0x00000400 ? L"dn" : L"up",	//  DF (direction flag)
    										             context.EFlags & 0x00000200 ? L"ei" : L"di",	//  IF (interrupt enable flag)
    										             context.EFlags & 0x00000080 ? L"ng" : L"pl",	//  SF (sign flag)
    										             context.EFlags & 0x00000040 ? L"zr" : L"nz",	//  ZF (zero flag)
    										             context.EFlags & 0x00000010 ? L"ac" : L"na",	//  AF (aux carry flag)
    										             context.EFlags & 0x00000004 ? L"pe" : L"po",	//  PF (parity flag)
    										             context.EFlags & 0x00000001 ? L"cy" : L"nc");	//  CF (carry flag)
    
    									if ((context.ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
    										PrintConsole(hConsole,
    										             L"\t\tEax = 0x%08lX, Ebx = 0x%08lX, Ecx = 0x%08lX, Edx = 0x%08lX\n"
    										             L"\t\tEdi = 0x%08lX, Esi = 0x%08lX\n",
    										             context.Eax, context.Ebx, context.Ecx, context.Edx,
    										             context.Edi, context.Esi);
    
    									if ((context.ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
    										PrintConsole(hConsole,
    										             L"\t\tDs  = 0x%08lX, Es  = 0x%08lX, Fs  = 0x%08lX, Gs  = 0x%08lX\n",
    										             context.SegDs, context.SegEs, context.SegFs, context.SegGs);
    
    									if ((context.ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
    										PrintConsole(hConsole,
    										             L"\t\tDr0 = 0x%08lX, Dr1 = 0x%08lX, Dr2 = 0x%08lX, Dr3 = 0x%08lX\n"
    										             L"\t\tDr6 = 0x%08lX, Dr7 = 0x%08lX\n",
    										             context.Dr0, context.Dr1, context.Dr2, context.Dr3,
    										             context.Dr6, context.Dr7);
    
    									if ((context.ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
    										;
    
    									if ((context.ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
    										;
    #endif // VERBOSE
    									sf.AddrPC.Offset = context.Eip;
    									sf.AddrPC.Mode = AddrModeFlat;
    									sf.AddrReturn.Mode = AddrModeFlat;
    									sf.AddrFrame.Offset = context.Ebp;
    									sf.AddrFrame.Mode = AddrModeFlat;
    									sf.AddrStack.Offset = context.Esp;
    									sf.AddrStack.Mode = AddrModeFlat;
    
    									PrintConsole(hConsole, L"\tCall stack:\n");
    
    									while (StackWalk64(IMAGE_FILE_MACHINE_I386,
    									                   hProcess,
    									                   hThread,
    									                   &sf,
    									                   &context,
    #if 1
    									                   NULL,
    #else
    									                   ReadProcessMemory,
    #endif
    									                   SymFunctionTableAccess64,
    									                   SymGetModuleBase64,
    									                   NULL))
    #ifdef VERBOSE
    										PrintConsole(hConsole,
    										             L"\t\tAddress   = 0x%08lX%ls\n"
    										             L"\t\tReturn    = 0x%08lX\n"
    										             L"\t\tFrame     = 0x%08lX\n"
    										             L"\t\tStack     = 0x%08lX\n"
    										             L"\t\tParameter = 0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX\n",
    										             (DWORD) sf.AddrPC.Offset,
    										             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus),
    										             (DWORD) sf.AddrReturn.Offset,
    										             (DWORD) sf.AddrFrame.Offset,
    										             (DWORD) sf.AddrStack.Offset,
    										             (DWORD) sf.Params[0],
    										             (DWORD) sf.Params[1],
    										             (DWORD) sf.Params[2],
    										             (DWORD) sf.Params[3]);
    #else
    										PrintConsole(hConsole,
    										             L"\t\tAddress   = 0x%08lX%ls\n",
    										             (DWORD) sf.AddrPC.Offset,
    										             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus));
    #endif // VERBOSE
    								}
    #elif _M_AMD64
    								if (bWow64)
    								{
    									if (!Wow64GetThreadContext(hThread, &wow64_context))
    										PrintConsole(hConsole,
    										             L"Wow64GetThreadContext() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    #ifdef VERBOSE
    										PrintConsole(hConsole, L"\tRegisters:\n");
    
    										if ((wow64_context.ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
    											PrintConsole(hConsole,
    											             L"\t\tEbp = 0x%08lX, Eip = 0x%08lX, Esp = 0x%08lX\n"
    											             L"\t\tCs  = 0x%08lX, Ss  = 0x%08lX\n"
    										                     L"\t\tEfl = 0x%08lX: Iopl %1lu,%ls%ls %ls %ls %ls %ls %ls %ls %ls %ls\n",
    											             wow64_context.Ebp, wow64_context.Eip, wow64_context.Esp,
    											             wow64_context.SegCs, wow64_context.SegSs,
    										                     wow64_context.EFlags,
    											             (wow64_context.EFlags >> 12) & 0x00000003,		//  IOPL level
    											             wow64_context.EFlags & 0x00100000 ? L" vip" : L"",	//  VIP (virtual interrupt pending)
    											             wow64_context.EFlags & 0x00080000 ? L" vif" : L"",	//  VIF (virtual interrupt flag)
    											             wow64_context.EFlags & 0x00000800 ? L"ov" : L"nv",	//  OF (overflow flag)
    											             wow64_context.EFlags & 0x00000400 ? L"dn" : L"up",	//  DF (direction flag)
    											             wow64_context.EFlags & 0x00000200 ? L"ei" : L"di",	//  IF (interrupt enable flag)
    											             wow64_context.EFlags & 0x00000080 ? L"ng" : L"pl",	//  SF (sign flag)
    											             wow64_context.EFlags & 0x00000040 ? L"zr" : L"nz",	//  ZF (zero flag)
    											             wow64_context.EFlags & 0x00000010 ? L"ac" : L"na",	//  AF (aux carry flag)
    											             wow64_context.EFlags & 0x00000004 ? L"pe" : L"po",	//  PF (parity flag)
    											             wow64_context.EFlags & 0x00000001 ? L"cy" : L"nc");	//  CF (carry flag)
    
    										if ((wow64_context.ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
    											PrintConsole(hConsole,
    											             L"\t\tEax = 0x%08lX, Ebx = 0x%08lX, Ecx = 0x%08lX, Edx = 0x%08lX\n"
    											             L"\t\tEdi = 0x%08lX, Esi = 0x%08lX\n",
    											             wow64_context.Eax, wow64_context.Ebx, wow64_context.Ecx, wow64_context.Edx,
    											             wow64_context.Edi, wow64_context.Esi);
    
    										if ((wow64_context.ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
    											PrintConsole(hConsole,
    											             L"\t\tDs  = 0x%08lX, Es  = 0x%08lX, Fs  = 0x%08lX, Gs  = 0x%08lX\n",
    											             wow64_context.SegDs, wow64_context.SegEs, wow64_context.SegFs, wow64_context.SegGs);
    
    										if ((wow64_context.ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
    											PrintConsole(hConsole,
    											             L"\t\tDr0 = 0x%08lX, Dr1 = 0x%08lX, Dr2 = 0x%08lX, Dr3 = 0x%08lX\n"
    											             L"\t\tDr6 = 0x%08lX, Dr7 = 0x%08lX\n",
    											             wow64_context.Dr0, wow64_context.Dr1, wow64_context.Dr2, wow64_context.Dr3,
    											             wow64_context.Dr6, wow64_context.Dr7);
    
    										if ((wow64_context.ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
    											;
    
    										if ((wow64_context.ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
    											;
    #endif // VERBOSE
    										sf.AddrPC.Offset = wow64_context.Eip;
    										sf.AddrPC.Mode = AddrModeFlat;
    										sf.AddrReturn.Mode = AddrModeFlat;
    										sf.AddrFrame.Offset = wow64_context.Ebp;
    										sf.AddrFrame.Mode = AddrModeFlat;
    										sf.AddrStack.Offset = wow64_context.Esp;
    										sf.AddrStack.Mode = AddrModeFlat;
    
    										PrintConsole(hConsole, L"\tCall stack:\n");
    
    										while (StackWalk64(IMAGE_FILE_MACHINE_I386,
    										                   hProcess,
    										                   hThread,
    										                   &sf,
    										                   &wow64_context,
    #if 1
    										                   NULL,
    #else
    										                   ReadProcessMemory,
    #endif
    										                   SymFunctionTableAccess64,
    										                   SymGetModuleBase64,
    										                   NULL))
    #ifdef VERBOSE
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%08lX%ls\n"
    											             L"\t\tReturn    = 0x%08lX\n"
    											             L"\t\tFrame     = 0x%08lX\n"
    											             L"\t\tStack     = 0x%08lX\n"
    											             L"\t\tParameter = 0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX\n",
    											             (DWORD) sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus),
    											             (DWORD) sf.AddrReturn.Offset,
    											             (DWORD) sf.AddrFrame.Offset,
    											             (DWORD) sf.AddrStack.Offset,
    											             (DWORD) sf.Params[0],
    											             (DWORD) sf.Params[1],
    											             (DWORD) sf.Params[2],
    											             (DWORD) sf.Params[3]);
    #else
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%08lX%ls\n",
    											             (DWORD) sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus));
    #endif // VERBOSE
    									}
    								}
    								else
    								{
    									if (!GetThreadContext(hThread, &context))
    										PrintConsole(hConsole,
    										             L"GetThreadContext() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    #ifdef VERBOSE
    										PrintConsole(hConsole, L"\tRegisters:\n");
    
    										if ((context.ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
    											PrintConsole(hConsole,
    											             L"\t\tRip = 0x%016I64X, Rsp = 0x%016I64X\n"
    											             L"\t\tCs  = %04hX, Ss  = %04hX\n"
    										                     L"\t\tRfl = 0x%08lX: Iopl %1lu,%ls%ls %ls %ls %ls %ls %ls %ls %ls %ls\n",
    											             context.Rip, context.Rsp,
    											             context.SegCs, context.SegSs,
    										                     context.EFlags,
    											             (context.EFlags >> 12) & 0x00000003,		//  IOPL level
    											             context.EFlags & 0x00100000 ? L" vip" : L"",	//  VIP (virtual interrupt pending)
    											             context.EFlags & 0x00080000 ? L" vif" : L"",	//  VIF (virtual interrupt flag)
    											             context.EFlags & 0x00000800 ? L"ov" : L"nv",	//  OF (overflow flag)
    											             context.EFlags & 0x00000400 ? L"dn" : L"up",	//  DF (direction flag)
    											             context.EFlags & 0x00000200 ? L"ei" : L"di",	//  IF (interrupt enable flag)
    											             context.EFlags & 0x00000080 ? L"ng" : L"pl",	//  SF (sign flag)
    											             context.EFlags & 0x00000040 ? L"zr" : L"nz",	//  ZF (zero flag)
    											             context.EFlags & 0x00000010 ? L"ac" : L"na",	//  AF (aux carry flag)
    											             context.EFlags & 0x00000004 ? L"pe" : L"po",	//  PF (parity flag)
    											             context.EFlags & 0x00000001 ? L"cy" : L"nc");	//  CF (carry flag)
    
    										if ((context.ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
    											PrintConsole(hConsole,
    											             L"\t\tRax = 0x%016I64X, Rbx = 0x%016I64X, Rcx = 0x%016I64X, Rdx = 0x%016I64X\n"
    											             L"\t\tRbp = 0x%016I64X, Rdi = 0x%016I64X, Rsi = 0x%016I64X\n"
    											             L"\t\tR08 = 0x%016I64X, R09 = 0x%016I64X, R10 = 0x%016I64X, R11 = 0x%016I64X\n"
    											             L"\t\tR12 = 0x%016I64X, R13 = 0x%016I64X, R14 = 0x%016I64X, R15 = 0x%016I64X\n",
    											             context.Rax, context.Rbx, context.Rcx, context.Rdx,
    											             context.Rbp, context.Rdi, context.Rsi,
    											             context.R08, context.R09, context.R10, context.R11,
    											             context.R12, context.R13, context.R14, context.R15);
    
    										if ((context.ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
    											PrintConsole(hConsole,
    											             L"\t\tDs  = %04hX, Es  = %04hX, Fs  = %04hX, Gs  = %04hX\n",
    											             context.SegDs, context.SegEs, context.SegFs, context.SegGs);
    
    										if ((context.ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
    											PrintConsole(hConsole,
    											             L"\t\tDr0 = 0x%016I64X, Dr1 = 0x%016I64X, Dr2 = 0x%016I64X, Dr3 = 0x%016I64X\n"
    											             L"\t\tDr6 = 0x%016I64X, Dr7 = 0x%016I64X\n",
    											             context.Dr0, context.Dr1, context.Dr2, context.Dr3,
    											             context.Dr6, context.Dr7);
    
    										if ((context.ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
    											;
    #endif // VERBOSE
    										sf.AddrPC.Offset = context.Rip;
    										sf.AddrPC.Mode = AddrModeFlat;
    										sf.AddrReturn.Mode = AddrModeFlat;
    										sf.AddrFrame.Offset = context.Rbp;
    										sf.AddrFrame.Mode = AddrModeFlat;
    										sf.AddrStack.Offset = context.Rsp;
    										sf.AddrStack.Mode = AddrModeFlat;
    
    										PrintConsole(hConsole, L"\tCall stack:\n");
    
    										while (StackWalk64(IMAGE_FILE_MACHINE_AMD64,
    										                   hProcess,
    										                   hThread,
    										                   &sf,
    										                   &context,
    #if 1
    										                   NULL,
    #else
    										                   ReadProcessMemory,
    #endif
    										                   SymFunctionTableAccess64,
    										                   SymGetModuleBase64,
    										                   NULL))
    #ifdef VERBOSE
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%016I64X%ls\n"
    											             L"\t\tReturn    = 0x%016I64X\n"
    											             L"\t\tFrame     = 0x%016I64X\n"
    											             L"\t\tStack     = 0x%016I64X\n"
    											             L"\t\tParameter = 0x%016I64X, 0x%016I64X, 0x%016I64X, 0x%016I64X\n",
    											             sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus),
    											             sf.AddrReturn.Offset,
    											             sf.AddrFrame.Offset,
    											             sf.AddrStack.Offset,
    											             sf.Params[0],
    											             sf.Params[1],
    											             sf.Params[2],
    											             sf.Params[3]);
    #else
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%016I64X%ls\n",
    											             sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus));
    #endif // VERBOSE
    									}
    								}
    #elif _M_IA64
    								if (bWow64)
    								{
    									if (!Wow64GetThreadContext(hThread, &wow64_context))
    										PrintConsole(hConsole,
    										             L"Wow64GetThreadContext() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    #ifdef VERBOSE
    										PrintConsole(hConsole, L"\tRegisters:\n");
    
    										if ((wow64_context.ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
    											PrintConsole(hConsole,
    											             L"\t\tEbp = 0x%08lX, Eip = 0x%08lX, Esp = 0x%08lX\n"
    											             L"\t\tCs  = 0x%08lX, Ss  = 0x%08lX\n"
    										                     L"\t\tEfl = 0x%08lX: Iopl %1lu,%ls%ls %ls %ls %ls %ls %ls %ls %ls %ls\n",
    											             wow64_context.Ebp, wow64_context.Eip, wow64_context.Esp,
    											             wow64_context.SegCs, wow64_context.SegSs,
    										                     wow64_context.EFlags,
    											             (wow64_context.EFlags >> 12) & 0x00000003,		//  IOPL level
    											             wow64_context.EFlags & 0x00100000 ? L" vip" : L"",	//  VIP (virtual interrupt pending)
    											             wow64_context.EFlags & 0x00080000 ? L" vif" : L"",	//  VIF (virtual interrupt flag)
    											             wow64_context.EFlags & 0x00000800 ? L"ov" : L"nv",	//  OF (overflow flag)
    											             wow64_context.EFlags & 0x00000400 ? L"dn" : L"up",	//  DF (direction flag)
    											             wow64_context.EFlags & 0x00000200 ? L"ei" : L"di",	//  IF (interrupt enable flag)
    											             wow64_context.EFlags & 0x00000080 ? L"ng" : L"pl",	//  SF (sign flag)
    											             wow64_context.EFlags & 0x00000040 ? L"zr" : L"nz",	//  ZF (zero flag)
    											             wow64_context.EFlags & 0x00000010 ? L"ac" : L"na",	//  AF (aux carry flag)
    											             wow64_context.EFlags & 0x00000004 ? L"pe" : L"po",	//  PF (parity flag)
    											             wow64_context.EFlags & 0x00000001 ? L"cy" : L"nc");	//  CF (carry flag)
    
    										if ((wow64_context.ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
    											PrintConsole(hConsole,
    											             L"\t\tEax = 0x%08lX, Ebx = 0x%08lX, Ecx = 0x%08lX, Edx = 0x%08lX\n"
    											             L"\t\tEdi = 0x%08lX, Esi = 0x%08lX\n",
    											             wow64_context.Eax, wow64_context.Ebx, wow64_context.Ecx, wow64_context.Edx,
    											             wow64_context.Edi, wow64_context.Esi);
    
    										if ((wow64_context.ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
    											PrintConsole(hConsole,
    											             L"\t\tDs  = 0x%08lX, Es  = 0x%08lX, Fs  = 0x%08lX, Gs  = 0x%08lX\n",
    											             wow64_context.SegDs, wow64_context.SegEs, wow64_context.SegFs, wow64_context.SegGs);
    
    										if ((wow64_context.ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
    											PrintConsole(hConsole,
    											             L"\t\tDr0 = 0x%08lX, Dr1 = 0x%08lX, Dr2 = 0x%08lX, Dr3 = 0x%08lX\n"
    											             L"\t\tDr6 = 0x%08lX, Dr7 = 0x%08lX\n",
    											             wow64_context.Dr0, wow64_context.Dr1, wow64_context.Dr2, wow64_context.Dr3,
    											             wow64_context.Dr6, wow64_context.Dr7);
    
    										if ((wow64_context.ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
    											;
    
    										if ((wow64_context.ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
    											;
    #endif // VERBOSE
    										sf.AddrPC.Offset = wow64_context.Eip;
    										sf.AddrPC.Mode = AddrModeFlat;
    										sf.AddrReturn.Mode = AddrModeFlat;
    										sf.AddrFrame.Offset = wow64_context.Ebp;
    										sf.AddrFrame.Mode = AddrModeFlat;
    										sf.AddrStack.Offset = wow64_context.Esp;
    										sf.AddrStack.Mode = AddrModeFlat;
    
    										PrintConsole(hConsole, L"\tCall stack:\n");
    
    										while (StackWalk64(IMAGE_FILE_MACHINE_I386,
    										                   hProcess,
    										                   hThread,
    										                   &sf,
    										                   &wow64_context,
    #if 1
    										                   NULL,
    #else
    										                   ReadProcessMemory,
    #endif
    										                   SymFunctionTableAccess64,
    										                   SymGetModuleBase64,
    										                   NULL))
    #ifdef VERBOSE
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%08lX%ls\n"
    											             L"\t\tReturn    = 0x%08lX\n"
    											             L"\t\tFrame     = 0x%08lX\n"
    											             L"\t\tStack     = 0x%08lX\n"
    											             L"\t\tParameter = 0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX\n",
    											             (DWORD) sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus),
    											             (DWORD) sf.AddrReturn.Offset,
    											             (DWORD) sf.AddrFrame.Offset,
    											             (DWORD) sf.AddrStack.Offset,
    											             (DWORD) sf.Params[0],
    											             (DWORD) sf.Params[1],
    											             (DWORD) sf.Params[2],
    											             (DWORD) sf.Params[3]);
    #else
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%08lX%ls\n",
    											             (DWORD) sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus));
    #endif // VERBOSE
    									}
    								}
    								else
    								{
    									if (!GetThreadContext(hThread, &context))
    										PrintConsole(hConsole,
    										             L"GetThreadContext() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    										sf.AddrPC.Offset = context.StIIP;
    										sf.AddrPC.Mode = AddrModeFlat;
    										sf.AddrReturn.Mode = AddrModeFlat;
    										sf.AddrFrame.Mode = AddrModeFlat;
    										sf.AddrStack.Offset = context.IntSp;
    										sf.AddrStack.Mode = AddrModeFlat;
    										sf.AddrBStore.Offset = context.RsBSP;
    										sf.AddrBStore.Mode = AddrModeFlat;
    
    										PrintConsole(hConsole, L"\tCall stack:\n");
    
    										while (StackWalk64(IMAGE_FILE_MACHINE_IA64,
    										                   hProcess,
    										                   hThread,
    										                   &sf,
    										                   &context,
    #if 1
    										                   NULL,
    #else
    										                   ReadProcessMemory,
    #endif
    										                   SymFunctionTableAccess64,
    										                   SymGetModuleBase64,
    										                   NULL))
    #ifdef VERBOSE
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%016I64X%ls\n"
    											             L"\t\tReturn    = 0x%016I64X\n"
    											             L"\t\tFrame     = 0x%016I64X\n"
    											             L"\t\tStack     = 0x%016I64X\n"
    											             L"\t\tParameter = 0x%016I64X, 0x%016I64X, 0x%016I64X, 0x%016I64X\n",
    											             sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus),
    											             sf.AddrReturn.Offset,
    											             sf.AddrFrame.Offset,
    											             sf.AddrStack.Offset,
    											             sf.Params[0],
    											             sf.Params[1],
    											             sf.Params[2],
    											             sf.Params[3]);
    #else
    											PrintConsole(hConsole,
    											             L"\t\tAddress   = 0x%016I64X%ls\n",
    											             sf.AddrPC.Offset,
    											             NameLookup(hProcess, sf.AddrPC.Offset, &mi, &siplus));
    #endif // VERBOSE
    									}
    								}
    #else
    #error Only I386, AMD64 and IA64 supported!
    #endif
    								if (!CloseHandle(hThread))
    									PrintConsole(hConsole,
    									             L"CloseHandle() returned error %lu\n",
    									             dwError = GetLastError());
    							}
    #endif // SYMBOLS
    							break;
    
    						default:
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"Unknown debug event %lu in thread %lu of process %lu\n",
    							             de.dwDebugEventCode,
    							             de.dwThreadId, de.dwProcessId);
    						}
    
    						// NOTE: DBG_EXCEPTION_NOT_HANDLED repeats OUTPUT_DEBUG_STRING_EVENT once!
    
    						if (ContinueDebugEvent(de.dwProcessId,
    						                       de.dwThreadId,
    						                       de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE))
    							continue;
    
    						PrintConsole(hConsole,
    						             L"ContinueDebugEvent() returned error %lu\n",
    						             dwError = GetLastError());
    						break;
    					}
    					while (hProcess != NULL);
    
    					PrintConsole(hConsole, L"\n");
    
    					if (WaitForSingleObject(pi.hThread, INFINITE) == WAIT_FAILED)
    						PrintConsole(hConsole,
    						             L"WaitForSingleObject() returned error %lu\n",
    						             dwError = GetLastError());
    
    					if (!GetExitCodeThread(pi.hThread, &dwThread))
    						PrintConsole(hConsole,
    						             L"GetExitCodeThread() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						if (dwThread > 65535)
    							PrintConsole(hConsole,
    							             L"Primary thread %lu of debuggee process %lu exited with code 0x%08lX\n",
    							             pi.dwThreadId, pi.dwProcessId, dwThread);
    						else
    							PrintConsole(hConsole,
    							             L"Primary thread %lu of debuggee process %lu exited with code %lu\n",
    							             pi.dwThreadId, pi.dwProcessId, dwThread);
    
    					if (!GetThreadTimes(pi.hThread,
    					                    (LPFILETIME) uli,
    					                    (LPFILETIME) uli + 1,
    					                    (LPFILETIME) uli + 2,
    					                    (LPFILETIME) uli + 3))
    						PrintConsole(hConsole,
    						             L"GetThreadTimes() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    					{
    						PrintConsole(hConsole,
    						             L"Primary thread times:\n");
    
    						uli[1].QuadPart -= uli[0].QuadPart;
    
    						for (dwThread = 1; dwThread < 4; dwThread++)
    							PrintConsole(hConsole,
    							             L"\t%ls = %10lu.%07lu s\n",
    							             szTimes[dwThread],
    #ifdef _M_IX86
    							             SplitFileTime(uli[dwThread].LowPart, uli[dwThread].HighPart));
    #else
    							             (DWORD) (uli[dwThread].QuadPart / 10000000),
    							             (DWORD) (uli[dwThread].QuadPart % 10000000));
    #endif
    					}
    
    					if (!CloseHandle(pi.hThread))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             dwError = GetLastError());
    
    					if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED)
    						PrintConsole(hConsole,
    						             L"WaitForSingleObject() returned error %lu\n",
    						             dwError = GetLastError());
    
    					if (!GetExitCodeProcess(pi.hProcess, &dwProcess))
    						PrintConsole(hConsole,
    						             L"GetExitCodeProcess() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						if (dwProcess > 65535)
    							PrintConsole(hConsole,
    							             L"Debuggee process %lu exited with code 0x%08lX\n",
    							             pi.dwProcessId, dwProcess);
    						else
    							PrintConsole(hConsole,
    							             L"Debuggee process %lu exited with code %lu\n",
    							             pi.dwProcessId, dwProcess);
    
    					if (!GetProcessTimes(pi.hProcess,
    					                     (LPFILETIME) uli,
    					                     (LPFILETIME) uli + 1,
    					                     (LPFILETIME) uli + 2,
    					                     (LPFILETIME) uli + 3))
    						PrintConsole(hConsole,
    						             L"GetProcessTimes() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    					{
    						PrintConsole(hConsole,
    						             L"Debuggee process times:\n");
    
    						uli[1].QuadPart -= uli[0].QuadPart;
    
    						for (dwProcess = 1; dwProcess < 4; dwProcess++)
    							PrintConsole(hConsole,
    							             L"\t%ls = %10lu.%07lu s\n",
    							             szTimes[dwProcess],
    #ifdef _M_IX86
    							             SplitFileTime(uli[dwProcess].LowPart, uli[dwProcess].HighPart));
    #else
    							             (DWORD) (uli[dwProcess].QuadPart / 10000000),
    							             (DWORD) (uli[dwProcess].QuadPart % 10000000));
    #endif
    					}
    
    					if (!CloseHandle(pi.hProcess))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             dwError = GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file DEBUGGER.C created in step 1., link the compiled object file DEBUGGER.OBJ and cleanup afterwards:

    SET CL=/DDELAYLOADINFO /DSYMBOLS /GAFS /Gs69632 /Gy /O2isy /UVERBOSE /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:6.0 /RELEASE /STACK:1048576,65536 /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeDEBUGGER.COM DEBUGGER.C KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE DEBUGGER.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    DEBUGGER.C
    delayimp.h(67) : warning C4201: nonstandard extension used : nameless struct/union
    DEBUGGER.C(754) : warning C4100: 'hProcess' : unreferenced formal parameter
    DEBUGGER.C(1111) : warning C4090: 'function' : different 'const' qualifiers
    DEBUGGER.C(1293) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1293) : warning C4024: 'SymLoadModuleExW' : different types for formal and actual parameter 5
    DEBUGGER.C(1319) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1319) : warning C4024: 'SymLoadModuleEx' : different types for formal and actual parameter 5
    DEBUGGER.C(1389) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1389) : warning C4024: 'SymLoadModuleEx' : different types for formal and actual parameter 5
    DEBUGGER.C(1467) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPTHREAD_START_ROUTINE'
    DEBUGGER.C(1467) : warning C4024: 'NameLookup' : different types for formal and actual parameter 2
    DEBUGGER.C(1500) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPTHREAD_START_ROUTINE'
    DEBUGGER.C(1500) : warning C4024: 'NameLookup' : different types for formal and actual parameter 2
    DEBUGGER.C(1595) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1595) : warning C4024: 'SymLoadModuleExW' : different types for formal and actual parameter 5
    DEBUGGER.C(1621) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1621) : warning C4024: 'SymLoadModuleEx' : different types for formal and actual parameter 5
    DEBUGGER.C(1689) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1689) : warning C4024: 'SymLoadModuleEx' : different types for formal and actual parameter 5
    DEBUGGER.C(1760) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1760) : warning C4024: 'NameLookup' : different types for formal and actual parameter 2
    DEBUGGER.C(1784) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1784) : warning C4024: 'NameLookup' : different types for formal and actual parameter 2
    DEBUGGER.C(1787) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPVOID'
    DEBUGGER.C(1787) : warning C4024: 'SymUnloadModule64' : different types for formal and actual parameter 2
    DEBUGGER.C(1811) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'LPSTR'
    DEBUGGER.C(1811) : warning C4024: 'NameLookup' : different types for formal and actual parameter 2
    DEBUGGER.C(1923) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'PVOID'
    DEBUGGER.C(1923) : warning C4024: 'NameLookup' : different types for formal and actual parameter 2
    DEBUGGER.C(1966) : warning C4047: 'function' : 'DWORD64' differs in levels of indirection from 'PVOID'
    DEBUGGER.C(1966) : warning C4024: 'NameLookup' : different types for formal and actual parameter 2
    DEBUGGER.C(1502) : warning C4701: potentially uninitialized local variable 'hProcess' used
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Debug String Monitor

Purpose
Background Information
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Monitor debug strings written from all processes running in the current (user) session with the Win32 function OutputDebugString().

Background Information

In Win32 processes that are run under a debugger, debug strings written with the Win32 function OutputDebugString() are catched and typically displayed by the debugger.

In Win32 processes that are not run under a debugger, the Win32 function OutputDebugString() checks whether the shared memory section named DBWIN_BUFFER as well as the events named DBWIN_BUFFER_READY and DBWIN_DATA_READY exist; if yes, it waits until the event DBWIN_BUFFER_READY is signaled, writes the process identifier and its argument into the shared memory section DBWIN_BUFFER, signals the event DBWIN_DATA_READY and returns to its caller.

Synopsis

DBWINNER.COM

Downloads

The console application is available in two functional identical forms: DBWINNER.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and DBWINNER.COM, a small form without these extras.

Implementation and Build Details

Debug String Monitor is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Debug String Monitor from the source presented hereafter.
  1. Create the text file DBWINNER.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    const	LPCSTR	szCtrlType[] = {"Ctrl-C",
    		                "Ctrl-Break",
    		                "Ctrl-Close",
    		                NULL,
    		                NULL,
    		                "Ctrl-Logoff",
    		                "Ctrl-Shutdown"};
    
    BOOL	WINAPI	CtrlHandler(DWORD dwCtrlType)
    {
    	switch (dwCtrlType)
    	{
    	case CTRL_C_EVENT:
    	case CTRL_BREAK_EVENT:
    	case CTRL_CLOSE_EVENT:
    	case CTRL_LOGOFF_EVENT:
    	case CTRL_SHUTDOWN_EVENT:
    
    		OutputDebugStringA(szCtrlType[dwCtrlType]);
    
    		return TRUE;
    
    	default:
    		return FALSE;
    	}
    }
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    typedef	struct	_dbwin_buffer
    {
    	DWORD	dwProcessId;
    	CHAR	szString[4096 - sizeof(DWORD)];
    } DBWIN_BUFFER;
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	DBWIN_BUFFER	*lpDBWin;
    
    	HANDLE	hDBWin;
    	HANDLE	hDBWinBuffer;
    	HANDLE	hDBWinData;
    	DWORD	dwDBWinData;
    	DWORD	dwString;
    	DWORD	dwError = ERROR_SUCCESS;
    	DWORD	dwProcessId = 0;
    	DWORD	dwCurrentProcessId = GetCurrentProcessId();
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		hDBWin = CreateFileMapping(INVALID_HANDLE_VALUE,
    		                           (LPSECURITY_ATTRIBUTES) NULL,
    		                           PAGE_READWRITE,
    		                           0,
    		                           sizeof(DBWIN_BUFFER),
    		                           L"DBWIN_BUFFER");
    		dwError = GetLastError();
    
    		if (hDBWin == NULL)
    			PrintConsole(hConsole,
    			             L"CreateFileMapping() returned error %lu\n",
    			             dwError);
    		else
    		{
    			if (dwError == ERROR_ALREADY_EXISTS)
    				PrintConsole(hConsole,
    				             L"Shared section \'DBWIN_BUFFER\' already created by another process!\n");
    			else
    			{
    				hDBWinBuffer = CreateEvent((LPSECURITY_ATTRIBUTES) NULL,
    				                           FALSE,
    				                           FALSE,
    				                           L"DBWIN_BUFFER_READY");
    				dwError = GetLastError();
    
    				if (hDBWinBuffer == NULL)
    					PrintConsole(hConsole,
    					             L"CreateEvent() returned error %lu\n",
    					             dwError);
    				else
    				{
    					if (dwError == ERROR_ALREADY_EXISTS)
    						PrintConsole(hConsole,
    						             L"Event \'DBWIN_BUFFER_READY\' already created by another process!\n");
    					else
    					{
    						hDBWinData = CreateEvent((LPSECURITY_ATTRIBUTES) NULL,
    						                         FALSE,
    						                         FALSE,
    						                         L"DBWIN_DATA_READY");
    						dwError = GetLastError();
    
    						if (hDBWinData == NULL)
    							PrintConsole(hConsole,
    							             L"CreateEvent() returned error %lu\n",
    							             dwError);
    						else
    						{
    							if (dwError == ERROR_ALREADY_EXISTS)
    								PrintConsole(hConsole,
    								             L"Event \'DBWIN_DATA_READY\' already created by another process!\n");
    							else
    							{
    								lpDBWin = MapViewOfFile(hDBWin,
    								                        SECTION_MAP_READ | SECTION_MAP_WRITE,
    								                        0, 0,
    								                        (SIZE_T) 0);
    
    								if (lpDBWin == NULL)
    									PrintConsole(hConsole,
    									             L"MapViewOfFile() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    								{
    									if (!SetConsoleCtrlHandler(CtrlHandler, TRUE))
    										PrintConsole(hConsole,
    										             L"SetConsoleCtrlHandler() returned error %lu\n",
    										             dwError = GetLastError());
    
    									PrintConsole(hConsole,
    									             L"Press \'Ctrl-C\' or \'Ctrl-Break\' to stop!\n"
    									             L"\n"
    									             L"Process\tDebug String\n");
    									do
    									{
    										dwDBWinData = SignalObjectAndWait(hDBWinBuffer,
    										                                  hDBWinData,
    										                                  INFINITE,
    										                                  FALSE);
    
    										if (dwDBWinData != WAIT_OBJECT_0)
    											break;
    
    										dwString = strlen(lpDBWin->szString);
    
    										while ((dwString-- > 0)
    										    && ((lpDBWin->szString[dwString] == ' ')
    										     || (lpDBWin->szString[dwString] == '\a')
    										     || (lpDBWin->szString[dwString] == '\b')
    										     || (lpDBWin->szString[dwString] == '\f')
    										     || (lpDBWin->szString[dwString] == '\n')
    										     || (lpDBWin->szString[dwString] == '\r')
    										     || (lpDBWin->szString[dwString] == '\t')
    										     || (lpDBWin->szString[dwString] == '\v')))
    											/* lpDBWin->szString[dwString] = '\0' */;
    
    										lpDBWin->szString[++dwString] = '\0';
    
    										if (lpDBWin->dwProcessId != dwProcessId)
    											PrintConsole(hConsole,
    											             L"\n"
    											             L"%7lu\t%hs\n",
    											             dwProcessId = lpDBWin->dwProcessId,
    											             lpDBWin->szString);
    										else
    											PrintConsole(hConsole,
    											             L"\t%hs\n",
    											             lpDBWin->szString);
    									} while (dwProcessId != dwCurrentProcessId);
    
    									if (dwDBWinData == WAIT_FAILED)
    										PrintConsole(hConsole,
    										             L"SignalObjectAndWait() returned error %lu\n",
    										             dwError = GetLastError());
    
    									if (!SetConsoleCtrlHandler(CtrlHandler, FALSE))
    										PrintConsole(hConsole,
    										             L"SetConsoleCtrlHandler() returned error %lu\n",
    										             GetLastError());
    
    									if (!UnmapViewOfFile(lpDBWin))
    										PrintConsole(hConsole,
    										             L"UnmapViewOfFile() returned error %lu\n",
    										             GetLastError());
    								}
    							}
    
    							if (!CloseHandle(hDBWinData))
    								PrintConsole(hConsole,
    								             L"CloseHandle() returned error %lu\n",
    								             GetLastError());
    						}
    					}
    
    					if (!CloseHandle(hDBWinBuffer))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (!CloseHandle(hDBWin))
    				PrintConsole(hConsole,
    				             L"CloseHandle() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file DBWINNER.C created in step 1., link the compiled object file DBWINNER.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeDBWINNER.COM DBWINNER.C KERNEL32.LIB USER32.LIB
    ERASE DBWINNER.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    DBWINNER.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Language Enumerator

Purpose
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Enumerate Languages via Language Identifiers and print the (localised) Language Names.

Synopsis

LANGUAGE.COM

Downloads

The console application is available in two functional identical forms: LANGUAGE.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and LANGUAGE.COM, a small form without these extras.

Implementation and Build Details

Language Enumerator is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Language Enumerator from the source presented hereafter.
  1. Create the text file LANGUAGE.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	DWORD	dwError = ERROR_SUCCESS;
    	DWORD	dwPrimaryLanguage;
    	DWORD	dwLanguage;
    	WCHAR	szLanguage[123];
    	WCHAR	szNeutral[123];
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		if (VerLanguageName(0,
    		                    szNeutral,
    		                    sizeof(szNeutral) / sizeof(*szNeutral)) == 0)
    			PrintConsole(hConsole,
    			             L"VerLanguageName() returned error %lu for LCID 0x%04lX\n",
    			             dwError = GetLastError(), 0);
    		else
    		{
    			PrintConsole(hConsole,
    			             L"\n0x%04lX = %ls\n",
    			             0, szNeutral);
    
    			for (dwPrimaryLanguage = 0; dwPrimaryLanguage < 0x0200; dwPrimaryLanguage++)
    				for (dwLanguage = dwPrimaryLanguage; dwLanguage < 0x8000; dwLanguage += 0x0400)
    					if (VerLanguageName(dwLanguage,
    					                    szLanguage,
    					                    sizeof(szLanguage) / sizeof(*szLanguage)) == 0)
    						PrintConsole(hConsole,
    						             L"VerLanguageName() returned error %lu for LCID 0x%04lX\n",
    						             dwError = GetLastError(), dwLanguage);
    					else
    						if (wcscmp(szLanguage, szNeutral) != 0)
    							PrintConsole(hConsole,
    							             L"\n0x%04lX = %ls\n" + (dwLanguage != dwPrimaryLanguage),
    							             dwLanguage, szLanguage);
    						else
    							if ((dwLanguage != 0)
    							 && (dwLanguage == dwPrimaryLanguage))
    								break;
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file LANGUAGE.C created in step 1., link the compiled object file LANGUAGE.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeLANGUAGE.COM LANGUAGE.C KERNEL32.LIB USER32.LIB
    ERASE LANGUAGE.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    LANGUAGE.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Locale Enumerator

Purpose
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Enumerate Locales via Locale Identifiers and print the localised, english plus native Locale Names.

Synopsis

LOCALE.COM

Downloads

The console application is available in two functional identical forms: LOCALE.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and LOCALE.COM, a small form without these extras.

Implementation and Build Details

Locale Enumerator is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Locale Enumerator from the source presented hereafter.
  1. Create the text file LOCALE.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	DWORD	dwError = ERROR_SUCCESS;
    	DWORD	dwPrimaryLanguage;
    	DWORD	dwLanguage;
    	BOOL	bLanguage;
    	WCHAR	szLanguage[123];
    	WCHAR	szEnglishLanguage[123];
    	WCHAR	szEnglishCountry[123];
    #ifdef NATIVE
    	WCHAR	szNativeLanguage[80];
    	WCHAR	szNativeCountry[80];
    #endif
    	WCHAR	szISO639[9];
    	WCHAR	szISO3166[9];
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		for (dwPrimaryLanguage = 0; ++dwPrimaryLanguage < 0x0200;)
    		{
    			bLanguage = FALSE;
    
    			for (dwLanguage = dwPrimaryLanguage; dwLanguage += 0x0400, dwLanguage < 0x8000;)
    				if (GetLocaleInfo(dwLanguage,
    				                  LOCALE_SLANGUAGE,
    				                  szLanguage,
    				                  sizeof(szLanguage) / sizeof(*szLanguage)) == 0)
    				{
    					dwError = GetLastError();
    
    					if (dwError == ERROR_INVALID_PARAMETER)
    						dwError = ERROR_SUCCESS;
    					else
    						PrintConsole(hConsole,
    						             L"GetLocaleInfo() returned error %lu for LCID 0x%04lX\n",
    						             dwError, dwLanguage);
    				}
    				else
    				{
    					if (GetLocaleInfo(dwLanguage,
    					                  LOCALE_SISO639LANGNAME,
    					                  szISO639,
    					                  sizeof(szISO3166) / sizeof(*szISO3166)) == 0)
    						PrintConsole(hConsole,
    						             L"GetLocaleInfo() returned error %lu for LCID 0x%04lX\n",
    						             dwError = GetLastError(), dwLanguage);
    
    					if (GetLocaleInfo(dwLanguage,
    					                  LOCALE_SISO3166CTRYNAME,
    					                  szISO3166,
    					                  sizeof(szISO3166) / sizeof(*szISO3166)) == 0)
    						PrintConsole(hConsole,
    						             L"GetLocaleInfo() returned error %lu for LCID 0x%04lX\n",
    						             dwError = GetLastError(), dwLanguage);
    
    					if (GetLocaleInfo(dwLanguage,
    					                  LOCALE_SENGLANGUAGE,
    					                  szEnglishLanguage,
    					                  sizeof(szEnglishLanguage) / sizeof(*szEnglishLanguage)) == 0)
    						PrintConsole(hConsole,
    						             L"GetLocaleInfo() returned error %lu for LCID 0x%04lX\n",
    						             dwError = GetLastError(), dwLanguage);
    
    					if (GetLocaleInfo(dwLanguage,
    					                  LOCALE_SENGCOUNTRY,
    					                  szEnglishCountry,
    					                  sizeof(szEnglishCountry) / sizeof(*szEnglishCountry)) == 0)
    						PrintConsole(hConsole,
    						             L"GetLocaleInfo() returned error %lu for LCID 0x%04lX\n",
    						             dwError = GetLastError(), dwLanguage);
    #ifdef NATIVE
    					if (GetLocaleInfo(dwLanguage,
    					                  LOCALE_SNATIVELANGNAME,
    					                  szNativeLanguage,
    					                  sizeof(szNativeLanguage) / sizeof(*szNativeLanguage)) == 0)
    						PrintConsole(hConsole,
    						             L"GetLocaleInfo() returned error %lu for LCID 0x%04lX\n",
    						             dwError = GetLastError(), dwLanguage);
    
    					if (GetLocaleInfo(dwLanguage,
    					                  LOCALE_SNATIVECTRYNAME,
    					                  szNativeCountry,
    					                  sizeof(szNativeCountry) / sizeof(*szNativeCountry)) == 0)
    						PrintConsole(hConsole,
    						             L"GetLocaleInfo() returned error %lu for LCID 0x%04lX\n",
    						             dwError = GetLastError(), dwLanguage);
    
    					PrintConsole(hConsole,
    					             L"\n0x%04lX = %ls // %ls-%ls;%ls (%ls), %ls (%ls)\n" + bLanguage,
    					             dwLanguage,
    					             szLanguage,
    					             szISO639,
    					             szISO3166,
    					             szEnglishLanguage,
    					             szEnglishCountry,
    					             szNativeLanguage,
    					             szNativeCountry);
    #else
    					PrintConsole(hConsole,
    					             L"\n0x%04lX = %ls // %ls-%ls;%ls (%ls)\n" + bLanguage,
    					             dwLanguage,
    					             szLanguage,
    					             szISO639,
    					             szISO3166,
    					             szEnglishLanguage,
    					             szEnglishCountry);
    #endif
    					bLanguage = TRUE;
    
    				}
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file LOCALE.C created in step 1., link the compiled object file LOCALE.OBJ and cleanup afterwards:

    SET CL=/DNATIVE /GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeLOCALE.COM LOCALE.C KERNEL32.LIB USER32.LIB
    ERASE LOCALE.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    LOCALE.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Network Enumerator

Purpose
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Enumerate network resources.

Synopsis

NETWORK.COM

Downloads

The console application is available in two functional identical forms: NETWORK.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and NETWORK.COM, a small form without these extras.

Implementation and Build Details

Network Enumerator is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Network Enumerator from the source presented hereafter.
  1. Create the text file NETWORK.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <winnetwk.h>
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    const	LPCWSTR	szDisplayType[] = {L"Generic",
    		                   L"Domain",
    		                   L"Server",
    		                   L"Share",
    		                   L"File",
    		                   L"Group",
    		                   L"Network",
    		                   L"Root",
    		                   L"Administrative Share",
    		                   L"Directory",
    		                   L"Tree",
    		                   L"NDS Container"};
    
    __declspec(safebuffers)
    VOID	WINAPI	Network(HANDLE hConsole, LPNETRESOURCE lpNR, DWORD dwLevel)
    {
    	NETRESOURCE	nr[80];
    
    	HANDLE	hNetwork;
    	DWORD	dwCount;
    	DWORD	dwSize;
    
    	DWORD	dwError = WNetOpenEnum(RESOURCE_GLOBALNET,
    		                       RESOURCETYPE_ANY,
    #if 0
    		                       RESOURCEUSAGE_ALL,
    #else
    		                       0,
    #endif
    		                       lpNR,
    		                       &hNetwork);
    
    	if (dwError != ERROR_SUCCESS)
    		PrintConsole(hConsole,
    		             L"WNetOpenEnum() returned error %lu\n",
    	                     dwError);
    	else
    	{
    		for (;;)
    		{
    			dwCount = 1;
    			dwSize = sizeof(nr);
    			dwError = WNetEnumResource(hNetwork,
    			                           &dwCount,
    			                           nr,
    			                           &dwSize);
    
    			if (dwError != ERROR_SUCCESS)
    				break;
    
    			PrintConsole(hConsole,
    			             L"\n"
    			             L"%lsScope:\t\t%lu\n"
    			             L"%lsType:\t\t%lu\n"
    			             L"%lsDisplay Type:\t%lu = %ls\n"
    			             L"%lsUsage:\t\t0x%08lX\n"
    			             L"%lsLocal Name:\t%ls\n"
    			             L"%lsRemote Name:\t%ls\n"
    			             L"%lsComment:\t%ls\n"
    			             L"%lsProvider:\t%ls\n",
    			             L"\t\t\t" + 3 + dwLevel, nr->dwScope,
    			             L"\t\t\t" + 3 + dwLevel, nr->dwType,
    			             L"\t\t\t" + 3 + dwLevel, nr->dwDisplayType,
    			             nr->dwDisplayType < sizeof(szDisplayType) / sizeof(*szDisplayType) ? szDisplayType[nr->dwDisplayType] : L"Unknown",
    			             L"\t\t\t" + 3 + dwLevel, nr->dwUsage,
    			             L"\t\t\t" + 3 + dwLevel, nr->lpLocalName,
    			             L"\t\t\t" + 3 + dwLevel, nr->lpRemoteName,
    			             L"\t\t\t" + 3 + dwLevel, nr->lpComment,
    			             L"\t\t\t" + 3 + dwLevel, nr->lpProvider);
    
    			if (nr->dwUsage & RESOURCEUSAGE_CONTAINER)
    				Network(hConsole, nr, dwLevel - 1);
    		}
    
    		if (dwError != ERROR_NO_MORE_ITEMS)
    			PrintConsole(hConsole,
    			             L"WNetEnumResource() returned error %lu\n",
    			             dwError);
    
    		dwError = WNetCloseEnum(hNetwork);
    
    		if (dwError != ERROR_SUCCESS)
    			PrintConsole(hConsole,
    			             L"WNetCloseEnum() returned error %lu\n",
    			             dwError);
    	}
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	DWORD	dwError = ERROR_SUCCESS;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		Network(hConsole, (LPNETRESOURCE) NULL, 0);
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file NETWORK.C created in step 1., link the compiled object file NETWORK.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeNETWORK.COM NETWORK.C KERNEL32.LIB MPR.LIB USER32.LIB
    ERASE NETWORK.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    NETWORK.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Directory Change Notifier

Purpose
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Monitor up to 64 directory trees, specified by their absolute or relative pathnames, for changes.

Synopsis

NOTIFIER.COM ‹directory name› …

Downloads

The console application is available in two functional identical forms: NOTIFIER.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and NOTIFIER.COM, a small form without these extras.

Implementation and Build Details

Directory Change Notifier is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows Vista and newer versions of Windows NT as well as Windows PE 2.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Directory Change Notifier from the source presented hereafter.
  1. Create the text file NOTIFIER.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #define FILE_NOTIFY_CHANGE_UNDOCUMENTED	0x00000E80UL
    #define FILE_NOTIFY_CHANGE_ANY		0x00000FFFUL
    #define FILE_NOTIFY_CHANGE_INVALID	0xFFFFF000UL
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    HANDLE	hThreads[MAXIMUM_WAIT_OBJECTS];
    DWORD	dwThreads = 0;
    
    const	LPCWSTR	szCtrlType[] = {L"C",
    		                L"Break",
    		                L"Close",
    		                NULL,
    		                NULL,
    		                L"Logoff",
    		                L"Shutdown"};
    
    BOOL	WINAPI	CtrlHandler(DWORD dwCtrlType)
    {
    	DWORD	dwThread = dwThreads;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	switch (dwCtrlType)
    	{
    	case CTRL_C_EVENT:
    	case CTRL_BREAK_EVENT:
    	case CTRL_CLOSE_EVENT:
    	case CTRL_LOGOFF_EVENT:
    	case CTRL_SHUTDOWN_EVENT:
    
    		PrintConsole(hConsole,
    		             L"Ctrl-%ls\n",
    		             szCtrlType[dwCtrlType]);
    
    		while (dwThread-- > 0)
    			if (!CancelSynchronousIo(hThreads[dwThread]))
    				PrintConsole(hConsole,
    				             L"CancelSynchronousIo() returned error %lu for thread 0x%p\n",
    				             GetLastError(), hThreads[dwThread]);
    
    		return TRUE;
    
    	default:
    		return FALSE;
    	}
    }
    
    const	LPCWSTR	lpAction[] = {NULL,
    		              L"Added",
    		              L"Removed",
    		              L"Modified",
    		              L"Renamed from",
    		              L"Renamed to"};
    
    __declspec(safebuffers)
    DWORD	WINAPI	ThreadProc(LPCWSTR lpArgument)
    {
    	FILE_NOTIFY_INFORMATION	*lpEntry;
    #if 0
    	BY_HANDLE_FILE_INFORMATION	bhfi;
    #else
    	FILE_ATTRIBUTE_TAG_INFO		fati;
    #endif
    	HANDLE	hArgument;
    	WCHAR	szArgument[MAX_PATH];
    	DWORD	dwArgument;
    	DWORD	dwError = ERROR_SUCCESS;
    	DWORD	dwEntry;
    	DWORD	dwBuffer[65536 / sizeof(DWORD)];
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		hArgument = CreateFile(lpArgument,
    		                       FILE_LIST_DIRECTORY,
    		                       FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
    		                       (LPSECURITY_ATTRIBUTES) NULL,
    		                       OPEN_EXISTING,
    		                       FILE_FLAG_BACKUP_SEMANTICS,
    		                       (HANDLE) NULL);
    
    		if (hArgument == INVALID_HANDLE_VALUE)
    			PrintConsole(hConsole,
    			             L"CreateFile() returned error %lu for argument \'%ls\'\n",
    			             dwError = GetLastError(), lpArgument);
    		else
    		{
    #if 0
    			if (!GetFileInformationByHandle(hArgument,
    			                                &bhfi))
    				PrintConsole(hConsole,
    				             L"GetFileInformationByHandle() returned error %lu for argument \'%ls\'\n",
    				             dwError = GetLastError(), lpArgument);
    			else
    				if (((bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
    				 || ((bhfi.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT))
    #else
    			if (!GetFileInformationByHandleEx(hArgument,
    			                                  FileAttributeTagInfo,
    			                                  &fati,
    			                                  sizeof(fati)))
    				PrintConsole(hConsole,
    				             L"GetFileInformationByHandleEx() returned error %lu for argument \'%ls\'\n",
    				             dwError = GetLastError(), lpArgument);
    			else
    				if (((fati.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
    				 || ((fati.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT))
    #endif
    					PrintConsole(hConsole,
    					             L"Argument \'%ls\' is not a directory!\n",
    					             lpArgument);
    				else
    				{
    					dwArgument = GetFinalPathNameByHandle(hArgument,
    					                                      szArgument,
    					                                      sizeof(szArgument) / sizeof(*szArgument),
    					                                      FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
    
    					if (dwArgument == 0)
    						PrintConsole(hConsole,
    						             L"GetFinalPathNameByHandle() returned error %lu for argument \'%ls\'\n",
    						             dwError = GetLastError(), lpArgument);
    					else
    					{
    						while (ReadDirectoryChangesW(hArgument,
    						                             dwBuffer,
    						                             sizeof(dwBuffer),
    						                             TRUE,
    #ifdef FILE_NOTIFY_CHANGE_ALL
    						                             FILE_NOTIFY_CHANGE_ALL,
    #else
    						                             FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_SIZE,
    #endif
    						                             &dwEntry,
    						                             (LPOVERLAPPED) NULL,
    						                             (LPOVERLAPPED_COMPLETION_ROUTINE) NULL))
    							for (lpEntry = (PFILE_NOTIFY_INFORMATION) dwBuffer;
    							     dwEntry != 0;
    							     lpEntry = (PFILE_NOTIFY_INFORMATION) ((LPBYTE) lpEntry + dwEntry))
    							{
    								dwEntry = lpEntry->NextEntryOffset;
    								lpEntry->FileName[lpEntry->FileNameLength / sizeof(lpEntry->FileName[0])] = L'\0';
    
    								PrintConsole(hConsole,
    								             L"%ls %ls\\%ls\n",
    								             lpAction[lpEntry->Action], szArgument + 4, lpEntry->FileName);
    							}
    
    						PrintConsole(hConsole,
    						             L"ReadDirectoryChanges() returned error %lu for directory \'%ls\'\n",
    						             dwError = GetLastError(), szArgument + 4);
    					}
    				}
    
    			if (!CloseHandle(hArgument))
    				PrintConsole(hConsole,
    				             L"CloseHandle() returned error %lu\n",
    				             GetLastError());
    		}
    	}
    
    	return dwError;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 1;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwThreadId;
    	HANDLE	hThread;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"Too few arguments: at least one directory name must be given!\n");
    			else if (nArguments > sizeof(hThreads) / sizeof(*hThreads) + 1)
    				PrintConsole(hConsole,
    				             L"Too many arguments: at most %lu directory names may be given!\n",
    				             sizeof(hThreads) / sizeof(*hThreads));
    			else
    			{
    				do
    				{
    					hThread = CreateThread((LPSECURITY_ATTRIBUTES) NULL,
    					                       (SIZE_T) 65536,
    					                       ThreadProc,
    					                       lpArguments[nArgument],
    					                       0,
    					                       &dwThreadId);
    
    					if (hThread == NULL)
    						PrintConsole(hConsole,
    						             L"CreateThread() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    					{
    						hThreads[dwThreads++] = hThread;
    
    						PrintConsole(hConsole,
    						             L"Thread %lu created for argument \'%ls\'\n",
    						             dwThreadId, lpArguments[nArgument]);
    					}
    				} while (++nArgument < nArguments);
    
    				if (dwThreads > 0)
    				{
    					if (!SetConsoleCtrlHandler(CtrlHandler, TRUE))
    						PrintConsole(hConsole,
    						             L"SetConsoleCtrlHandler() returned error %lu\n",
    						             dwError = GetLastError());
    
    					PrintConsole(hConsole,
    					             L"Press \'Ctrl-C\' or \'Ctrl-Break\' to stop!\n"
    					             L"\n");
    
    					if (WaitForMultipleObjects(dwThreads,
    					                           hThreads,
    					                           TRUE,
    					                           INFINITE) == WAIT_FAILED)
    						PrintConsole(hConsole,
    						             L"WaitForMultipleObjects() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						do
    							if (!CloseHandle(hThreads[--dwThreads]))
    								PrintConsole(hConsole,
    								             L"CloseHandle() returned error %lu\n",
    								             GetLastError());
    						while (dwThreads > 0);
    
    					if (!SetConsoleCtrlHandler(CtrlHandler, FALSE))
    						PrintConsole(hConsole,
    						             L"SetConsoleCtrlHandler() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file NOTIFIER.C created in step 1., link the compiled object file NOTIFIER.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gs69632 /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:6.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeNOTIFIER.COM NOTIFIER.C KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE NOTIFIER.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    NOTIFIER.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Portable Executable Metadata Reader

Purpose
Background Information
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Enumerate the metadata of portable executable image files, i.e. applications, (resource) DLLs, drivers etc., print them in UTF-16LE encoding on standard output (which must be redirected to a file or piped into an application that reads from standard input, like Clip, Find or More).

Background Information

The MSDN article PE Format documents the disk layout of portable executable image files; Matt Pietrek’s MSDN magazine articles Peering Inside the PE - A Tour of the Win32 Portable Executable File Format, An In-Depth Look into the Win32 Portable Executable File Format and An In-Depth Look into the Win32 Portable Executable File Format, Part 2 provide additional information.

Synopsis

PE32PLUS.COM ‹image file name› >‹output file name›
PE32PLUS.COM ‹image file name› | CLIP.COM
PE32PLUS.COM ‹image file name› | MORE.COM

Downloads

The console application is available in two functional identical forms: PE32PLUS.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and PE32PLUS.COM, a small form without these extras.

Implementation and Build Details

Portable Executable Metadata Reader is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Portable Executable Metadata Reader from the source presented hereafter.
  1. Create the text file PE32PLUS.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <wintrust.h>
    #include <shellapi.h>
    
    #ifndef IMAGE_DEBUG_TYPE_VC_FEATURE
    #define IMAGE_DEBUG_TYPE_VC_FEATURE	12
    #endif
    
    #ifndef IMAGE_DEBUG_TYPE_POGO
    #define IMAGE_DEBUG_TYPE_POGO		13
    #endif
    
    #ifndef IMAGE_DEBUG_TYPE_ILTCG
    #define IMAGE_DEBUG_TYPE_ILTCG		14
    #endif
    
    #ifndef IMAGE_DEBUG_TYPE_MPX
    #define IMAGE_DEBUG_TYPE_MPX		15
    #endif
    
    #ifndef IMAGE_DEBUG_TYPE_REPRO
    #define IMAGE_DEBUG_TYPE_REPRO		16
    #endif
    
    #define IMAGE_DLLCHARACTERISTICS_RESERVED		0x000FU
    
    #ifndef IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
    #define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA	0x0020U
    #endif
    
    #ifndef IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
    #define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE		0x0040U
    #endif
    
    #ifndef IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY
    #define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY	0x0080U
    #endif
    
    #ifndef IMAGE_DLLCHARACTERISTICS_NX_COMPAT
    #define IMAGE_DLLCHARACTERISTICS_NX_COMPAT		0x0100U
    #endif
    
    #ifndef IMAGE_DLLCHARACTERISTICS_APPCONTAINER
    #define IMAGE_DLLCHARACTERISTICS_APPCONTAINER		0x1000U
    #endif
    
    #ifndef IMAGE_DLLCHARACTERISTICS_GUARD_CF
    #define IMAGE_DLLCHARACTERISTICS_GUARD_CF		0x4000U
    #endif
    
    #ifndef IMAGE_FILE_16BIT_MACHINE
    #define IMAGE_FILE_16BIT_MACHINE	0x0040U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_TARGET_HOST
    #define IMAGE_FILE_MACHINE_TARGET_HOST	0x0001U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_I860
    #define IMAGE_FILE_MACHINE_I860		0x014DU
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_ARMNT
    #define IMAGE_FILE_MACHINE_ARMNT	0x01C4U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_M68K
    #define IMAGE_FILE_MACHINE_M68K		0x0268U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_PARISC
    #define IMAGE_FILE_MACHINE_PARISC	0x0290U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_CHPE_X86
    #define IMAGE_FILE_MACHINE_CHPE_X86	0x3A64U	// Compiled Hybrid PE
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_RISCV32
    #define IMAGE_FILE_MACHINE_RISCV32	0x5032U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_RISCV64
    #define IMAGE_FILE_MACHINE_RISCV64	0x5064U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_RISCV128
    #define IMAGE_FILE_MACHINE_RISCV128	0x5128U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_LOONGARCH32
    #define IMAGE_FILE_MACHINE_LOONGARCH32	0x6232U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_LOONGARCH64
    #define IMAGE_FILE_MACHINE_LOONGARCH64	0x6264U
    #endif
    
    #ifndef IMAGE_FILE_MACHINE_ARM64
    #define IMAGE_FILE_MACHINE_ARM64	0xAA64U
    #endif
    
    #ifndef IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT
    #define IMAGE_GUARD_CF_INSTRUMENTED			0x00000100UL
    #define IMAGE_GUARD_CFW_INSTRUMENTED			0x00000200UL
    #define IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT		0x00000400UL
    #define IMAGE_GUARD_SECURITY_COOKIE_UNUSED		0x00000800UL
    #define IMAGE_GUARD_PROTECT_DELAYLOAD_IAT		0x00001000UL
    #define IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION	0x00002000UL
    #define IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT	0x00004000UL
    #define IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION	0x00008000UL
    #define IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT		0x00010000UL
    #define IMAGE_GUARD_RF_INSTRUMENTED			0x00020000UL
    #define IMAGE_GUARD_RF_ENABLE				0x00040000UL
    #define IMAGE_GUARD_RF_STRICT				0x00080000UL
    #define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK		0xF0000000UL
    #define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT	28
    #endif
    
    #ifndef IMAGE_LOADER_FLAGS_COMPLUS
    #define IMAGE_LOADER_FLAGS_COMPLUS		0x00000001UL
    #endif
    
    #ifndef IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL
    #define IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL	0x01000000UL
    #endif
    
    #ifndef IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
    #define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION	16
    #endif
    
    #ifndef IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG
    #define IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG		17
    #endif
    
    #ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
    #define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR		0x00000100UL
    #define LOAD_LIBRARY_SEARCH_APPLICATION_DIR		0x00000200UL
    #define LOAD_LIBRARY_SEARCH_USER_DIRS			0x00000400UL
    #define LOAD_LIBRARY_SEARCH_SYSTEM32			0x00000800UL
    #define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS		0x00001000UL
    #define LOAD_LIBRARY_SEARCH_SAFE_CURRENT_DIRS		0x00002000UL
    #define LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER	0x00004000UL
    #define LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY		0x00008000UL
    #endif
    
    typedef	struct	_IMAGE_ARMNT_RUNTIME_FUNCTION_ENTRY
    {
    	DWORD	BeginAddress;
    	DWORD	UnwindData;
    } IMAGE_ARMNT_RUNTIME_FUNCTION_ENTRY, *LPIMAGE_ARMNT_RUNTIME_FUNCTION_ENTRY, *PIMAGE_ARMNT_RUNTIME_FUNCTION_ENTRY;
    
    typedef	struct	_IMAGE_DELAYLOAD_DESCRIPTOR
    {
    	union
    	{
    		DWORD	AllAttributes;
    		struct
    		{
    			DWORD	RvaBased           : 1;
    			DWORD	ReservedAttributes : 31;
    		};
    	} Attributes;
    
    	DWORD	DllNameRVA;
    	DWORD	ModuleHandleRVA;
    	DWORD	ImportAddressTableRVA;
    	DWORD	ImportNameTableRVA;
    	DWORD	BoundImportAddressTableRVA;
    	DWORD	UnloadInformationTableRVA;
    	DWORD	TimeDateStamp;
    } IMAGE_DELAYLOAD_DESCRIPTOR, *LPIMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;
    
    typedef	struct	_IMAGE_LOAD_CONFIGURATION_DIRECTORY32
    {
    	DWORD	Size;
    	DWORD	TimeDateStamp;
    	WORD	MajorVersion;
    	WORD	MinorVersion;
    	DWORD	GlobalFlagsClear;
    	DWORD	GlobalFlagsSet;
    	DWORD	CriticalSectionDefaultTimeout;
    	DWORD	DeCommitFreeBlockThreshold;
    	DWORD	DeCommitTotalFreeThreshold;
    	DWORD	LockPrefixTable;
    	DWORD	MaximumAllocationSize;
    	DWORD	VirtualMemoryThreshold;
    	DWORD	ProcessHeapFlags;
    	DWORD	ProcessAffinityMask;
    	WORD	CSDVersion;
    #if 0
    	WORD	Reserved1;
    #else
    	WORD	DependentLoadFlags;
    #endif
    	DWORD	EditList;
    	DWORD	SecurityCookie;
    	DWORD	SEHandlerTable;
    	DWORD	SEHandlerCount;
    						// Threshold 1 (1507)
    	DWORD	GuardCFCheckFunctionPointer;
    	DWORD	GuardCFDispatchFunctionPointer;
    	DWORD	GuardCFFunctionTable;
    	DWORD	GuardCFFunctionCount;
    	DWORD	GuardFlags;
    						// Threshold 2 (1511)
    	struct	// _IMAGE_LOAD_CONFIG_CODE_INTEGRITY
    	{
    		WORD	Flags;
    		WORD	Catalog;
    		DWORD	CatalogOffset;
    		DWORD	Reserved;
    	} CodeIntegrity;
    						// Redstone 1 (1607)
    	DWORD	GuardAddressTakenIatEntryTable;
    	DWORD	GuardAddressTakenIatEntryCount;
    	DWORD	GuardLongJumpTargetTable;
    	DWORD	GuardLongJumpTargetCount;
    						//
    	DWORD	DynamicValueRelocTable;
    	DWORD	CHPEMetadataPointer;
    						// Redstone 2 (1703)
    	DWORD	GuardRFFailureRoutine;
    	DWORD	GuardRFFailureRoutineFunctionPointer;
    	DWORD	DynamicValueRelocTableOffset;
    	WORD	DynamicValueRelocTableSection;
    	WORD	Reserved2;
    						//
    	DWORD	GuardRFVerifyStackPointerFunctionPointer;
    	DWORD	HotPatchTableOffset;
    						// Redstone 3 (1709)
    	DWORD	Reserved3;
    	DWORD	EnclaveConfigurationPointer;
    						// Redstone 4 (1803)
    	DWORD	VolatileMetadataPointer;
    						// Redstone 5 (1809)
    	DWORD	GuardEHContinuationTable;
    	DWORD	GuardEHContinuationCount;
    						// Vanadium 1 (1903)
    						// Vanadium 2 (1909)
    						// Vibranium 1 (2004)
    						// Vibranium 2 (20H2)
    						// Vibranium 3 (21H1)
    	DWORD	GuardXFGCheckFunctionPointer;
    	DWORD	GuardXFGDispatchFunctionPointer;
    	DWORD	GuardXFGTableDispatchFunctionPointer;
    						// Vibranium 4 (21H2)
    	DWORD	CastGuardOsDeterminedFailureMode;
    						// Vibranium 5 (22H2)
    	DWORD	GuardMemcpyFunctionPointer;
    } IMAGE_LOAD_CONFIGURATION_DIRECTORY32, *LPIMAGE_LOAD_CONFIGURATION_DIRECTORY32, *PIMAGE_LOAD_CONFIGURATION_DIRECTORY32;
    
    typedef	struct	_IMAGE_LOAD_CONFIGURATION_DIRECTORY64
    {
    	DWORD	Size;
    	DWORD	TimeDateStamp;
    	WORD	MajorVersion;
    	WORD	MinorVersion;
    	DWORD	GlobalFlagsClear;
    	DWORD	GlobalFlagsSet;
    	DWORD	CriticalSectionDefaultTimeout;
    	DWORD64	DeCommitFreeBlockThreshold;
    	DWORD64	DeCommitTotalFreeThreshold;
    	DWORD64	LockPrefixTable;
    	DWORD64	MaximumAllocationSize;
    	DWORD64	VirtualMemoryThreshold;
    	DWORD64	ProcessAffinityMask;
    	DWORD	ProcessHeapFlags;
    	WORD	CSDVersion;
    #if 0
    	WORD	Reserved1;
    #else
    	WORD	DependentLoadFlags;
    #endif
    	DWORD64	EditList;
    	DWORD64	SecurityCookie;
    	DWORD64	SEHandlerTable;
    	DWORD64	SEHandlerCount;
    						// Threshold 1 (1507)
    	DWORD64	GuardCFCheckFunctionPointer;
    	DWORD64	GuardCFDispatchFunctionPointer;
    	DWORD64	GuardCFFunctionTable;
    	DWORD64	GuardCFFunctionCount;
    	DWORD	GuardFlags;
    						// Threshold 2 (1511)
    	struct	// _IMAGE_LOAD_CONFIG_CODE_INTEGRITY
    	{
    		WORD	Flags;
    		WORD	Catalog;
    		DWORD	CatalogOffset;
    		DWORD	Reserved;
    	} CodeIntegrity;
    						// Redstone 1 (1607)
    	DWORD64	GuardAddressTakenIatEntryTable;
    	DWORD64	GuardAddressTakenIatEntryCount;
    	DWORD64	GuardLongJumpTargetTable;
    	DWORD64	GuardLongJumpTargetCount;
    						//
    	DWORD64	DynamicValueRelocTable;
    	DWORD64	CHPEMetadataPointer;
    						// Redstone 2 (1703)
    	DWORD64	GuardRFFailureRoutine;
    	DWORD64	GuardRFFailureRoutineFunctionPointer;
    	DWORD	DynamicValueRelocTableOffset;
    	WORD	DynamicValueRelocTableSection;
    	WORD	Reserved2;
    						//
    	DWORD64	GuardRFVerifyStackPointerFunctionPointer;
    	DWORD	HotPatchTableOffset;
    						// Redstone 3 (1709)
    	DWORD	Reserved3;
    	DWORD64	EnclaveConfigurationPointer;
    						// Redstone 4 (1803)
    	DWORD64	VolatileMetadataPointer;
    						// Redstone 5 (1809)
    	DWORD64	GuardEHContinuationTable;
    	DWORD64	GuardEHContinuationCount;
    						// Vanadium 1 (1903)
    						// Vanadium 2 (1909)
    						// Vibranium 1 (2004)
    						// Vibranium 2 (20H2)
    						// Vibranium 3 (21H1)
    	DWORD64	GuardXFGCheckFunctionPointer;
    	DWORD64	GuardXFGDispatchFunctionPointer;
    	DWORD64	GuardXFGTableDispatchFunctionPointer;
    						// Vibranium 4 (21H2)
    	DWORD64	CastGuardOsDeterminedFailureMode;
    						// Vibranium 5 (22H2)
    	DWORD64	GuardMemcpyFunctionPointer;
    } IMAGE_LOAD_CONFIGURATION_DIRECTORY64, *LPIMAGE_LOAD_CONFIGURATION_DIRECTORY64, *PIMAGE_LOAD_CONFIGURATION_DIRECTORY64;
    
    #ifndef RT_MENUEX
    #define RT_MENUEX	MAKEINTRESOURCE(13)
    #endif
    
    #ifndef RT_NAMETABLE
    #define RT_NAMETABLE	MAKEINTRESOURCE(15)
    #endif
    
    #ifndef RT_DIALOGEX
    #define RT_DIALOGEX	MAKEINTRESOURCE(18)
    #endif
    
    #ifndef RT_DLGINIT
    #define RT_DLGINIT	MAKEINTRESOURCE(240)
    #endif
    
    #ifndef RT_TOOLBAR
    #define RT_TOOLBAR	MAKEINTRESOURCE(241)
    #endif
    
    #ifndef RT_LOCALE
    #define RT_LOCALE	MAKEINTRESOURCE(255)
    #endif
    
    #ifndef WIN_CERT_TYPE_PKCS1_SIGN
    #define WIN_CERT_TYPE_PKCS1_SIGN	0x0009
    #endif
    
    typedef	struct	_COFFStringTable
    {
    	DWORD	Size;
    	CHAR	Strings[ANYSIZE_ARRAY];
    } COFFStringTable;
    
    typedef	struct	_CV_INFO_PDB20
    {
    	DWORD	Magic;		// '01BN' = "NB10"
    	DWORD	Offset;
    	DWORD	Signature;	// seconds since 1970-01-01
    	DWORD	Age;
    	CHAR	PdbFileName[ANYSIZE_ARRAY];
    } CV_INFO_PDB20, *LPCV_INFO_PDB20, *PCV_INFO_PDB20;
    
    typedef	struct	_CV_INFO_PDB70
    {
    	DWORD	Magic;		// 'SDSR' = "RSDS"
    	GUID	Signature;
    	DWORD	Age;
    	CHAR	PdbFileName[ANYSIZE_ARRAY];
    } CV_INFO_PDB70, *LPCV_INFO_PDB70, *PCV_INFO_PDB70;
    
    typedef	struct	_POGO
    {
    	DWORD	Magic;		// 'LTCG' = "GCTL"
    	struct
    	{
    		DWORD	Address;
    		DWORD	Size;
    		CHAR	Section[ANYSIZE_ARRAY];
    	} Entries[ANYSIZE_ARRAY];
    } POGO, *LPPOGO, *PPOGO;
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	LPBYTE	lpOutput;
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	dwOutput *= sizeof(*szOutput);
    	lpOutput = (LPBYTE) szOutput;
    
    	do
    	{
    		if (!WriteFile(hFile, lpOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpOutput += dwFile;
    		dwOutput -= dwFile;
    	} while (dwOutput != 0);
    
    	return TRUE;
    }
    
    #define PrintString(HANDLE, LITERAL)	PrintDirect(HANDLE, LITERAL, sizeof(LITERAL) / sizeof(*LITERAL) - 1)
    
    __inline
    BOOL	WINAPI	PrintDirect(HANDLE hFile, LPCWSTR lpString, DWORD dwString)
    {
    	DWORD	dwFile;
    
    	dwString *= sizeof(*lpString);
    
    	do
    	{
    		if (!WriteFile(hFile, lpString, dwString, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpString = (LPCWSTR) ((LPBYTE) lpString + dwFile);
    		dwString -= dwFile;
    	} while (dwString != 0);
    
    	return TRUE;
    }
    
    LPCWSTR	WINAPI	CertificateTypeName(WORD wType)
    {
    	switch (wType)
    	{
    	case WIN_CERT_TYPE_X509:
    		return L"X.509";
    
    	case WIN_CERT_TYPE_PKCS_SIGNED_DATA:
    		return L"PKCS";
    
    	case WIN_CERT_TYPE_RESERVED_1:
    		return L"(reserved)";
    
    	case WIN_CERT_TYPE_TS_STACK_SIGNED:
    		return L"Terminal Server";
    
    	case WIN_CERT_TYPE_PKCS1_SIGN:
    		return L"PKCS1_MODULE_SIGN";
    
    	default:
    		return L"<undefined>";
    	}
    }
    
    LPCWSTR	WINAPI	DebugTypeName(DWORD dwType)
    {
    	switch (dwType)
    	{
    	case IMAGE_DEBUG_TYPE_UNKNOWN:
    		return L"Unknown";
    
    	case IMAGE_DEBUG_TYPE_COFF:
    		return L"COFF";
    
    	case IMAGE_DEBUG_TYPE_CODEVIEW:
    		return L"Codeview";
    
    	case IMAGE_DEBUG_TYPE_FPO:
    		return L"Frame pointer omission";
    
    	case IMAGE_DEBUG_TYPE_MISC:
    		return L"Misc";
    
    	case IMAGE_DEBUG_TYPE_EXCEPTION:
    		return L"Exception";
    
    	case IMAGE_DEBUG_TYPE_FIXUP:
    		return L"Fixup";
    
    	case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
    		return L"OMAP to source";
    
    	case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
    		return L"OMAP from source";
    
    	case IMAGE_DEBUG_TYPE_BORLAND:
    		return L"Borland";
    
    	case IMAGE_DEBUG_TYPE_RESERVED10:
    		return L"Reserved";
    
    	case IMAGE_DEBUG_TYPE_CLSID:
    		return L"CLSID";
    
    	case IMAGE_DEBUG_TYPE_VC_FEATURE:
    		return L"VC feature";
    
    	case IMAGE_DEBUG_TYPE_POGO:
    		return L"Profile guided optimization";
    
    	case IMAGE_DEBUG_TYPE_ILTCG:
    		return L"Link time code generation";
    
    	case IMAGE_DEBUG_TYPE_MPX:
    		return L"MPX";
    
    	case IMAGE_DEBUG_TYPE_REPRO:
    		return L"Repro";
    
    	default:
    		return L"<undefined>";
    	}
    }
    
    LPCWSTR	WINAPI	MachineTypeName(WORD wMachine)
    {
    	switch (wMachine)
    	{
    	case IMAGE_FILE_MACHINE_UNKNOWN:	// 0x0000
    		return L"Unknown";
    
    	case IMAGE_FILE_MACHINE_TARGET_HOST:	// 0x0001
    		return L"Target host";
    
    	case IMAGE_FILE_MACHINE_I386:		// 0x014C
    		return L"Intel IA-32";
    
    	case IMAGE_FILE_MACHINE_I860:		// 0x014D
    		return L"Intel i860";
    
    	case 0x0160:
    		return L"MIPS R3000, big-endian";
    
    	case IMAGE_FILE_MACHINE_R3000:		// 0x0162
    		return L"MIPS R3000, little-endian";
    
    	case IMAGE_FILE_MACHINE_R4000:		// 0x0166
    		return L"MIPS R4000, little-endian";
    
    	case IMAGE_FILE_MACHINE_R10000:		// 0x0168
    		return L"MIPS R10000, little-endian";
    
    	case IMAGE_FILE_MACHINE_WCEMIPSV2:	// 0x0169
    		return L"MIPS, little-endian, Windows CE v2";
    
    	case IMAGE_FILE_MACHINE_ALPHA:		// 0x0184
    		return L"DEC Alpha AXP";
    
    	case IMAGE_FILE_MACHINE_SH3:		// 0x01A2
    		return L"Hitachi SuperH 3, little-endian";
    
    	case IMAGE_FILE_MACHINE_SH3DSP:		// 0x01A3
    		return L"Hitachi SuperH 3 with DSP";
    
    	case IMAGE_FILE_MACHINE_SH3E:		// 0x01A4
    		return L"Hitachi SuperH 3E, little-endian";
    
    	case IMAGE_FILE_MACHINE_SH4:		// 0x01A6
    		return L"Hitachi SuperH 4, little-endian";
    
    	case IMAGE_FILE_MACHINE_SH5:		// 0x01A8
    		return L"Hitachi SuperH 5";
    
    	case IMAGE_FILE_MACHINE_ARM:		// 0x01C0
    		return L"ARM, little-endian";
    
    	case IMAGE_FILE_MACHINE_THUMB:		// 0x01C2
    		return L"ARM Thumb, little-endian";
    
    	case IMAGE_FILE_MACHINE_ARMNT:		// 0x01C4
    		return L"ARM Thumb-2, little-endian";
    
    	case IMAGE_FILE_MACHINE_AM33:		// 0x01D3
    		return L"Matsushita AM33";
    
    	case IMAGE_FILE_MACHINE_POWERPC:	// 0x01F0
    		return L"IBM PowerPC, little-endian";
    
    	case IMAGE_FILE_MACHINE_POWERPCFP:	// 0x01F1
    		return L"IBM PowerPC with FPU";
    
    	case IMAGE_FILE_MACHINE_IA64:		// 0x0200
    		return L"Intel IA-64";
    
    	case IMAGE_FILE_MACHINE_MIPS16:		// 0x0266
    		return L"MIPS, 16-bit instructions";
    
    	case IMAGE_FILE_MACHINE_M68K:		// 0x0268
    		return L"Motorola MC68000";
    
    	case IMAGE_FILE_MACHINE_ALPHA64:	// 0x0284
    //	case IMAGE_FILE_MACHINE_AXP64:
    		return L"DEC Alpha AXP64";
    
    	case IMAGE_FILE_MACHINE_PARISC:		// 0x0290
    		return L"Hewlett-Packard PA-RISC";
    
    	case IMAGE_FILE_MACHINE_MIPSFPU:	// 0x0366
    		return L"MIPS with FPU";
    
    	case IMAGE_FILE_MACHINE_MIPSFPU16:	// 0x0466
    		return L"MIPS with FPU, 16-bit instructions";
    
    	case IMAGE_FILE_MACHINE_TRICORE:	// 0x0520
    		return L"Infineon TriCore";
    
    	case 0x0601:
    		return L"Motorola PowerPC 601";
    
    	case IMAGE_FILE_MACHINE_CEF:		// 0x0CEF
    		return L"CEF";
    
    	case IMAGE_FILE_MACHINE_EBC:		// 0x0EBC
    		return L"EFI Byte Code";
    
    	case IMAGE_FILE_MACHINE_CHPE_X86:	// 0x3A64
    		return L"Compiled Hybrid PE";
    
    	case IMAGE_FILE_MACHINE_RISCV32:	// 0x5032
    		return L"RISC-V, 32-bit address space";
    
    	case IMAGE_FILE_MACHINE_RISCV64:	// 0x5064
    		return L"RISC-V, 64-bit address space";
    
    	case IMAGE_FILE_MACHINE_RISCV128:	// 0x5128
    		return L"RISC-V, 128-bit address space";
    
    	case IMAGE_FILE_MACHINE_LOONGARCH32:	// 0x6232
    		return L"LoongArch, 32-bit";
    
    	case IMAGE_FILE_MACHINE_LOONGARCH64:	// 0x6264
    		return L"LoongArch, 64-bit";
    
    	case IMAGE_FILE_MACHINE_AMD64:		// 0x8664
    		return L"AMD64";
    
    	case IMAGE_FILE_MACHINE_M32R:		// 0x9041
    		return L"Mitsubishi M32R, little-endian";
    
    	case IMAGE_FILE_MACHINE_ARM64:		// 0xAA64
    		return L"ARMv8, 64-bit mode, little-endian";
    
    	case IMAGE_FILE_MACHINE_CEE:		// 0xC0EE
    		return L"CEE";
    
    	default:
    		return L"<undefined>";
    	}
    }
    
    LPCWSTR	WINAPI	SubsystemName(WORD wSubsystem)
    {
    	switch (wSubsystem)
    	{
    	case IMAGE_SUBSYSTEM_UNKNOWN:
    		return L"Unknown";
    
    	case IMAGE_SUBSYSTEM_NATIVE:
    		return L"Native";
    
    	case IMAGE_SUBSYSTEM_WINDOWS_GUI:
    		return L"Windows GUI";
    
    	case IMAGE_SUBSYSTEM_WINDOWS_CUI:
    		return L"Windows CUI";
    
    	case IMAGE_SUBSYSTEM_OS2_CUI:
    		return L"OS/2 CUI";
    
    	case IMAGE_SUBSYSTEM_POSIX_CUI:
    		return L"POSIX CUI";
    
    	case IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
    		return L"Native Windows 9x driver";
    
    	case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
    		return L"Windows CE";
    
    	case IMAGE_SUBSYSTEM_EFI_APPLICATION:
    		return L"EFI application";
    
    	case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
    		return L"EFI driver with boot services";
    
    	case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
    		return L"EFI driver with run-time services";
    
    	case IMAGE_SUBSYSTEM_EFI_ROM:
    		return L"EFI ROM image";
    
    	case IMAGE_SUBSYSTEM_XBOX:
    		return L"Xbox";
    
    	case IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
    		return L"Boot application";
    
    	case IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG:
    		return L"Xbox code catalog";
    
    	default:
    		return L"<undefined>";
    	}
    }
    
    LPCWSTR	WINAPI	ResourceTypeName(WORD wResType)
    {
    	switch (wResType)
    	{
    	case RT_CURSOR:		// MAKEINTRESOURCE(1)
    		return L"RT_CURSOR";
    
    	case RT_BITMAP:		// MAKEINTRESOURCE(2)
    		return L"RT_BITMAP";
    
    	case RT_ICON:		// MAKEINTRESOURCE(3)
    		return L"RT_ICON";
    
    	case RT_MENU:		// MAKEINTRESOURCE(4)
    		return L"RT_MENU";
    
    	case RT_DIALOG:		// MAKEINTRESOURCE(5)
    		return L"RT_DIALOG";
    
    	case RT_STRING:		// MAKEINTRESOURCE(6)
    #if 1
    		return L"RT_STRING";
    #else
    		return L"RT_STRINGTABLE";
    #endif
    	case RT_FONTDIR:	// MAKEINTRESOURCE(7)
    		return L"RT_FONTDIR";
    
    	case RT_FONT:		// MAKEINTRESOURCE(8)
    		return L"RT_FONT";
    
    	case RT_ACCELERATOR:	// MAKEINTRESOURCE(9)
    		return L"RT_ACCELERATOR";
    
    	case RT_RCDATA:		// MAKEINTRESOURCE(10)
    		return L"RT_RCDATA";
    
    	case RT_MESSAGETABLE:	// MAKEINTRESOURCE(11)
    		return L"RT_MESSAGETABLE";
    
    	case RT_GROUP_CURSOR:	// MAKEINTRESOURCE(12)
    		return L"RT_GROUP_CURSOR";
    
    	case RT_MENUEX:		// MAKEINTRESOURCE(13)
    		return L"RT_MENUEX";
    
    	case RT_GROUP_ICON:	// MAKEINTRESOURCE(14)
    		return L"RT_GROUP_ICON";
    
    	case RT_NAMETABLE:	// MAKEINTRESOURCE(15)
    		return L"RT_NAMETABLE";
    
    	case RT_VERSION:	// MAKEINTRESOURCE(16)
    		return L"RT_VERSION";
    
    	case RT_DLGINCLUDE:	// MAKEINTRESOURCE(17)
    		return L"RT_DLGINCLUDE";
    
    	case RT_DIALOGEX:	// MAKEINTRESOURCE(18)
    		return L"RT_DIALOGEX";
    
    	case RT_PLUGPLAY:	// MAKEINTRESOURCE(19)
    		return L"RT_PLUGPLAY";
    
    	case RT_VXD:		// MAKEINTRESOURCE(20)
    		return L"RT_VXD";
    
    	case RT_ANICURSOR:	// MAKEINTRESOURCE(21)
    		return L"RT_ANICURSOR";
    
    	case RT_ANIICON:	// MAKEINTRESOURCE(22)
    		return L"RT_ANIICON";
    
    	case RT_HTML:		// MAKEINTRESOURCE(23)
    		return L"RT_HTML";
    
    	case RT_MANIFEST:	// MAKEINTRESOURCE(24)
    		return L"RT_MANIFEST";
    
    	case RT_DLGINIT:	// MAKEINTRESOURCE(240)
    		return L"RT_DLGINIT";
    
    	case RT_TOOLBAR:	// MAKEINTRESOURCE(241)
    		return L"RT_TOOLBAR";
    
    	case RT_LOCALE:		// MAKEINTRESOURCE(255)
    		return L"RT_LOCALE";
    
    	default:
    		return NULL;
    	}
    }
    
    BOOL	WINAPI	Resource(HANDLE                   hOutput,
    		         IMAGE_RESOURCE_DIRECTORY *lpRoot,
    		         IMAGE_RESOURCE_DIRECTORY *lpLevel,
    		         DWORD                    dwLevel)	// 0 = Type, 1 = Id, 2 = Language
    {
    	BOOL	bOutput = TRUE;
    	DWORD	dwEntry;
    
    	IMAGE_RESOURCE_DIRECTORY_ENTRY	*lpEntry;
    	IMAGE_RESOURCE_DIR_STRING_U	*lpUnicode;
    	IMAGE_RESOURCE_DATA_ENTRY	*lpData;
    
    	for (lpEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *) (lpLevel + 1),
    	     dwEntry = lpLevel->NumberOfNamedEntries + lpLevel->NumberOfIdEntries;
    	     dwEntry > 0;
    	     dwEntry--,
    	     lpEntry++)
    	{
    		if ((lpEntry->Name & IMAGE_RESOURCE_NAME_IS_STRING) == IMAGE_RESOURCE_NAME_IS_STRING)
    		{
    			lpUnicode = (IMAGE_RESOURCE_DIR_STRING_U *) ((BYTE *) lpRoot + (lpEntry->Name ^ IMAGE_RESOURCE_NAME_IS_STRING));
    
    			bOutput &= PrintDirect(hOutput, L"\t\t\t\tName   = " + 2 - dwLevel, dwLevel + 11);
    			bOutput &= PrintDirect(hOutput, lpUnicode->NameString, lpUnicode->Length);
    			bOutput &= PrintString(hOutput, L"\r\n");
    			bOutput &= PrintFormat(hOutput, L"\t\t\t\tOffset = 0x%08lX\r\n" + 2 - dwLevel, lpEntry->OffsetToData);
    		}
    		else if (dwLevel > 1)
    			bOutput &= PrintFormat(hOutput,
    			                       L"\t\t\t\tLanguage = %hu\r\n"
    			                       L"\t\t\t\tOffset   = 0x%08lX\r\n",
    			                       lpEntry->Id,
    			                       lpEntry->OffsetToData);
    		else if (dwLevel > 0)
    			bOutput &= PrintFormat(hOutput,
    			                       L"\t\t\tId     = %hu\r\n"
    			                       L"\t\t\tOffset = 0x%08lX\r\n",
    			                       lpEntry->Id,
    			                       lpEntry->OffsetToData);
    		else
    			bOutput &= PrintFormat(hOutput,
    			                       L"\t\tType   = %hu (%ls)\r\n"
    			                       L"\t\tOffset = 0x%08lX\r\n",
    			                       lpEntry->Id, ResourceTypeName(lpEntry->Id),
    			                       lpEntry->OffsetToData);
    
    		if ((lpEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY) == IMAGE_RESOURCE_DATA_IS_DIRECTORY)
    			bOutput &= Resource(hOutput,
    			                    lpRoot,
    			                    (IMAGE_RESOURCE_DIRECTORY *) ((BYTE *) lpRoot + (lpEntry->OffsetToData ^ IMAGE_RESOURCE_DATA_IS_DIRECTORY)),
    			                    dwLevel + 1);
    		else
    		{
    			lpData = (IMAGE_RESOURCE_DATA_ENTRY *) ((BYTE *) lpRoot + lpEntry->OffsetToData);
    
    			bOutput &= PrintFormat(hOutput,
    			                       L"\t\t\t\t\tAddress   = 0x%08lX\r\n"
    			                       L"\t\t\t\t\tSize      = %lu\r\n"
    			                       L"\t\t\t\t\tCode Page = %lu\r\n"
    			                       L"\t\t\t\t\tReserved  = 0x%08lX\r\n",
    			                       lpData->OffsetToData,
    			                       lpData->Size,
    			                       lpData->CodePage,
    			                       lpData->Reserved);
    		}
    	}
    
    	return bOutput;
    }
    
    LPVOID	WINAPI	RVA2Image(BYTE                 *lpImage,
    		          IMAGE_SECTION_HEADER *lpSection,
    		          DWORD                dwSection,
    		          DWORD                dwRVA,
    		          DWORD                dwDirectory,
    		          HANDLE               hConsole)
    {
    	while (dwSection > 0)
    	{
    		if ((dwRVA >= lpSection->VirtualAddress)
    		 && (dwRVA < lpSection->VirtualAddress + lpSection->SizeOfRawData))
    			return lpImage + dwRVA - lpSection->VirtualAddress + lpSection->PointerToRawData;
    
    		lpSection++;
    		dwSection--;
    	}
    
    	PrintConsole(hConsole,
    	             L"RVA 0x%08lX in IMAGE_DATA_DIRECTORY[%lu] outside of COFF sections!\n",
    	             dwRVA, dwDirectory);
    
    	return NULL;
    }
    
    const	LPCWSTR	szDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = {L"Export",
    		                                                 L"Import",
    		                                                 L"Resource",
    		                                                 L"Exception Handler",
    		                                                 L"Security",
    		                                                 L"Base Relocation",
    		                                                 L"Debug",
    		                                                 L"Architecture",
    		                                                 L"Global Pointer",
    		                                                 L"Thread Local Storage",
    		                                                 L"Load Configuration",
    		                                                 L"Bound Import",
    		                                                 L"Import Address Table",
    		                                                 L"Delay Load Import",
    		                                                 L"COM+ Descriptor",
    		                                                 L"Reserved"};
    
    const	LPCWSTR	szDayOfWeek[7] = {L"Sunday",
    		                  L"Monday",
    		                  L"Tuesday",
    		                  L"Wednesday",
    		                  L"Thursday",
    		                  L"Friday",
    		                  L"Saturday"};
    
    const	LPCWSTR	szRelocation[16] = {L"ABSOLUTE",
    		                    L"HIGH",
    		                    L"LOW",
    		                    L"HIGHLOW",
    		                    L"HIGHADJ",
    		                    L"ARM_MOV32",	// also L"MIPS_JMPADDR" or L"RISCV_HIGH20"
    		                    L"SECTION",
    		                    L"THUMB_MOV32",	// also L"REL32" or L"RISCV_LOW12I"
    		                    L"RISCV_LOW12S",	// also L"LOONGARCH32_MARK_LA" or L"LOONGARCH64_MARK_LA"
    		                    L"IA64_IMM64",	// also L"MIPS_JMPADDR16"
    		                    L"DIR64",
    		                    L"HIGH3ADJ",
    		                    NULL,
    		                    NULL,
    		                    NULL,
    		                    NULL};
    
    const	LPCWSTR	szGlobalFlags[32] = {L"Stop on exception",
    		                     L"Show loader snaps",
    		                     NULL,
    		                     NULL,
    		                     L"Enable heap tail checking",
    		                     L"Enable heap free checking",
    		                     L"Enable heap parameter checking",
    		                     L"Enable heap validation on call",
    		                     L"Enable application verifier",
    		                     L"Enable silent process exit monitoring",
    		                     NULL,
    		                     L"Enable heap tagging",
    		                     L"Create user mode stack trace database",
    		                     NULL,
    		                     NULL,
    		                     L"Enable heap tagging by DLL",
    		                     L"Disable stack extension",
    		                     NULL,
    		                     NULL,
    		                     NULL,
    		                     L"Enable system critical breaks",
    		                     L"Disable heap coalesce on free",
    		                     L"Enable close exception",
    		                     NULL,
    		                     NULL,
    		                     L"Enable page heap",
    		                     NULL,
    		                     L"Buffer DbgPrint output",
    		                     L"Early critical section event creation",
    		                     L"Stop on unhandled user-mode exception",
    		                     L"Enable bad handles detection",
    		                     L"Disable protected DLL verification"};
    #ifdef RDN
    const	DWORD	dwStrType = CERT_NAME_STR_REVERSE_FLAG | CERT_X500_NAME_STR;
    #endif
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	IMAGE_DOS_HEADER	*lpMZ;
    	IMAGE_NT_HEADERS	*lpPE;
    	IMAGE_NT_HEADERS32	*lpPE32;
    	IMAGE_NT_HEADERS64	*lpPE64;
    	IMAGE_SECTION_HEADER	*lpSection;
    	IMAGE_SECTION_HEADER	*lpTLS = NULL;
    	IMAGE_DATA_DIRECTORY	*lpDirectory;
    	IMAGE_DEBUG_DIRECTORY	*lpDebug;
    	IMAGE_EXPORT_DIRECTORY	*lpExport;
    	IMAGE_IMPORT_DESCRIPTOR	*lpImport;
    	IMAGE_THUNK_DATA32	*lpThunk32;
    	IMAGE_THUNK_DATA64	*lpThunk64;
    	IMAGE_IMPORT_BY_NAME	*lpAddress;
    	IMAGE_DEBUG_MISC	*lpMisc;
    	IMAGE_BASE_RELOCATION	*lpRelocation;
    	IMAGE_TLS_DIRECTORY32	*lpTLS32;
    	IMAGE_TLS_DIRECTORY64	*lpTLS64;
    	IMAGE_COR20_HEADER	*lpCOMPlus;
    
    	IMAGE_RESOURCE_DIRECTORY	*lpResource;
    	IMAGE_BOUND_IMPORT_DESCRIPTOR	*lpDescriptor;
    	IMAGE_DELAYLOAD_DESCRIPTOR	*lpDelay;
    	IMAGE_RUNTIME_FUNCTION_ENTRY	*lpRuntime;
    
    	IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY	*lpAlpha;
    	IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY	*lpAlpha64;
    	IMAGE_ARMNT_RUNTIME_FUNCTION_ENTRY	*lpARM;
    	IMAGE_LOAD_CONFIGURATION_DIRECTORY32	*lpLoadCfg32;
    	IMAGE_LOAD_CONFIGURATION_DIRECTORY64	*lpLoadCfg64;
    
    	COFFStringTable	*lpCOFF;
    	CV_INFO_PDB70	*lpCodeView;
    	WIN_CERTIFICATE	*lpCertificate;
    	CERT_CONTEXT	*lpSigner;
    	CERT_BLOB	blob;
    	HCERTSTORE	hStore;
    	HCRYPTMSG	hMsg;
    	SYSTEMTIME	st;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	BOOL	bOutput;
    	HANDLE	hOutput;
    	HANDLE	hInput;
    	DWORD	dwInput;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwArray = 0;
    	DWORD	dwIndex;
    	DWORD	dwImage;
    	HANDLE	hImage;
    	BYTE	*lpImage;
    	BYTE	*lpBound;
    	WORD	*lpWord;
    	DWORD	*lpDanS;
    	DWORD	*lpRich;
    	DWORD	dwRich;
    	DWORD	dwSigner;
    	LPWSTR	szSigner;
    	LPCSTR	lpString;
    	LPCSTR	lpModule;
    	BYTE	*lpException;
    	DWORD	*lpFunctions;
    	WORD	*lpOrdinals;
    	DWORD	*lpNames;
    	DWORD	dwNames;
    	DWORD	dwFlags;
    	DWORD	dwDebug;
    	DWORD	dwDescriptor;
    	DWORD	dwCertificate;
    	DWORD	dwRelocation;
    	DWORD	dwException;
    	DWORD	dwDirectory;
    	DWORD	dwSection;
    	DWORD	dwCheckSum;
    	DWORD	dwAccumulator;
    	DWORD	dwCode;
    	DWORD	dwData;
    	DWORD	dwNone;
    	DWORD	dwSize;
    	DWORD	dwLast;
    	DWORD	dwFile;
    	DWORD	dwOffset;
    	DWORD	dwMemory;
    	DWORD	dwRVA;
    	DWORD	dwBase;
    	DWORD64	qwBase;
    	DWORD64	qw;
    	DWORD64	*lpCookie64;
    	DWORD	*lpCookie32;
    	DWORD	*lpHandler;
    	DWORD	dwHandler;
    	DWORD	dwPogo;
    	POGO	*lpPogo;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments != 2)
    				PrintConsole(hConsole,
    				             L"No argument: a single file or path name of an image file must be given!\n");
    			else
    			{
    				hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    				if (hOutput == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"GetStdHandle() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!FlushFileBuffers(hOutput))
    						PrintConsole(hConsole,
    						             L"FlushFileBuffers() returned error %lu: standard output is not redirected to a file!\n",
    						             dwError = GetLastError());
    					else
    					{
    						hInput = CreateFile(lpArguments[1],
    						                    FILE_READ_DATA,
    						                    FILE_SHARE_READ,
    						                    (SECURITY_ATTRIBUTES *) NULL,
    						                    OPEN_EXISTING,
    						                    FILE_FLAG_SEQUENTIAL_SCAN,
    						                    (HANDLE) NULL);
    
    						if (hInput == INVALID_HANDLE_VALUE)
    							PrintConsole(hConsole,
    							             L"CreateFile() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							dwInput = GetFileSize(hInput, (DWORD *) NULL);
    
    							if (dwInput == INVALID_FILE_SIZE)
    								PrintConsole(hConsole,
    								             L"GetFileSize() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								hImage = CreateFileMapping(hInput,
    								                           (LPSECURITY_ATTRIBUTES) NULL,
    								                           PAGE_WRITECOPY,
    								                           0, 0,
    								                           (LPCWSTR) NULL);
    
    								if (hImage == NULL)
    									PrintConsole(hConsole,
    									             L"CreateFileMapping() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    								{
    									lpImage = MapViewOfFile(hImage,
    									                        FILE_MAP_COPY,
    									                        0, 0,
    									                        (SIZE_T) 0);
    
    									if (lpImage == NULL)
    										PrintConsole(hConsole,
    										             L"MapViewOfFile() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    										dwError = ERROR_INVALID_EXE_SIGNATURE;
    
    										lpMZ = (IMAGE_DOS_HEADER *) lpImage;
    
    										if (lpMZ->e_magic != IMAGE_DOS_SIGNATURE)
    											PrintConsole(hConsole,
    											             L"No signature \'%ls\' at offset 0x%08lX in file \'%ls\'!\n",
    											             L"MZ", 0, lpArguments[1]);
    										else
    										{
    											dwImage = dwInput;
    
    											lpPE = (IMAGE_NT_HEADERS *) ((BYTE *) lpMZ + lpMZ->e_lfanew);
    
    											if (((DWORD) lpMZ->e_lfanew > dwImage)
    											 || (lpPE->Signature != IMAGE_NT_SIGNATURE))
    												PrintConsole(hConsole,
    												             L"No signature \'%ls\' at offset 0x%08lX in file \'%ls\'!\n",
    												             L"PE\\0\\0", lpMZ->e_lfanew, lpArguments[1]);
    											else
    											{
    												bOutput = PrintFormat(hOutput,
    												                      L"\xFEFF"	// UTF-16LE BOM
    												                      L"Image File = %ls\r\n"
    												                      L"Image Size = %lu\r\n",
    												                      lpArguments[1],
    												                      dwImage);
    
    												lpRich = (DWORD *) lpPE;
    
    												while ((--lpRich > (DWORD *) (lpImage + sizeof(IMAGE_DOS_HEADER)))
    												    && (*lpRich != 'hciR'))
    													dwRich = *lpRich;
    
    												if (*lpRich == 'hciR')
    												{
    													lpDanS = lpRich;
    
    													while ((--lpDanS > (DWORD *) (lpImage + sizeof(IMAGE_DOS_HEADER)))
    													    && ((*lpDanS ^ dwRich) != 'SnaD'))
    														continue;
    
    													if ((*lpDanS ^ dwRich) != 'SnaD')
    														PrintConsole(hConsole,
    														             L"End marker \"Rich\" present at offset 0x%08lX, but start marker \"DanS\" missing in file \'%ls\'!\n",
    														             (BYTE *) lpRich - lpImage, lpArguments[1]);
    													else
    													{
    														bOutput &= PrintString(hOutput,
    														                       L"\r\n"
    														                       L"Tool Version Information:\r\n");
    
    														for (lpDanS += 4; lpDanS < lpRich; lpDanS += 2)
    															bOutput &= PrintFormat(hOutput,
    															                       L"\t@comp.id = %5hu %5hu, Count = %lu\r\n",
    															                       HIWORD(lpDanS[0] ^ dwRich), LOWORD(lpDanS[0] ^ dwRich), lpDanS[1] ^ dwRich);
    													}
    												}
    
    												dwError = ERROR_SUCCESS;
    
    												qw = __emulu(lpPE->FileHeader.TimeDateStamp, 10000000)
    												   + 116444736000000000;	// seconds since 1970-01-01 to
    																//  100 nano-seconds since 1601-01-01
    
    												if (!FileTimeToSystemTime((FILETIME *) &qw, &st))
    													PrintConsole(hConsole,
    													             L"FileTimeToSystemTime() returned error %lu\n",
    													             dwError = GetLastError());
    
    												bOutput = PrintFormat(hOutput,
    												                      L"\r\n"
    												                      L"File Header:\r\n"
    												                      L"\tMachine                 = 0x%04hX (%ls)\r\n"
    												                      L"\tTime/Date Stamp         = 0x%08lX (%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu UTC)\r\n"
    												                      L"\tPointer to Symbol Table = 0x%08lX\r\n"
    												                      L"\tNumber of Symbols       = %lu\r\n"
    												                      L"\tSize of Optional Header = 0x%04hX\r\n"
    												                      L"\tCharacteristics         = 0x%04hX\r\n",
    												                      lpPE->FileHeader.Machine, MachineTypeName(lpPE->FileHeader.Machine),
    												                      lpPE->FileHeader.TimeDateStamp,
    												                      szDayOfWeek[st.wDayOfWeek], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
    												                      lpPE->FileHeader.PointerToSymbolTable,
    												                      lpPE->FileHeader.NumberOfSymbols,
    												                      lpPE->FileHeader.SizeOfOptionalHeader,
    												                      lpPE->FileHeader.Characteristics);
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) == IMAGE_FILE_RELOCS_STRIPPED)
    													bOutput &= PrintString(hOutput, L"\t\tRelocation information stripped\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == IMAGE_FILE_EXECUTABLE_IMAGE)
    													bOutput &= PrintString(hOutput, L"\t\tExecutable image\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED) == IMAGE_FILE_LINE_NUMS_STRIPPED)
    													bOutput &= PrintString(hOutput, L"\t\tLine numbers stripped\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED) == IMAGE_FILE_LOCAL_SYMS_STRIPPED)
    													bOutput &= PrintString(hOutput, L"\t\tLocal symbols stripped\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_AGGRESIVE_WS_TRIM) == IMAGE_FILE_AGGRESIVE_WS_TRIM)
    													bOutput &= PrintString(hOutput, L"\t\tAggressively trim working set\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) == IMAGE_FILE_LARGE_ADDRESS_AWARE)
    													bOutput &= PrintString(hOutput, L"\t\tHandles addresses above 2 GB\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_16BIT_MACHINE) == IMAGE_FILE_16BIT_MACHINE)
    													bOutput &= PrintString(hOutput, L"\t\t16 bit word machine\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_32BIT_MACHINE) == IMAGE_FILE_32BIT_MACHINE)
    													bOutput &= PrintString(hOutput, L"\t\t32 bit word machine\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == IMAGE_FILE_DEBUG_STRIPPED)
    													bOutput &= PrintString(hOutput, L"\t\tDebugging information stripped\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) == IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
    													bOutput &= PrintString(hOutput, L"\t\tRun image on CD from swap file\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_NET_RUN_FROM_SWAP) == IMAGE_FILE_NET_RUN_FROM_SWAP)
    													bOutput &= PrintString(hOutput, L"\t\tRun image on network from swap file\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_SYSTEM) == IMAGE_FILE_SYSTEM)
    													bOutput &= PrintString(hOutput, L"\t\tSystem file\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL)
    													bOutput &= PrintString(hOutput, L"\t\tDLL\r\n");
    
    												if ((lpPE->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) == IMAGE_FILE_UP_SYSTEM_ONLY)
    													bOutput &= PrintString(hOutput, L"\t\tUniprocessor machine only\r\n");
    
    												if (((lpPE->FileHeader.Characteristics & IMAGE_FILE_BYTES_REVERSED_LO) == IMAGE_FILE_BYTES_REVERSED_LO)
    												 || ((lpPE->FileHeader.Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) == IMAGE_FILE_BYTES_REVERSED_HI))
    													bOutput &= PrintString(hOutput, L"\t\tBytes of machine word are reversed\r\n");
    
    												if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    												{
    													if (lpPE->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER64))
    														PrintConsole(hConsole,
    														             L"Size of %ls differs from size of %ls structure!\n",
    														             L"optional header", L"IMAGE_OPTIONAL_HEADER64");
    
    													lpPE64 = (IMAGE_NT_HEADERS64 *) lpPE;
    												//	lpSection = (IMAGE_SECTION_HEADER *) (lpPE64->OptionalHeader.DataDirectory + lpPE64->OptionalHeader.NumberOfRvaAndSizes);
    													lpDirectory = lpPE64->OptionalHeader.DataDirectory;
    												//	dwDirectory = lpPE64->OptionalHeader.NumberOfRvaAndSizes;
    													qwBase = lpPE64->OptionalHeader.ImageBase;
    												//	dwBase = lpPE64->OptionalHeader.BaseOfCode;
    													dwCode = lpPE64->OptionalHeader.SizeOfCode;
    													dwData = lpPE64->OptionalHeader.SizeOfInitializedData;
    													dwNone = lpPE64->OptionalHeader.SizeOfUninitializedData;
    													dwSize = lpPE64->OptionalHeader.SizeOfImage;
    													dwOffset = lpPE64->OptionalHeader.SizeOfHeaders;
    													dwMemory = lpPE64->OptionalHeader.SectionAlignment;
    													dwFile = lpPE64->OptionalHeader.FileAlignment;
    												}
    												else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    												{
    													if (lpPE->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER32))
    														PrintConsole(hConsole,
    														             L"Size of %ls differs from size of %ls structure!\n",
    														             L"optional header", L"IMAGE_OPTIONAL_HEADER32");
    
    													lpPE32 = (IMAGE_NT_HEADERS32 *) lpPE;
    												//	lpSection = (IMAGE_SECTION_HEADER *) (lpPE32->OptionalHeader.DataDirectory + lpPE32->OptionalHeader.NumberOfRvaAndSizes);
    													lpDirectory = lpPE32->OptionalHeader.DataDirectory;
    												//	dwDirectory = lpPE32->OptionalHeader.NumberOfRvaAndSizes;
    													dwBase = lpPE32->OptionalHeader.ImageBase;
    												//	dwBase = lpPE32->OptionalHeader.BaseOfCode;
    													dwCode = lpPE32->OptionalHeader.SizeOfCode;
    													dwData = lpPE32->OptionalHeader.SizeOfInitializedData;
    													dwNone = lpPE32->OptionalHeader.SizeOfUninitializedData;
    													dwSize = lpPE32->OptionalHeader.SizeOfImage;
    													dwOffset = lpPE32->OptionalHeader.SizeOfHeaders;
    													dwMemory = lpPE32->OptionalHeader.SectionAlignment;
    													dwFile = lpPE32->OptionalHeader.FileAlignment;
    												}
    												else
    													PrintConsole(hConsole,
    													             L"Image format is neither PE32 (32-bit) nor PE32+ (64-bit)!\n");
    
    												dwFile--;
    
    												if ((dwFile & (dwFile + 1)) != 0)
    													PrintConsole(hConsole,
    													             L"File alignment is not a power of 2!\n");
    												else if ((dwMemory & dwFile) != 0)
    													PrintConsole(hConsole,
    													             L"Section alignment is not a multiple of file alignment!\n");
    #if 0
    												dwMemory--;
    
    												if ((dwMemory & (dwMemory + 1)) != 0)
    													PrintConsole(hConsole,
    													             L"Section alignment is not a power of 2!\n");
    #else
    												if ((dwMemory & (dwMemory - 1)) != 0)
    													PrintConsole(hConsole,
    													             L"Section alignment is not a power of 2!\n");
    
    												dwMemory--;
    #endif
    												dwRVA = (dwOffset + dwMemory) & ~dwMemory;
    												dwLast = 0;
    
    												bOutput &= PrintFormat(hOutput,
    												                       L"\tNumber of COFF Sections = %hu\r\n",
    												                       lpPE->FileHeader.NumberOfSections);
    
    												for (lpSection = (IMAGE_SECTION_HEADER *) ((BYTE *) &(lpPE->OptionalHeader) + lpPE->FileHeader.SizeOfOptionalHeader),
    												     dwSection = 0;
    												     dwSection < lpPE->FileHeader.NumberOfSections;
    												     dwSection++)
    												{
    													bOutput &= PrintFormat(hOutput,
    													                       L"\t%.8hs:\r\n"
    													                       L"\t\tVirtual Address & Size = 0x%08lX, 0x%08lX\r\n"
    													                       L"\t\tFile Offset & Raw Size = 0x%08lX, 0x%08lX\r\n"
    													                       L"\t\tCharacteristics        = 0x%08lX\r\n",
    													                       lpSection[dwSection].Name,
    													                       lpSection[dwSection].VirtualAddress,
    													                       lpSection[dwSection].Misc.VirtualSize,
    													                       lpSection[dwSection].PointerToRawData,
    													                       lpSection[dwSection].SizeOfRawData,
    													                       lpSection[dwSection].Characteristics);
    #ifdef IMAGE_SCN_TYPE_REG
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_TYPE_REG) == IMAGE_SCN_TYPE_REG)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    #endif
    #ifdef IMAGE_SCN_TYPE_DSECT
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_TYPE_DSECT) == IMAGE_SCN_TYPE_DSECT)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    #endif
    #ifdef IMAGE_SCN_TYPE_NOLOAD
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_TYPE_NOLOAD) == IMAGE_SCN_TYPE_NOLOAD)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    #endif
    #ifdef IMAGE_SCN_TYPE_GROUP
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_TYPE_GROUP) == IMAGE_SCN_TYPE_GROUP)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    #endif
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_TYPE_NO_PAD) == IMAGE_SCN_TYPE_NO_PAD)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved (COFF)\r\n");
    #ifdef IMAGE_SCN_TYPE_COPY
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_TYPE_COPY) == IMAGE_SCN_TYPE_COPY)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    #endif
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_CNT_CODE) == IMAGE_SCN_CNT_CODE)
    													{
    														bOutput &= PrintString(hOutput, L"\t\t\tExecutable code\r\n");
    
    														dwCode -= lpSection[dwSection].SizeOfRawData;
    													}
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) == IMAGE_SCN_CNT_INITIALIZED_DATA)
    													{
    														bOutput &= PrintString(hOutput, L"\t\t\tInitialized data\r\n");
    
    														dwData -= lpSection[dwSection].SizeOfRawData;
    													}
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) == IMAGE_SCN_CNT_UNINITIALIZED_DATA)
    													{
    														bOutput &= PrintString(hOutput, L"\t\t\tUninitialized data\r\n");
    
    														dwNone -= lpSection[dwSection].Misc.VirtualSize;
    													}
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_LNK_OTHER) == IMAGE_SCN_LNK_OTHER)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved (COFF)\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_LNK_INFO) == IMAGE_SCN_LNK_INFO)
    														bOutput &= PrintString(hOutput, L"\t\t\tLinker information: .cormeta, .drectve, .idlsym or .sxdata (COFF)\r\n");
    #ifdef IMAGE_SCN_TYPE_OVER
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_TYPE_OVER) == IMAGE_SCN_TYPE_OVER)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    #endif
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_LNK_REMOVE) == IMAGE_SCN_LNK_REMOVE)
    														bOutput &= PrintString(hOutput, L"\t\t\tRemovable content (COFF)\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_LNK_COMDAT) == IMAGE_SCN_LNK_COMDAT)
    														bOutput &= PrintString(hOutput, L"\t\t\tCOMDAT (COFF)\r\n");
    #ifdef IMAGE_SCN_MEM_PROTECTED
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_PROTECTED) == IMAGE_SCN_MEM_PROTECTED)
    														bOutput &= PrintString(hOutput, L"\t\t\tObsolete\r\n");
    #endif
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_NO_DEFER_SPEC_EXC) == IMAGE_SCN_NO_DEFER_SPEC_EXC)
    														bOutput &= PrintString(hOutput, L"\t\t\tReset speculative exceptions handling bits in the TLB entries for this section\r\n");
    #ifdef IMAGE_SCN_GPREL
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_GPREL) == IMAGE_SCN_GPREL)
    #else
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_FARDATA) == IMAGE_SCN_MEM_FARDATA)
    #endif
    														bOutput &= PrintString(hOutput, L"\t\t\tGP relative data\r\n");
    #ifdef IMAGE_SCN_MEM_SYSHEAP
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_SYSHEAP) == IMAGE_SCN_MEM_SYSHEAP)
    														bOutput &= PrintString(hOutput, L"\t\t\tObsolete\r\n");
    #endif
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_PURGEABLE) == IMAGE_SCN_MEM_PURGEABLE)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_16BIT) == IMAGE_SCN_MEM_16BIT)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_LOCKED) == IMAGE_SCN_MEM_LOCKED)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_PRELOAD) == IMAGE_SCN_MEM_PRELOAD)
    														bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_ALIGN_MASK) != 0)
    														if ((lpSection[dwSection].Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_MASK)
    															bOutput &= PrintString(hOutput, L"\t\t\tReserved\r\n");
    														else
    															bOutput &= PrintFormat(hOutput,
    															                       L"\t\t\t%lu-byte alignment (COFF)\r\n",
    															                       1 << (((lpSection[dwSection].Characteristics & IMAGE_SCN_ALIGN_MASK) >> 20) - 1));
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL) == IMAGE_SCN_LNK_NRELOC_OVFL)
    														bOutput &= PrintString(hOutput, L"\t\t\tExtended relocations\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == IMAGE_SCN_MEM_DISCARDABLE)
    														bOutput &= PrintString(hOutput, L"\t\t\tDiscardable\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_NOT_CACHED) == IMAGE_SCN_MEM_NOT_CACHED)
    														bOutput &= PrintString(hOutput, L"\t\t\tVolatile, not cacheable\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_NOT_PAGED) == IMAGE_SCN_MEM_NOT_PAGED)
    														bOutput &= PrintString(hOutput, L"\t\t\tResident, not pageable\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_SHARED) == IMAGE_SCN_MEM_SHARED)
    														bOutput &= PrintString(hOutput, L"\t\t\tShared\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_EXECUTE) == IMAGE_SCN_MEM_EXECUTE)
    														bOutput &= PrintString(hOutput, L"\t\t\tExecutable\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_READ) == IMAGE_SCN_MEM_READ)
    														bOutput &= PrintString(hOutput, L"\t\t\tReadable\r\n");
    
    													if ((lpSection[dwSection].Characteristics & IMAGE_SCN_MEM_WRITE) == IMAGE_SCN_MEM_WRITE)
    														bOutput &= PrintString(hOutput, L"\t\t\tWritable\r\n");
    
    													if ((lpSection[dwSection].VirtualAddress & dwMemory) != 0)
    														PrintConsole(hConsole,
    														             L"Address of \'%.8hs\' section is not aligned!\n",
    														             lpSection[dwSection].Name);
    
    													if (lpSection[dwSection].VirtualAddress != dwRVA)
    														PrintConsole(hConsole,
    														             L"Address of \'%.8hs\' section is not contiguous!\n",
    														             lpSection[dwSection].Name);
    
    													if ((lpSection[dwSection].PointerToRawData & dwFile) != 0)
    														PrintConsole(hConsole,
    														             L"Offset of \'%.8hs\' section is not aligned!\n",
    														             lpSection[dwSection].Name);
    
    													if ((lpSection[dwSection].PointerToRawData != 0)
    													 && (lpSection[dwSection].PointerToRawData != dwOffset))
    														PrintConsole(hConsole,
    														             L"Offset of \'%.8hs\' section is not contiguous!\n",
    														             lpSection[dwSection].Name);
    
    													if ((lpSection[dwSection].PointerToRawData != 0)
    													 && (lpSection[dwSection].SizeOfRawData != 0))
    														dwOffset = lpSection[dwSection].PointerToRawData
    														         + lpSection[dwSection].SizeOfRawData;
    
    													if ((lpSection[dwSection].SizeOfRawData & dwFile) != 0)
    														PrintConsole(hConsole,
    														             L"Data of \'%.8hs\' section is not aligned!\n",
    														             lpSection[dwSection].Name);
    
    													dwRVA = lpSection[dwSection].VirtualAddress + lpSection[dwSection].Misc.VirtualSize;
    
    													if (dwRVA > dwSize)
    														PrintConsole(hConsole,
    														             L"Section \'%.8hs\' extends past image!\n",
    														             lpSection[dwSection].Name);
    
    													if (dwLast < dwRVA)
    														dwLast = dwRVA;
    
    													dwRVA = (lpSection[dwSection].Misc.VirtualSize + dwMemory) & ~dwMemory;
    
    													if (lpSection[dwSection].SizeOfRawData > dwRVA)
    														PrintConsole(hConsole,
    														             L"Data of \'%.8hs\' section exceeds its size!\n",
    														             lpSection[dwSection].Name);
    
    													dwRVA += lpSection[dwSection].VirtualAddress;
    
    													if (lpSection[dwSection].Name[0] != '.')
    														continue;
    #if 0
    													if (strcmp(lpSection[dwSection].Name, ".arch") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_ARCHITECTURE;
    													else if (strcmp(lpSection[dwSection].Name, ".debug") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_DEBUG;
    													else if ((strcmp(lpSection[dwSection].Name, ".didat") == 0)
    													      || (strcmp(lpSection[dwSection].Name, ".didata") == 0))
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
    													else if (strcmp(lpSection[dwSection].Name, ".edata") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_EXPORT;
    													else if (strcmp(lpSection[dwSection].Name, ".idata") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_IMPORT;
    													else if (strcmp(lpSection[dwSection].Name, ".pdata") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_EXCEPTION;
    													else if (strcmp(lpSection[dwSection].Name, ".reloc") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_BASERELOC;
    													else if (strcmp(lpSection[dwSection].Name, ".rsrc") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_RESOURCE;
    													else if (strcmp(lpSection[dwSection].Name, ".tls") == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_TLS;
    													else
    														continue;
    #else
    													if (memcmp(lpSection[dwSection].Name, ".arch", sizeof(".arch")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_ARCHITECTURE;
    													else if (memcmp(lpSection[dwSection].Name, ".debug", sizeof(".debug")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_DEBUG;
    													else if ((memcmp(lpSection[dwSection].Name, ".didat", sizeof(".didat")) == 0)
    													      || (memcmp(lpSection[dwSection].Name, ".didata", sizeof(".didata")) == 0))
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
    													else if (memcmp(lpSection[dwSection].Name, ".edata", sizeof(".edata")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_EXPORT;
    													else if (memcmp(lpSection[dwSection].Name, ".idata", sizeof(".idata")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_IMPORT;
    													else if (memcmp(lpSection[dwSection].Name, ".pdata", sizeof(".pdata")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_EXCEPTION;
    													else if (memcmp(lpSection[dwSection].Name, ".reloc", sizeof(".reloc")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_BASERELOC;
    													else if (memcmp(lpSection[dwSection].Name, ".rsrc", sizeof(".rsrc")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_RESOURCE;
    													else if (memcmp(lpSection[dwSection].Name, ".tls", sizeof(".tls")) == 0)
    														dwDirectory = IMAGE_DIRECTORY_ENTRY_TLS;
    													else
    														continue;
    #endif
    													if (dwArray & (1 << dwDirectory))
    														PrintConsole(hConsole,
    														             L"Multiple \'%.8hs\' sections!\n",
    														             lpSection[dwSection].Name);
    													else
    													{
    														dwArray |= 1 << dwDirectory;
    
    														if ((lpDirectory[dwDirectory].VirtualAddress == 0)
    														  && (lpDirectory[dwDirectory].Size == 0))
    															PrintConsole(hConsole,
    															             L"No IMAGE_DATA_DIRECTORY[%lu] for \'%.8hs\' section!\n",
    															             dwDirectory, lpSection[dwSection].Name);
    														else if (dwDirectory == IMAGE_DIRECTORY_ENTRY_TLS)
    															lpTLS = lpSection + dwSection;
    														else if ((lpDirectory[dwDirectory].VirtualAddress != lpSection[dwSection].VirtualAddress)
    														      || (lpDirectory[dwDirectory].Size != lpSection[dwSection].Misc.VirtualSize))
    															PrintConsole(hConsole,
    															             L"Address/size in IMAGE_DATA_DIRECTORY[%lu] differ from address/size of \'%.8hs\' section!\n",
    															             dwDirectory, lpSection[dwSection].Name);
    													}
    												}
    
    												if (!bOutput)
    													PrintConsole(hConsole,
    													             L"WriteFile() returned error %lu\n",
    													             dwError = GetLastError());
    
    												if (dwCode != 0)
    													PrintConsole(hConsole,
    													             L"Size of %ls differs from sum of \'*%ls\' section sizes!\n",
    													             L"code", L"text");
    
    												if (dwData != 0)
    													PrintConsole(hConsole,
    													             L"Size of %ls differs from sum of \'*%ls\' section sizes!\n",
    													             L"initialised data", L"data");
    
    												if (dwNone != 0)
    													PrintConsole(hConsole,
    													             L"Size of %ls differs from sum of \'*%ls\' section sizes!\n",
    													             L"uninitialised data", L"bss");
    
    												if (((dwLast + dwMemory) & ~dwMemory) != dwSize)
    													PrintConsole(hConsole,
    													             L"Last COFF section not at end of image!\n");
    
    												if (lpPE->FileHeader.PointerToSymbolTable > dwImage)
    													PrintConsole(hConsole,
    													             L"Pointer to COFF symbol table past file size 0x%08lX!\n",
    													             dwImage);
    												else if (lpPE->FileHeader.PointerToSymbolTable != 0)
    												{
    													bOutput = PrintString(hOutput,
    													                      L"\r\n"
    													                      L"COFF String Table:\r\n");
    
    													lpCOFF = (COFFStringTable *) (lpImage + lpPE->FileHeader.PointerToSymbolTable
    													                                      + lpPE->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL));
    
    													for (lpString = lpCOFF->Strings;
    													     lpString < (CHAR *) lpCOFF + lpCOFF->Size;
    													     lpString += strlen(lpString) + 1)
    														bOutput &= PrintFormat(hOutput,
    														                       L"\t/%lu = %hs\r\n",
    														                       lpString - (CHAR *) lpCOFF, lpString);
    
    													if (!bOutput)
    														PrintConsole(hConsole,
    														             L"WriteFile() returned error %lu\n",
    														             dwError = GetLastError());
    												}
    
    												if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    												{
    													bOutput = PrintFormat(hOutput,
    													                      L"\r\n"
    													                      L"Optional Header:\r\n"
    													                      L"\tMagic                        = 0x%04hX (32-bit)\r\n"
    													                      L"\tSize of Code                 = 0x%08lX\r\n"
    													                      L"\tSize of Initialized Data     = 0x%08lX\r\n"
    													                      L"\tSize of Uninitialized Data   = 0x%08lX\r\n"
    													                      L"\tEntry Point                  = 0x%08lX\r\n"
    													                      L"\tBase of Code                 = 0x%08lX\r\n"
    													                      L"\tBase of Data                 = 0x%08lX\r\n"
    													                      L"\tImage Base                   = 0x%08lX\r\n"
    													                      L"\tSection Alignment            = 0x%08lX\r\n"
    													                      L"\tFile Alignment               = 0x%08lX\r\n"
    													                      L"\tSize of Image                = 0x%08lX\r\n"
    													                      L"\tSize of Headers              = 0x%08lX\r\n"
    													                      L"\tChecksum                     = 0x%08lX\r\n"
    													                      L"\tDLL Characteristics          = 0x%04hX\r\n",
    													                      lpPE32->OptionalHeader.Magic,
    													                      lpPE32->OptionalHeader.SizeOfCode,
    													                      lpPE32->OptionalHeader.SizeOfInitializedData,
    													                      lpPE32->OptionalHeader.SizeOfUninitializedData,
    													                      lpPE32->OptionalHeader.AddressOfEntryPoint,
    													                      lpPE32->OptionalHeader.BaseOfCode,
    													                      lpPE32->OptionalHeader.BaseOfData,
    													                      lpPE32->OptionalHeader.ImageBase,
    													                      lpPE32->OptionalHeader.SectionAlignment,
    													                      lpPE32->OptionalHeader.FileAlignment,
    													                      lpPE32->OptionalHeader.SizeOfImage,
    													                      lpPE32->OptionalHeader.SizeOfHeaders,
    													                      lpPE32->OptionalHeader.CheckSum,
    													                      lpPE32->OptionalHeader.DllCharacteristics);
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_RESERVED) != 0)
    														bOutput &= PrintString(hOutput, L"\t\tReserved\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA)
    														bOutput &= PrintString(hOutput, L"\t\tHigh entropy ASLR\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
    														bOutput &= PrintString(hOutput, L"\t\tDynamic base\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY) == IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY)
    														bOutput &= PrintString(hOutput, L"\t\tCode integrity checks enforced\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT) == IMAGE_DLLCHARACTERISTICS_NX_COMPAT)
    														bOutput &= PrintString(hOutput, L"\t\tNX compatible\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_ISOLATION) == IMAGE_DLLCHARACTERISTICS_NO_ISOLATION)
    														bOutput &= PrintString(hOutput, L"\t\tIsolation aware, but don't isolate\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH) == IMAGE_DLLCHARACTERISTICS_NO_SEH)
    														bOutput &= PrintString(hOutput, L"\t\tNo structured exception handler\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_BIND) == IMAGE_DLLCHARACTERISTICS_NO_BIND)
    														bOutput &= PrintString(hOutput, L"\t\tDon\'t bind\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_APPCONTAINER) == IMAGE_DLLCHARACTERISTICS_APPCONTAINER)
    														bOutput &= PrintString(hOutput, L"\t\tApp container\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WDM_DRIVER) == IMAGE_DLLCHARACTERISTICS_WDM_DRIVER)
    														bOutput &= PrintString(hOutput, L"\t\tWDM driver\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF) == IMAGE_DLLCHARACTERISTICS_GUARD_CF)
    														bOutput &= PrintString(hOutput, L"\t\tControl flow guard\r\n");
    
    													if ((lpPE32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE) == IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)
    														bOutput &= PrintString(hOutput, L"\t\tTerminal server aware\r\n");
    
    													bOutput &= PrintFormat(hOutput,
    													                       L"\tLoader Flags                 = 0x%08lX\r\n",
    													                       lpPE32->OptionalHeader.LoaderFlags);
    
    													if ((lpPE32->OptionalHeader.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS) == IMAGE_LOADER_FLAGS_COMPLUS)
    														bOutput &= PrintString(hOutput, L"\t\tCOM+ image\r\n");
    
    													if ((lpPE32->OptionalHeader.LoaderFlags & IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL) == IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL)
    														bOutput &= PrintString(hOutput, L"\t\tGlobal subsections apply across TS sessions\r\n");
    
    													bOutput &= PrintFormat(hOutput,
    													                       L"\tSize of Stack Reserve        = 0x%08lX\r\n"
    													                       L"\tSize of Stack Commit         = 0x%08lX\r\n"
    													                       L"\tSize of Heap Reserve         = 0x%08lX\r\n"
    													                       L"\tSize of Heap Commit          = 0x%08lX\r\n"
    													                       L"\tNumber of Data Directories   = %lu\r\n",
    													                       lpPE32->OptionalHeader.SizeOfStackReserve,
    													                       lpPE32->OptionalHeader.SizeOfStackCommit,
    													                       lpPE32->OptionalHeader.SizeOfHeapReserve,
    													                       lpPE32->OptionalHeader.SizeOfHeapCommit,
    													                       lpPE32->OptionalHeader.NumberOfRvaAndSizes);
    
    													if (lpPE32->OptionalHeader.NumberOfRvaAndSizes > 0)
    														bOutput &= PrintString(hOutput, L"\tData Directories:\r\n");
    
    													for (dwDirectory = 0; dwDirectory < lpPE32->OptionalHeader.NumberOfRvaAndSizes; dwDirectory++)
    														bOutput &= PrintFormat(hOutput,
    														                       L"\t\t%-20ls = 0x%08lX, 0x%08lX\r\n",
    														                       szDirectory[dwDirectory],
    														                       lpPE32->OptionalHeader.DataDirectory[dwDirectory].VirtualAddress,
    														                       lpPE32->OptionalHeader.DataDirectory[dwDirectory].Size);
    
    													bOutput &= PrintFormat(hOutput,
    													                       L"\tLinker Version               = %u.%u\r\n"
    													                       L"\tOperating System Version     = %hu.%hu\r\n"
    													                       L"\tImage Version                = %hu.%hu\r\n"
    													                       L"\tSubsystem version            = %hu.%hu\r\n"
    													                       L"\tWin32 Version                = %lu (expected: 0)\r\n"
    													                       L"\tSubsystem                    = %hu (%ls)\r\n",
    													                       lpPE32->OptionalHeader.MajorLinkerVersion,
    													                       lpPE32->OptionalHeader.MinorLinkerVersion,
    													                       lpPE32->OptionalHeader.MajorOperatingSystemVersion,
    													                       lpPE32->OptionalHeader.MinorOperatingSystemVersion,
    													                       lpPE32->OptionalHeader.MajorImageVersion,
    													                       lpPE32->OptionalHeader.MinorImageVersion,
    													                       lpPE32->OptionalHeader.MajorSubsystemVersion,
    													                       lpPE32->OptionalHeader.MinorSubsystemVersion,
    													                       lpPE32->OptionalHeader.Win32VersionValue,
    													                       lpPE32->OptionalHeader.Subsystem, SubsystemName(lpPE32->OptionalHeader.Subsystem));
    
    													if (!bOutput)
    														PrintConsole(hConsole,
    														             L"WriteFile() returned error %lu\n",
    														             dwError = GetLastError());
    
    													dwCheckSum = lpPE32->OptionalHeader.CheckSum;
    													lpPE32->OptionalHeader.CheckSum = 0;
    
    													for (lpWord = (WORD *) (lpImage + dwImage + (dwImage & 1)), dwAccumulator = 0;
    													     lpWord > (WORD *) lpImage;
    													     dwAccumulator += *--lpWord, dwAccumulator = HIWORD(dwAccumulator) + LOWORD(dwAccumulator))
    														continue;
    
    													if (dwAccumulator + dwImage != dwCheckSum)
    														PrintConsole(hConsole,
    														             L"Computed checksum 0x%08lX differs from image checksum 0x%08lX!\n",
    														             dwAccumulator + dwImage, dwCheckSum);
    												}
    												else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    												{
    													bOutput = PrintFormat(hOutput,
    													                      L"\r\n"
    													                      L"Optional Header:\r\n"
    													                      L"\tMagic                        = 0x%04hX (64-bit)\r\n"
    													                      L"\tSize of Code                 = 0x%08lX\r\n"
    													                      L"\tSize of Initialized Data     = 0x%08lX\r\n"
    													                      L"\tSize of Uninitialized Data   = 0x%08lX\r\n"
    													                      L"\tEntry Point                  = 0x%08lX\r\n"
    													                      L"\tBase of Code                 = 0x%08lX\r\n"
    													                      L"\tImage Base                   = 0x%016I64X\r\n"
    													                      L"\tSection Alignment            = 0x%08lX\r\n"
    													                      L"\tFile Alignment               = 0x%08lX\r\n"
    													                      L"\tSize of Image                = 0x%08lX\r\n"
    													                      L"\tSize of Headers              = 0x%08lX\r\n"
    													                      L"\tChecksum                     = 0x%08lX\r\n"
    													                      L"\tDLL Characteristics          = 0x%04hX\r\n",
    													                      lpPE64->OptionalHeader.Magic,
    													                      lpPE64->OptionalHeader.SizeOfCode,
    													                      lpPE64->OptionalHeader.SizeOfInitializedData,
    													                      lpPE64->OptionalHeader.SizeOfUninitializedData,
    													                      lpPE64->OptionalHeader.AddressOfEntryPoint,
    													                      lpPE64->OptionalHeader.BaseOfCode,
    													                      lpPE64->OptionalHeader.ImageBase,
    													                      lpPE64->OptionalHeader.SectionAlignment,
    													                      lpPE64->OptionalHeader.FileAlignment,
    													                      lpPE64->OptionalHeader.SizeOfImage,
    													                      lpPE64->OptionalHeader.SizeOfHeaders,
    													                      lpPE64->OptionalHeader.CheckSum,
    													                      lpPE64->OptionalHeader.DllCharacteristics);
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_RESERVED) != 0)
    														bOutput &= PrintString(hOutput, L"\t\tReserved\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA)
    														bOutput &= PrintString(hOutput, L"\t\tHigh entropy ASLR\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
    														bOutput &= PrintString(hOutput, L"\t\tDynamic base\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY) == IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY)
    														bOutput &= PrintString(hOutput, L"\t\tCode integrity checks enforced\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT) == IMAGE_DLLCHARACTERISTICS_NX_COMPAT)
    														bOutput &= PrintString(hOutput, L"\t\tNX compatible\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_ISOLATION) == IMAGE_DLLCHARACTERISTICS_NO_ISOLATION)
    														bOutput &= PrintString(hOutput, L"\t\tIsolation aware, but don't isolate\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH) == IMAGE_DLLCHARACTERISTICS_NO_SEH)
    														bOutput &= PrintString(hOutput, L"\t\tNo structured exception handler\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_BIND) == IMAGE_DLLCHARACTERISTICS_NO_BIND)
    														bOutput &= PrintString(hOutput, L"\t\tDon\'t bind\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_APPCONTAINER) == IMAGE_DLLCHARACTERISTICS_APPCONTAINER)
    														bOutput &= PrintString(hOutput, L"\t\tApp container\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WDM_DRIVER) == IMAGE_DLLCHARACTERISTICS_WDM_DRIVER)
    														bOutput &= PrintString(hOutput, L"\t\tWDM driver\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF) == IMAGE_DLLCHARACTERISTICS_GUARD_CF)
    														bOutput &= PrintString(hOutput, L"\t\tControl flow guard\r\n");
    
    													if ((lpPE64->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE) == IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)
    														bOutput &= PrintString(hOutput, L"\t\tTerminal server aware\r\n");
    
    													bOutput &= PrintFormat(hOutput,
    													                       L"\tLoader Flags                 = 0x%08lX\r\n",
    													                       lpPE64->OptionalHeader.LoaderFlags);
    
    													if ((lpPE64->OptionalHeader.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS) == IMAGE_LOADER_FLAGS_COMPLUS)
    														bOutput &= PrintString(hOutput, L"\t\tCOM+ image\r\n");
    
    													if ((lpPE64->OptionalHeader.LoaderFlags & IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL) == IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL)
    														bOutput &= PrintString(hOutput, L"\t\tGlobal subsections apply across TS sessions\r\n");
    
    													bOutput &= PrintFormat(hOutput,
    													                       L"\tSize of Stack Reserve        = 0x%016I64X\r\n"
    													                       L"\tSize of Stack Commit         = 0x%016I64X\r\n"
    													                       L"\tSize of Heap Reserve         = 0x%016I64X\r\n"
    													                       L"\tSize of Heap Commit          = 0x%016I64X\r\n"
    													                       L"\tNumber of Data Directories   = %lu\r\n",
    													                       lpPE64->OptionalHeader.SizeOfStackReserve,
    													                       lpPE64->OptionalHeader.SizeOfStackCommit,
    													                       lpPE64->OptionalHeader.SizeOfHeapReserve,
    													                       lpPE64->OptionalHeader.SizeOfHeapCommit,
    													                       lpPE64->OptionalHeader.NumberOfRvaAndSizes);
    
    													if (lpPE64->OptionalHeader.NumberOfRvaAndSizes > 0)
    														bOutput &= PrintString(hOutput, L"\tData Directories:\r\n");
    
    													for (dwDirectory = 0; dwDirectory < lpPE64->OptionalHeader.NumberOfRvaAndSizes; dwDirectory++)
    														bOutput &= PrintFormat(hOutput,
    														                       L"\t\t%-20ls = 0x%08lX, 0x%08lX\r\n",
    														                       szDirectory[dwDirectory],
    														                       lpPE64->OptionalHeader.DataDirectory[dwDirectory].VirtualAddress,
    														                       lpPE64->OptionalHeader.DataDirectory[dwDirectory].Size);
    
    													bOutput &= PrintFormat(hOutput,
    													                       L"\tLinker Version               = %u.%u\r\n"
    													                       L"\tOperating System Version     = %hu.%hu\r\n"
    													                       L"\tImage Version                = %hu.%hu\r\n"
    													                       L"\tSubsystem Version            = %hu.%hu\r\n"
    													                       L"\tWin32 Version                = %lu (expected: 0)\r\n"
    													                       L"\tSubsystem                    = %hu (%ls)\r\n",
    													                       lpPE64->OptionalHeader.MajorLinkerVersion,
    													                       lpPE64->OptionalHeader.MinorLinkerVersion,
    													                       lpPE64->OptionalHeader.MajorOperatingSystemVersion,
    													                       lpPE64->OptionalHeader.MinorOperatingSystemVersion,
    													                       lpPE64->OptionalHeader.MajorImageVersion,
    													                       lpPE64->OptionalHeader.MinorImageVersion,
    													                       lpPE64->OptionalHeader.MajorSubsystemVersion,
    													                       lpPE64->OptionalHeader.MinorSubsystemVersion,
    													                       lpPE64->OptionalHeader.Win32VersionValue,
    													                       lpPE64->OptionalHeader.Subsystem, SubsystemName(lpPE64->OptionalHeader.Subsystem));
    
    													if (!bOutput)
    														PrintConsole(hConsole,
    														             L"WriteFile() returned error %lu\n",
    														             dwError = GetLastError());
    
    													dwCheckSum = lpPE64->OptionalHeader.CheckSum;
    													lpPE64->OptionalHeader.CheckSum = 0;
    
    													for (lpWord = (WORD *) (lpImage + dwImage + (dwImage & 1)), dwAccumulator = 0;
    													     lpWord > (WORD *) lpImage;
    													     dwAccumulator += *--lpWord, dwAccumulator = HIWORD(dwAccumulator) + LOWORD(dwAccumulator))
    														continue;
    
    													if (dwAccumulator + dwImage != dwCheckSum)
    														PrintConsole(hConsole,
    														             L"Computed checksum 0x%08lX differs from image checksum 0x%08lX!\n",
    														             dwAccumulator + dwImage, dwCheckSum);
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_EXPORT)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_EXPORT)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".edata", IMAGE_DIRECTORY_ENTRY_EXPORT);
    
    													lpExport = (IMAGE_EXPORT_DIRECTORY *) RVA2Image(lpImage, lpSection, dwSection,
    													                                                lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
    													                                                IMAGE_DIRECTORY_ENTRY_EXPORT,
    													                                                hConsole);
    													if (lpExport != NULL)
    													{
    														lpModule = (CHAR *) RVA2Image(lpImage, lpSection, dwSection,
    														                              lpExport->Name,
    														                              IMAGE_DIRECTORY_ENTRY_EXPORT,
    														                              hConsole);
    
    														qw = __emulu(lpExport->TimeDateStamp, 10000000)	// seconds since 1970-01-01 to
    														   + 116444736000000000;			//  100 nano-seconds since 1601-01-01
    
    														if (!FileTimeToSystemTime((FILETIME *) &qw, &st))
    															PrintConsole(hConsole,
    															             L"FileTimeToSystemTime() returned error %lu for module \'%hs\'\n",
    															             dwError = GetLastError(), lpModule);
    
    														bOutput = PrintFormat(hOutput,
    														                      L"\r\n"
    														                      L"Export Directory:\r\n"
    														                      L"\tCharacteristics        = 0x%08lX\r\n"
    														                      L"\tTime/Date Stamp        = 0x%08lX (%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu UTC)\r\n"
    														                      L"\tVersion                = %hu.%hu\r\n"
    														                      L"\tModule Name            = %hs\r\n"
    														                      L"\tBase of Ordinals       = %lu\r\n"
    														                      L"\tNumber of Functions    = %lu\r\n"
    														                      L"\tNumber of Names        = %lu\r\n"
    														                      L"\tArray of Functions     = 0x%08lX\r\n"
    														                      L"\tArray of Names         = 0x%08lX\r\n"
    														                      L"\tArray of Name Ordinals = 0x%08lX\r\n",
    														                      lpExport->Characteristics,
    														                      lpExport->TimeDateStamp,
    														                      szDayOfWeek[st.wDayOfWeek], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
    														                      lpExport->MajorVersion,
    														                      lpExport->MinorVersion,
    														                      lpModule,
    														                      lpExport->Base,
    														                      lpExport->NumberOfFunctions,
    														                      lpExport->NumberOfNames,
    														                      lpExport->AddressOfFunctions,
    														                      lpExport->AddressOfNames,
    														                      lpExport->AddressOfNameOrdinals);
    
    														lpFunctions = (DWORD *) RVA2Image(lpImage, lpSection, dwSection,
    														                                  lpExport->AddressOfFunctions,
    														                                  IMAGE_DIRECTORY_ENTRY_EXPORT,
    														                                  hConsole);
    														if (lpFunctions != NULL)
    														{
    															if (lpExport->NumberOfNames != 0)
    															{
    																bOutput &= PrintString(hOutput, L"\tNamed Exports:\r\n");
    
    																lpOrdinals = (WORD *) RVA2Image(lpImage, lpSection, dwSection,
    																                                lpExport->AddressOfNameOrdinals,
    																                                IMAGE_DIRECTORY_ENTRY_EXPORT,
    																                                hConsole);
    																lpNames = (DWORD *) RVA2Image(lpImage, lpSection, dwSection,
    																                              lpExport->AddressOfNames,
    																                              IMAGE_DIRECTORY_ENTRY_EXPORT,
    																                              hConsole);
    																dwNames = lpExport->NumberOfNames;
    
    																do
    																{
    																	if (*lpOrdinals < lpExport->NumberOfFunctions)
    																	{
    																		if ((lpFunctions[*lpOrdinals] < lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
    																		 || (lpFunctions[*lpOrdinals] >= lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
    																		                               + lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size))
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t%lu\t%lu\t0x%08lX\t%hs\r\n",
    																			                       lpExport->Base + *lpOrdinals,
    																			                       *lpOrdinals,
    																			                       lpFunctions[*lpOrdinals],
    																			                       RVA2Image(lpImage, lpSection, dwSection,
    																			                                 *lpNames,
    																			                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
    																			                                 hConsole));
    																		else	// forwarded export
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t%lu\t%lu\t-\t\t%hs -> %hs\r\n",
    																			                       lpExport->Base + *lpOrdinals,
    																			                       *lpOrdinals,
    																			                       RVA2Image(lpImage, lpSection, dwSection,
    																			                                 *lpNames,
    																			                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
    																			                                 hConsole),
    																			                       RVA2Image(lpImage, lpSection, dwSection,
    																			                                 lpFunctions[*lpOrdinals],
    																			                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
    																			                                 hConsole));
    
    																		lpFunctions[*lpOrdinals] = 0;
    																	}
    																	else
    																		PrintConsole(hConsole,
    																		             L"Ordinal %hu of export \'%hs\' out of bounds!\n",
    																		             lpExport->Base + *lpOrdinals,
    																		             RVA2Image(lpImage, lpSection, dwSection,
    																		                       *lpNames,
    																		                       IMAGE_DIRECTORY_ENTRY_EXPORT,
    																		                       hConsole));
    
    																	lpOrdinals++;
    																	lpNames++;
    																	dwNames--;
    																} while (dwNames != 0);
    															}
    
    															if (lpExport->NumberOfFunctions > lpExport->NumberOfNames)
    															{
    																bOutput &= PrintString(hOutput, L"\tUnnamed Exports:\r\n");
    
    																for (dwIndex = 0; dwIndex < lpExport->NumberOfFunctions; dwIndex++)
    																	if (lpFunctions[dwIndex] != 0)
    																		if ((lpFunctions[dwIndex] < lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
    																		 || (lpFunctions[dwIndex] >= lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
    																		                           + lpDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size))
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t%lu\t%lu\t0x%08lX\r\n",
    																			                       lpExport->Base + dwIndex,
    																			                       dwIndex,
    																			                       lpFunctions[dwIndex]);
    																		else	// forwarded export
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t%lu\t%lu\t-\t\t-> %hs\r\n",
    																			                       lpExport->Base + dwIndex,
    																			                       dwIndex,
    																			                       RVA2Image(lpImage, lpSection, dwSection,
    																			                                 lpFunctions[dwIndex],
    																			                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
    																			                                 hConsole));
    															}
    														}
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_IMPORT)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_IMPORT)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".idata", IMAGE_DIRECTORY_ENTRY_IMPORT);
    
    													lpImport = (IMAGE_IMPORT_DESCRIPTOR *) RVA2Image(lpImage, lpSection, dwSection,
    													                                                 lpDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
    													                                                 IMAGE_DIRECTORY_ENTRY_IMPORT,
    													                                                 hConsole);
    													if (lpImport != NULL)
    													{
    														bOutput &= PrintString(hOutput,
    														                       L"\r\n"
    														                       L"Import Directory:\r\n");
    
    														while ((lpImport->OriginalFirstThunk != 0)
    														    || (lpImport->TimeDateStamp != 0)
    														    || (lpImport->ForwarderChain != 0)
    														    || (lpImport->Name != 0)
    														    || (lpImport->FirstThunk != 0))
    														{
    															lpModule = (CHAR *) RVA2Image(lpImage, lpSection, dwSection,
    															                              lpImport->Name,
    															                              IMAGE_DIRECTORY_ENTRY_IMPORT,
    															                              hConsole);
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tImport Descriptor:\r\n"
    															                       L"\t\tModule Name     = %hs\r\n"
    															                       L"\t\tTime/Date Stamp = 0x%08lX\r\n"
    															                       L"\t\tForwarder Chain = 0x%08lX\r\n"
    															                       L"\t\tAddress Table   = 0x%08lX\r\n"
    															                       L"\t\tLookup Table    = 0x%08lX\r\n"
    															                       L"\t\tImports:\r\n",
    															                       lpModule,
    															                       lpImport->TimeDateStamp,
    															                       lpImport->ForwarderChain,
    															                       lpImport->FirstThunk,
    															                       lpImport->OriginalFirstThunk);
    
    															if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    															{
    																lpThunk32 = (IMAGE_THUNK_DATA32 *) RVA2Image(lpImage, lpSection, dwSection,
    																                                             lpImport->OriginalFirstThunk != 0 ? lpImport->OriginalFirstThunk : lpImport->FirstThunk,
    																                                             IMAGE_DIRECTORY_ENTRY_IMPORT,
    																                                             hConsole);
    																if (lpThunk32 != NULL)
    																	while (lpThunk32->u1.AddressOfData != 0)
    																	{
    																		if ((lpThunk32->u1.Ordinal & IMAGE_ORDINAL_FLAG32) == IMAGE_ORDINAL_FLAG32)
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t\t%hu\r\n",
    																			                       LOWORD(lpThunk32->u1.Ordinal));
    																		else
    																		{
    																			lpAddress = (IMAGE_IMPORT_BY_NAME *) RVA2Image(lpImage, lpSection, dwSection,
    																			                                               lpThunk32->u1.AddressOfData,
    																			                                               IMAGE_DIRECTORY_ENTRY_IMPORT,
    																			                                               hConsole);
    																			if (lpAddress != NULL)
    																				bOutput &= PrintFormat(hOutput,
    																				                       L"\t\t\t%hu\t%hs\r\n",
    																				                       lpAddress->Hint,
    																				                       lpAddress->Name);
    																		}
    
    																		lpThunk32++;
    																	}
    															}
    															else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    															{
    																lpThunk64 = (IMAGE_THUNK_DATA64 *) RVA2Image(lpImage, lpSection, dwSection,
    																                                             lpImport->OriginalFirstThunk != 0 ? lpImport->OriginalFirstThunk : lpImport->FirstThunk,
    																                                             IMAGE_DIRECTORY_ENTRY_IMPORT,
    																                                             hConsole);
    																if (lpThunk64 != NULL)
    																	while (lpThunk64->u1.AddressOfData != 0)
    																	{
    																		if ((lpThunk64->u1.Ordinal & IMAGE_ORDINAL_FLAG64) == IMAGE_ORDINAL_FLAG64)
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t\t%hu\r\n",
    																			                       LOWORD(lpThunk64->u1.Ordinal));
    																		else
    																		{
    																			lpAddress = (IMAGE_IMPORT_BY_NAME *) RVA2Image(lpImage, lpSection, dwSection,
    																			                                               (DWORD) lpThunk64->u1.AddressOfData,
    																			                                               IMAGE_DIRECTORY_ENTRY_IMPORT,
    																			                                               hConsole);
    																			if (lpAddress != NULL)
    																				bOutput &= PrintFormat(hOutput,
    																				                       L"\t\t\t%hu\t%hs\r\n",
    																				                       lpAddress->Hint,
    																				                       lpAddress->Name);
    																		}
    
    																		lpThunk64++;
    																	}
    															}
    
    															lpImport++;
    														}
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_RESOURCE)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_RESOURCE)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".rsrc", IMAGE_DIRECTORY_ENTRY_RESOURCE);
    
    													lpResource = (IMAGE_RESOURCE_DIRECTORY *) RVA2Image(lpImage, lpSection, dwSection,
    													                                                    lpDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress,
    													                                                    IMAGE_DIRECTORY_ENTRY_RESOURCE,
    													                                                    hConsole);
    													if (lpResource != NULL)
    													{
    														bOutput &= PrintFormat(hOutput,
    														                       L"\r\n"
    														                       L"Resource Directory:\r\n"
    														                       L"\tCharacteristics = 0x%08lX\r\n"
    														                       L"\tTime/Date Stamp = 0x%08lX\r\n"
    														                       L"\tVersion         = %hu.%hu\r\n"
    														                       L"\tNamed Entries   = %hu\r\n"
    														                       L"\tUnnamed Entries = %hu\r\n"
    														                       L"\tEntries:\r\n",
    														                       lpResource->Characteristics,
    														                       lpResource->TimeDateStamp,
    														                       lpResource->MajorVersion,
    														                       lpResource->MinorVersion,
    														                       lpResource->NumberOfNamedEntries,
    														                       lpResource->NumberOfIdEntries);
    
    														bOutput &= Resource(hOutput, lpResource, lpResource, 0);
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_EXCEPTION)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_EXCEPTION)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".pdata", IMAGE_DIRECTORY_ENTRY_EXCEPTION);
    
    													dwException = lpDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
    													lpException = (BYTE *) RVA2Image(lpImage, lpSection, dwSection,
    													                                 lpDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress,
    													                                 IMAGE_DIRECTORY_ENTRY_EXCEPTION,
    													                                 hConsole);
    													if (lpException != NULL)
    													{
    														bOutput &= PrintString(hOutput,
    														                       L"\r\n"
    														                       L"Exception Handler Directory:\r\n");
    
    														if ((lpPE->FileHeader.Machine == IMAGE_FILE_MACHINE_ARMNT)
    														 || (lpPE->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64))
    														{
    															lpARM = (IMAGE_ARMNT_RUNTIME_FUNCTION_ENTRY *) lpException;
    															lpException += dwException;
    
    															do
    																bOutput &= PrintFormat(hOutput,
    																                       L"\tException Handler:\r\n"
    																                       L"\t\tBegin Address = 0x%08lX\r\n"
    																                       L"\t\tUnwind Data   = 0x%08lX\r\n",
    																                       lpARM->BeginAddress,
    																                       lpARM->UnwindData);
    															while (++lpARM < (IMAGE_ARMNT_RUNTIME_FUNCTION_ENTRY *) lpException);
    														}
    														else if (lpPE->FileHeader.Machine == IMAGE_FILE_MACHINE_ALPHA)
    														{
    															lpAlpha = (IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY *) lpException;
    															lpException += dwException;
    
    															do
    																bOutput &= PrintFormat(hOutput,
    																                       L"\tException Handler:\r\n"
    																                       L"\t\tBegin Address      = 0x%08lX\r\n"
    																                       L"\t\tEnd Address        = 0x%08lX\r\n"
    																                       L"\t\tException Handler  = 0x%08lX\r\n"
    																                       L"\t\tHandler Data       = 0x%08lX\r\n"
    																                       L"\t\tProlog End Address = 0x%08lX\r\n",
    																                       lpAlpha->BeginAddress,
    																                       lpAlpha->EndAddress,
    																                       lpAlpha->ExceptionHandler,
    																                       lpAlpha->HandlerData,
    																                       lpAlpha->PrologEndAddress);
    															while (++lpAlpha < (IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY *) lpException);
    														}
    														else if (lpPE->FileHeader.Machine == IMAGE_FILE_MACHINE_ALPHA64)
    														{
    															lpAlpha64 = (IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY *) lpException;
    															lpException += dwException;
    
    															do
    																bOutput &= PrintFormat(hOutput,
    																                       L"\tException Handler:\r\n"
    																                       L"\t\tBegin Address      = 0x%016I64X\r\n"
    																                       L"\t\tEnd Address        = 0x%016I64X\r\n"
    																                       L"\t\tException Handler  = 0x%016I64X\r\n"
    																                       L"\t\tHandler Data       = 0x%016I64X\r\n"
    																                       L"\t\tProlog End Address = 0x%016I64X\r\n",
    																                       lpAlpha64->BeginAddress,
    																                       lpAlpha64->EndAddress,
    																                       lpAlpha64->ExceptionHandler,
    																                       lpAlpha64->HandlerData,
    																                       lpAlpha64->PrologEndAddress);
    															while (++lpAlpha64 < (IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY *) lpException);
    														}
    														else
    														{
    															lpRuntime = (IMAGE_RUNTIME_FUNCTION_ENTRY *) lpException;
    															lpException += dwException;
    
    															do
    																bOutput &= PrintFormat(hOutput,
    																                       L"\tException Handler:\r\n"
    																                       L"\t\tStart & End Address = 0x%08lX, 0x%08lX\r\n"
    																                       L"\t\tUnwind Info Address = 0x%08lX\r\n",
    																                       lpRuntime->BeginAddress,
    																                       lpRuntime->EndAddress,
    																                       lpRuntime->UnwindInfoAddress);
    															while (++lpRuntime < (IMAGE_RUNTIME_FUNCTION_ENTRY *) lpException);
    														}
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_SECURITY)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size != 0))
    												{
    													if (dwOffset != lpDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress)
    														PrintConsole(hConsole,
    														             L"Authenticode signature not adjacent to last COFF section!\n");
    
    													if (dwImage != lpDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress
    													             + lpDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size)
    														PrintConsole(hConsole,
    														             L"Image file extends past authenticode signature!\n");
    
    													bOutput &= PrintString(hOutput,
    													                       L"\r\n"
    													                       L"Security Directory:\r\n");
    
    													lpCertificate = (WIN_CERTIFICATE *) (lpImage + lpDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress);
    													dwCertificate = lpDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
    
    													do
    													{
    														bOutput &= PrintFormat(hOutput,
    														                       L"\tCertificate Entry:\r\n"
    														                       L"\t\tRevision = %hu\r\n"
    														                       L"\t\tType     = %hu (%ls)\r\n"
    														                       L"\t\tSize     = %lu\r\n",
    														                       lpCertificate->wRevision,
    														                       lpCertificate->wCertificateType, CertificateTypeName(lpCertificate->wCertificateType),
    														                       lpCertificate->dwLength);
    
    														blob.cbData = lpCertificate->dwLength - (lpCertificate->bCertificate - (BYTE *) lpCertificate);
    														blob.pbData = lpCertificate->bCertificate;
    
    														if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
    														                      &blob,
    														                      CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
    														                      CERT_QUERY_FORMAT_FLAG_BINARY,
    														                      0,
    														                      (DWORD *) NULL,
    														                      (DWORD *) NULL,
    														                      (DWORD *) NULL,
    														                      &hStore,
    														                      &hMsg,
    														                      NULL))
    															PrintConsole(hConsole,
    															             L"CryptQueryObject() returned error 0x%08lX\n",
    															             dwError = GetLastError());
    														else
    														{
    															if (!CryptMsgGetAndVerifySigner(hMsg,
    															                                1,
    															                                &hStore,
    															                                CMSG_TRUSTED_SIGNER_FLAG,
    															                                &lpSigner,
    															                                (DWORD *) NULL))
    																PrintConsole(hConsole,
    																             L"CryptMsgGetAndVerifySigner() returned error 0x%08lX\n",
    																             dwError = GetLastError());
    															else
    															{
    																dwFlags = 0;
    
    																do
    																{
    																	dwSigner = CertGetNameString(lpSigner,
    #ifndef RDN
    																	                             CERT_NAME_FRIENDLY_DISPLAY_TYPE,
    																	                             dwFlags,
    																	                             NULL,
    #else
    																	                             CERT_NAME_RDN_TYPE,
    																	                             dwFlags,
    																	                             &dwStrType,
    #endif
    																	                             (LPWSTR) NULL,
    																                                     0);
    
    																	if (dwSigner == 0)
    																		PrintConsole(hConsole,
    																		             L"CertGetNameString() returned error 0x%08lX\n",
    																		             dwError = GetLastError());
    																	else
    																	{
    																		szSigner = (LPWSTR) LocalAlloc(LPTR, dwSigner * sizeof(*szSigner));
    
    																		if (szSigner == NULL)
    																			PrintConsole(hConsole,
    																			             L"LocalAlloc() returned error %lu\n",
    																			             dwError = GetLastError());
    																		else
    																		{
    																			dwSigner = CertGetNameString(lpSigner,
    #ifndef RDN
    																			                             CERT_NAME_FRIENDLY_DISPLAY_TYPE,
    																			                             dwFlags,
    																			                             NULL,
    #else
    																			                             CERT_NAME_RDN_TYPE,
    																			                             dwFlags,
    																			                             &dwStrType,
    #endif
    																			                             szSigner,
    																			                             dwSigner);
    
    																			if (dwSigner == 0)
    																				PrintConsole(hConsole,
    																				             L"CertGetNameString() returned error 0x%08lX\n",
    																				             dwError = GetLastError());
    																			else
    																				bOutput &= PrintFormat(hOutput,
    																				                       L"\t\t%ls  = %ls\r\n",
    																				                       dwFlags == 0 ? L"Subject" : L"Issuer ", szSigner);
    
    																			if (LocalFree(szSigner) != NULL)
    																				PrintConsole(hConsole,
    																				             L"LocalFree() returned error %lu\n",
    																				             GetLastError());
    																		}
    																	}
    																} while (dwFlags ^= CERT_NAME_ISSUER_FLAG);
    
    																if (!CertFreeCertificateContext(lpSigner))
    																	PrintConsole(hConsole,
    																	             L"CertFreeCertificateContext() returned error 0x%08lX\n",
    																	             dwError = GetLastError());
    															}
    
    															if (!CryptMsgClose(hMsg))
    																PrintConsole(hConsole,
    																             L"CryptMsgClose() returned error 0x%08lX\n",
    																             dwError = GetLastError());
    
    															if (!CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG))
    																PrintConsole(hConsole,
    																             L"CertCloseStore() returned error 0x%08lX\n",
    																             dwError = GetLastError());
    														}
    
    														dwSize = (lpCertificate->dwLength + sizeof(DWORD64) - 1) & (0 - sizeof(DWORD64));
    														lpCertificate = (WIN_CERTIFICATE *) ((BYTE *) lpCertificate + dwSize);
    														dwCertificate -= dwSize;
    													} while (dwCertificate != 0);
    												}
    												else
    													if (dwOffset != dwImage)
    														PrintConsole(hConsole,
    														             L"Image file extends past last COFF section!\n");
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_BASERELOC)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_BASERELOC)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".reloc", IMAGE_DIRECTORY_ENTRY_BASERELOC);
    
    													dwRelocation = lpDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
    													lpRelocation = (IMAGE_BASE_RELOCATION *) RVA2Image(lpImage, lpSection, dwSection,
    													                                                   lpDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
    													                                                   IMAGE_DIRECTORY_ENTRY_BASERELOC,
    													                                                   hConsole);
    													if (lpRelocation != NULL)
    													{
    														bOutput &= PrintString(hOutput,
    														                       L"\r\n"
    														                       L"Base Relocation Directory:\r\n");
    
    														while (dwRelocation > 0)
    														{
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tRelocation Block:\r\n"
    															                       L"\t\tAddress of Data = 0x%08lX\r\n"
    															                       L"\t\tSize of Block   = 0x%08lX\r\n",
    															                       lpRelocation->VirtualAddress,
    															                       lpRelocation->SizeOfBlock);
    
    															lpWord = (WORD *) (lpRelocation + 1);
    
    															dwRelocation -= lpRelocation->SizeOfBlock;
    															lpRelocation = (IMAGE_BASE_RELOCATION *) ((BYTE *) lpRelocation + lpRelocation->SizeOfBlock);
    
    															do
    																bOutput &= PrintFormat(hOutput,
    																                       L"\t\t\t0x%03hX\t%ls\r\n",
    																                       *lpWord & 0x0FFF,
    																                       szRelocation[*lpWord >> 12]);
    															while (++lpWord < (WORD *) lpRelocation);
    														}
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_DEBUG)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_DEBUG)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".debug", IMAGE_DIRECTORY_ENTRY_DEBUG);
    
    													dwDebug = lpDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
    													lpDebug = (IMAGE_DEBUG_DIRECTORY *) RVA2Image(lpImage, lpSection, dwSection,
    													                                              lpDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
    													                                              IMAGE_DIRECTORY_ENTRY_DEBUG,
    													                                              hConsole);
    													if (lpDebug != NULL)
    													{
    														bOutput &= PrintString(hOutput,
    														                       L"\r\n"
    														                       L"Debug Directory:\r\n");
    														do
    														{
    															qw = __emulu(lpDebug->TimeDateStamp, 10000000)	// seconds since 1970-01-01 to
    															   + 116444736000000000;			//  100 nano-seconds since 1601-01-01
    
    															if (!FileTimeToSystemTime((FILETIME *) &qw, &st))
    																PrintConsole(hConsole,
    																             L"FileTimeToSystemTime() returned error %lu\n",
    																             dwError = GetLastError());
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tDebug Directory Entry:\r\n"
    															                       L"\t\tCharacteristics = 0x%08lX\r\n"
    															                       L"\t\tTime/Date Stamp = 0x%08lX (%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu UTC)\r\n"
    															                       L"\t\tVersion         = %hu.%hu\r\n"
    															                       L"\t\tType            = %lu (%ls)\r\n"
    															                       L"\t\tAddress of Data = 0x%08lX\r\n"
    															                       L"\t\tOffset of Data  = 0x%08lX\r\n"
    															                       L"\t\tSize of Data    = 0x%08lX\r\n",
    															                       lpDebug->Characteristics,
    															                       lpDebug->TimeDateStamp,
    															                       szDayOfWeek[st.wDayOfWeek], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
    															                       lpDebug->MajorVersion,
    															                       lpDebug->MinorVersion,
    															                       lpDebug->Type, DebugTypeName(lpDebug->Type),
    															                       lpDebug->AddressOfRawData,
    															                       lpDebug->PointerToRawData,
    															                       lpDebug->SizeOfData);
    
    															if (lpDebug->Type == IMAGE_DEBUG_TYPE_CODEVIEW)
    															{
    																lpCodeView = (CV_INFO_PDB70 *) (lpImage + lpDebug->PointerToRawData);
    
    																if (lpCodeView->Magic == 'SDSR')
    																	bOutput &= PrintFormat(hOutput,
    																	                       L"\t\t\tFormat    = RSDS\r\n"
    																	                       L"\t\t\tSignature = {%08lX-%04lX-%04lX-%02X%02X-%02X%02X%02X%02X%02X%02X}\r\n"
    																	                       L"\t\t\tAge       = %lu\r\n"
    																	                       L"\t\t\tFilename  = %hs\r\n",
    																	                       lpCodeView->Signature.Data1, lpCodeView->Signature.Data2, lpCodeView->Signature.Data3,
    																	                       lpCodeView->Signature.Data4[0], lpCodeView->Signature.Data4[1],
    																	                       lpCodeView->Signature.Data4[2], lpCodeView->Signature.Data4[3], lpCodeView->Signature.Data4[4],
    																	                       lpCodeView->Signature.Data4[5], lpCodeView->Signature.Data4[6], lpCodeView->Signature.Data4[7],
    																	                       lpCodeView->Age,
    																	                       lpCodeView->PdbFileName);
    																else
    																	bOutput &= PrintFormat(hOutput,
    																	                       L"\t\t\tFormat = %.4hs\r\n",
    																	                       &lpCodeView->Magic);
    															}
    															else if (lpDebug->Type == IMAGE_DEBUG_TYPE_MISC)
    															{
    																lpMisc = (IMAGE_DEBUG_MISC *) (lpImage + lpDebug->PointerToRawData);
    
    																if (lpMisc->DataType == IMAGE_DEBUG_MISC_EXENAME)
    																	bOutput &= PrintFormat(hOutput,
    																	                       lpMisc->Unicode ? L"\t\t\tFilename = %ls\r\n" : L"\t\t\tFilename = %hs\r\n",
    																	                       lpMisc->Data);
    															}
    															else if (lpDebug->Type == IMAGE_DEBUG_TYPE_RESERVED10)
    																bOutput &= PrintFormat(hOutput,
    																                       L"\t\t\tData = 0x%08lX\r\n",
    																                       *(DWORD *) (lpImage + lpDebug->PointerToRawData));
    															else if (lpDebug->Type == IMAGE_DEBUG_TYPE_POGO)
    															{
    															        dwPogo = lpDebug->SizeOfData - sizeof(DWORD);
    																lpPogo = (POGO *) (lpImage + lpDebug->PointerToRawData);
    
    																if (lpPogo->Magic == 'LTCG')
    																	while (dwPogo > 0)
    																	{
    																		bOutput &= PrintFormat(hOutput,
    																		                       L"\t\t%hs:\r\n"
    																		                       L"\t\t\tVirtual Address & Size = 0x%08lX, 0x%08lX\r\n",
    																		                       lpPogo->Entries[0].Section,
    																		                       lpPogo->Entries[0].Address, lpPogo->Entries[0].Size);
    
    																		dwSize = (sizeof(POGO) - sizeof(DWORD) + strlen(lpPogo->Entries[0].Section)) & (0 - sizeof(DWORD));
    																		dwPogo -= dwSize;
    																		lpPogo = (POGO *) ((BYTE *) lpPogo + dwSize);
    																	}
    															}
    
    															lpDebug++;
    															dwDebug -= sizeof(IMAGE_DEBUG_DIRECTORY);
    														} while (dwDebug != 0);
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_ARCHITECTURE)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_ARCHITECTURE)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".arch", IMAGE_DIRECTORY_ENTRY_ARCHITECTURE);
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_TLS)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_TLS)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".tls", IMAGE_DIRECTORY_ENTRY_TLS);
    
    													if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    													{
    														if (lpDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != sizeof(IMAGE_TLS_DIRECTORY32))
    															PrintConsole(hConsole,
    															             L"Size of \'%ls\' differs from size of %ls structure!\n",
    															             L"_tls_used", L"IMAGE_TLS_DIRECTORY32");
    
    														lpTLS32 = (IMAGE_TLS_DIRECTORY32 *) RVA2Image(lpImage, lpSection, dwSection,
    														                                              lpDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress,
    														                                              IMAGE_DIRECTORY_ENTRY_TLS,
    														                                              hConsole);
    														if (lpTLS32 == NULL)
    															PrintConsole(hConsole,
    															             L"No \'%ls\' alias %ls structure!\n",
    															             L"_tls_used", L"IMAGE_TLS_DIRECTORY32");
    														else
    														{
    															if (lpTLS32->StartAddressOfRawData != lpTLS32->EndAddressOfRawData)
    																if (lpTLS == NULL)
    																/*	PrintConsole(hConsole,
    																	             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    																	             ".tls", IMAGE_DIRECTORY_ENTRY_TLS) */;
    																else if ((lpTLS32->StartAddressOfRawData - dwBase != lpTLS->VirtualAddress)
    																      || (lpTLS32->EndAddressOfRawData - lpTLS32->StartAddressOfRawData != lpTLS->Misc.VirtualSize))
    																	PrintConsole(hConsole,
    																	             L"Address/size in %ls differ from address/size of \'.tls\' section!\n",
    																	             L"IMAGE_TLS_DIRECTORY32");
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\r\n"
    															                       L"Thread Local Storage Directory:\r\n"
    															                       L"\tStart Address of Data = 0x%08lX\r\n"
    															                       L"\tEnd Address of Data   = 0x%08lX\r\n"
    															                       L"\tAddress of Index      = 0x%08lX\r\n"
    															                       L"\tAddress of Callbacks  = 0x%08lX\r\n"
    															                       L"\tSize of Zero Fill     = 0x%08lX\r\n"
    															                       L"\tCharacteristics       = 0x%08lX\r\n",
    															                       lpTLS32->StartAddressOfRawData,
    															                       lpTLS32->EndAddressOfRawData,
    															                       lpTLS32->AddressOfIndex,
    															                       lpTLS32->AddressOfCallBacks,
    															                       lpTLS32->SizeOfZeroFill,
    															                       lpTLS32->Characteristics);
    
    															if (lpTLS32->AddressOfCallBacks != 0)
    															{
    																bOutput &= PrintString(hOutput,
    																                       L"\tCallback Functions:\r\n");
    
    																lpCookie32 = (DWORD *) RVA2Image(lpImage, lpSection, dwSection,
    																                                 lpTLS32->AddressOfCallBacks - dwBase,
    																                                 IMAGE_DIRECTORY_ENTRY_TLS,
    																                                 hConsole);
    																if (lpCookie32 != NULL)
    																	while (*lpCookie32 != 0)
    																		bOutput &= PrintFormat(hOutput,
    																		                       L"\t\t0x%08lX\r\n",
    																		                       *lpCookie32++);
    															}
    														}
    													}
    													else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    													{
    														if (lpDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != sizeof(IMAGE_TLS_DIRECTORY64))
    															PrintConsole(hConsole,
    															             L"Size of \'%ls\' differs from size of %ls structure!\n",
    															             L"_tls_used", L"IMAGE_TLS_DIRECTORY64");
    
    														lpTLS64 = (IMAGE_TLS_DIRECTORY64 *) RVA2Image(lpImage, lpSection, dwSection,
    														                                              lpDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress,
    														                                              IMAGE_DIRECTORY_ENTRY_TLS,
    														                                              hConsole);
    														if (lpTLS64 == NULL)
    															PrintConsole(hConsole,
    															             L"No \'%ls\' alias %ls structure!\n",
    															             L"_tls_used", L"IMAGE_TLS_DIRECTORY64");
    														else
    														{
    															if (lpTLS64->StartAddressOfRawData != lpTLS64->EndAddressOfRawData)
    																if (lpTLS == NULL)
    																/*	PrintConsole(hConsole,
    																	             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    																	             ".tls", IMAGE_DIRECTORY_ENTRY_TLS) */;
    																else if ((lpTLS64->StartAddressOfRawData - qwBase != lpTLS->VirtualAddress)
    																      || (lpTLS64->EndAddressOfRawData - lpTLS64->StartAddressOfRawData != lpTLS->Misc.VirtualSize))
    																	PrintConsole(hConsole,
    																	             L"Address/size in %ls differ from address/size of \'.tls\' section!\n",
    																	             L"IMAGE_TLS_DIRECTORY64");
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\r\n"
    															                       L"Thread Local Storage Directory:\r\n"
    															                       L"\tStart Address of Data = 0x%016I64X\r\n"
    															                       L"\tEnd Address of Data   = 0x%016I64X\r\n"
    															                       L"\tAddress of Index      = 0x%016I64X\r\n"
    															                       L"\tAddress of Callbacks  = 0x%016I64X\r\n"
    															                       L"\tSize of Zero Fill     = 0x%08lX\r\n"
    															                       L"\tCharacteristics       = 0x%08lX\r\n",
    															                       lpTLS64->StartAddressOfRawData,
    															                       lpTLS64->EndAddressOfRawData,
    															                       lpTLS64->AddressOfIndex,
    															                       lpTLS64->AddressOfCallBacks,
    															                       lpTLS64->SizeOfZeroFill,
    															                       lpTLS64->Characteristics);
    
    															if (lpTLS64->AddressOfCallBacks != 0)
    															{
    																bOutput &= PrintString(hOutput,
    																                       L"\tCallback Functions:\r\n");
    
    																lpCookie64 = (DWORD64 *) RVA2Image(lpImage, lpSection, dwSection,
    																                                   (DWORD) (lpTLS64->AddressOfCallBacks - qwBase),
    																                                   IMAGE_DIRECTORY_ENTRY_TLS,
    																                                   hConsole);
    																if (lpCookie64 != NULL)
    																	while (*lpCookie64 != 0)
    																		bOutput &= PrintFormat(hOutput,
    																		                       L"\t\t0x%016I64X\r\n",
    																		                       *lpCookie64++);
    															}
    														}
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size != 0))
    												{
    													if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    													{
    														lpLoadCfg32 = (IMAGE_LOAD_CONFIGURATION_DIRECTORY32 *) RVA2Image(lpImage, lpSection, dwSection,
    														                                                                 lpDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress,
    														                                                                 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
    														                                                                 hConsole);
    														while (lpLoadCfg32 != NULL)
    														{
    															if (lpLoadCfg32->Size > sizeof(IMAGE_LOAD_CONFIGURATION_DIRECTORY32))
    																PrintConsole(hConsole,
    																             L"Size of \'%ls\' exceeds size of %ls structure!\n",
    																             L"_load_config_used", L"IMAGE_LOAD_CONFIGURATION_DIRECTORY32");
    
    															if (lpLoadCfg32->Size != lpDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size)
    																PrintConsole(hConsole,
    																             L"Size member of \'%ls\' differs from size member of %ls!\n",
    																             L"_load_config_used", L"IMAGE_DATA_DIRECTORY[10]");
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\r\n"
    															                       L"Load Configuration:\r\n"
    															                       L"\tSize                       = 0x%08lX\r\n"
    															                       L"\tTime/Date Stamp            = 0x%08lX\r\n"
    															                       L"\tVersion                    = %hu.%hu\r\n"
    															                       L"\tGlobal Flags Clear         = 0x%08lX\r\n",
    															                       lpLoadCfg32->Size,
    															                       lpLoadCfg32->TimeDateStamp,
    															                       lpLoadCfg32->MajorVersion,
    															                       lpLoadCfg32->MinorVersion,
    															                       lpLoadCfg32->GlobalFlagsClear);
    
    															for (dwFlags = lpLoadCfg32->GlobalFlagsClear; _BitScanForward(&dwIndex, dwFlags); dwFlags &= dwFlags - 1)
    																bOutput &= PrintFormat(hOutput, L"\t\t%ls\r\n", szGlobalFlags[dwIndex]);
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tGlobal Flags Set           = 0x%08lX\r\n",
    															                       lpLoadCfg32->GlobalFlagsSet);
    
    															for (dwFlags = lpLoadCfg32->GlobalFlagsSet; _BitScanForward(&dwIndex, dwFlags); dwFlags &= dwFlags - 1)
    																bOutput &= PrintFormat(hOutput, L"\t\t%ls\r\n", szGlobalFlags[dwIndex]);
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCritical Section Timeout   = %lu\r\n"
    															                       L"\tDecommit Block Threshold   = 0x%08lX\r\n"
    															                       L"\tDecommit Total Threshold   = 0x%08lX\r\n"
    															                       L"\tLock Prefix Table Address  = 0x%08lX\r\n"
    															                       L"\tMaximum Allocation Size    = 0x%08lX\r\n"
    															                       L"\tVirtual Memory Threshold   = 0x%08lX\r\n"
    															                       L"\tProcess Heap Flags         = 0x%08lX\r\n"
    															                       L"\tProcess Affinity Mask      = 0x%08lX\r\n"
    															                       L"\tCSD Version                = %hu\r\n"
    															                       L"\tDependent Load Flags       = 0x%04hX\r\n",
    															                       lpLoadCfg32->CriticalSectionDefaultTimeout,
    															                       lpLoadCfg32->DeCommitFreeBlockThreshold,
    															                       lpLoadCfg32->DeCommitTotalFreeThreshold,
    															                       lpLoadCfg32->LockPrefixTable,
    															                       lpLoadCfg32->MaximumAllocationSize,
    															                       lpLoadCfg32->VirtualMemoryThreshold,
    															                       lpLoadCfg32->ProcessHeapFlags,
    															                       lpLoadCfg32->ProcessAffinityMask,
    															                       lpLoadCfg32->CSDVersion,
    															                       lpLoadCfg32->DependentLoadFlags);
    
    															if ((lpLoadCfg32->DependentLoadFlags & DONT_RESOLVE_DLL_REFERENCES) == DONT_RESOLVE_DLL_REFERENCES)
    																bOutput &= PrintString(hOutput, L"\t\tDon't resolve DLL references\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_AS_DATAFILE) == LOAD_LIBRARY_AS_DATAFILE)
    																bOutput &= PrintString(hOutput, L"\t\tLoad as data file\r\n");
    #ifdef LOAD_PACKAGED_LIBRARY
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_PACKAGED_LIBRARY) == LOAD_PACKAGED_LIBRARY)
    																bOutput &= PrintString(hOutput, L"\t\tLoad packaged library\r\n");
    #endif
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_WITH_ALTERED_SEARCH_PATH) == LOAD_WITH_ALTERED_SEARCH_PATH)
    																bOutput &= PrintString(hOutput, L"\t\tLoad with altered search path\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_IGNORE_CODE_AUTHZ_LEVEL) == LOAD_IGNORE_CODE_AUTHZ_LEVEL)
    																bOutput &= PrintString(hOutput, L"\t\tIgnore AUTHZ level\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) == LOAD_LIBRARY_AS_IMAGE_RESOURCE)
    																bOutput &= PrintString(hOutput, L"\t\tLoad as image resource\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) == LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
    																bOutput &= PrintString(hOutput, L"\t\tLoad as data file exclusively\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) == LOAD_LIBRARY_REQUIRE_SIGNED_TARGET)
    																bOutput &= PrintString(hOutput, L"\t\tRequire signed target\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) == LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)
    																bOutput &= PrintString(hOutput, L"\t\tSearch DLL directory\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) == LOAD_LIBRARY_SEARCH_APPLICATION_DIR)
    																bOutput &= PrintString(hOutput, L"\t\tSearch application directory\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_SEARCH_USER_DIRS) == LOAD_LIBRARY_SEARCH_USER_DIRS)
    																bOutput &= PrintString(hOutput, L"\t\tSearch user directories\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_SEARCH_SYSTEM32) == LOAD_LIBRARY_SEARCH_SYSTEM32)
    																bOutput &= PrintString(hOutput, L"\t\tSearch system directory\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) == LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)
    																bOutput &= PrintString(hOutput, L"\t\tSearch default directories\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_SEARCH_SAFE_CURRENT_DIRS) == LOAD_LIBRARY_SEARCH_SAFE_CURRENT_DIRS)
    																bOutput &= PrintString(hOutput, L"\t\tSearch safe current directory\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER) == LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER)
    																bOutput &= PrintString(hOutput, L"\t\tSearch system directory, exempt (reverse) forwarder modules\r\n");
    
    															if ((lpLoadCfg32->DependentLoadFlags & LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY) == LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY)
    																bOutput &= PrintString(hOutput, L"\t\tOS integrity continuity\r\n");
    
    															if (lpLoadCfg32->Size < 64)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tEdit List Address          = 0x%08lX\r\n"
    															                       L"\tSecurity Cookie Address    = 0x%08lX\r\n",
    															                       lpLoadCfg32->EditList,
    															                       lpLoadCfg32->SecurityCookie);
    
    															if (lpLoadCfg32->SecurityCookie != 0)
    															{
    																lpCookie32 = (DWORD *) RVA2Image(lpImage, lpSection, dwSection,
    																                                 lpLoadCfg32->SecurityCookie - dwBase,
    																                                 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
    																                                 hConsole);
    																if (lpCookie32 != NULL)
    																	bOutput &= PrintFormat(hOutput,
    																	                       L"\t\tSecurity Cookie    = 0x%08lX (%ls)\r\n",
    																	                       *lpCookie32,
    																	                       *lpCookie32 == 0xBB40E64E ? L"default" : L"custom");
    															}
    
    															if (lpLoadCfg32->Size < 72)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    																               L"\tSEH Table Address          = 0x%08lX\r\n"
    															                       L"\tSEH Table Entries          = %lu\r\n",
    															                       lpLoadCfg32->SEHandlerTable,
    															                       lpLoadCfg32->SEHandlerCount);
    
    															if (lpLoadCfg32->SEHandlerTable != 0)
    															{
    																lpHandler = (DWORD *) RVA2Image(lpImage, lpSection, dwSection,
    																                                lpLoadCfg32->SEHandlerTable - dwBase,
    																                                IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
    																                                hConsole);
    																if (lpHandler != NULL)
    																	for (dwHandler = 0; dwHandler < lpLoadCfg32->SEHandlerCount; dwHandler++)
    																		bOutput &= PrintFormat(hOutput,
    																		                       L"\t\tException Handler  = 0x%08lX\r\n",
    																		                       lpHandler[dwHandler]);
    															}
    
    															if (lpLoadCfg32->Size < 92)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG Check Function         = 0x%08lX\r\n"
    															                       L"\tCFG Dispatch Function      = 0x%08lX\r\n"
    															                       L"\tCFG Function Table         = 0x%08lX\r\n"
    															                       L"\tCFG Function Count         = %lu\r\n"
    															                       L"\tCFG Function Table Stride  = %lu\r\n"
    															                       L"\tCFG Flags                  = 0x%08lX\r\n",
    															                       lpLoadCfg32->GuardCFCheckFunctionPointer,
    															                       lpLoadCfg32->GuardCFDispatchFunctionPointer,
    															                       lpLoadCfg32->GuardCFFunctionTable,
    															                       lpLoadCfg32->GuardCFFunctionCount,
    															                       (lpLoadCfg32->GuardFlags & IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK) >> IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT,
    															                       lpLoadCfg32->GuardFlags & ~IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK);
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_CF_INSTRUMENTED) == IMAGE_GUARD_CF_INSTRUMENTED)
    																bOutput &= PrintString(hOutput, L"\t\tControl flow integrity checks using system-supplied support\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_CFW_INSTRUMENTED) == IMAGE_GUARD_CFW_INSTRUMENTED)
    																bOutput &= PrintString(hOutput, L"\t\tControl flow and write integrity checks\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT) == IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT)
    																bOutput &= PrintString(hOutput, L"\t\tControl flow target metadata\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_SECURITY_COOKIE_UNUSED) == IMAGE_GUARD_SECURITY_COOKIE_UNUSED)
    																bOutput &= PrintString(hOutput, L"\t\t/GS security cookie not used\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_PROTECT_DELAYLOAD_IAT) == IMAGE_GUARD_PROTECT_DELAYLOAD_IAT)
    																bOutput &= PrintString(hOutput, L"\t\tRead-only delay-load IAT\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION) == IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION)
    																bOutput &= PrintString(hOutput, L"\t\tDelay-load import table in own \'.didat\' section\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT) == IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT)
    																bOutput &= PrintString(hOutput, L"\t\tExport suppression information\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION) == IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION)
    																bOutput &= PrintString(hOutput, L"\t\tExport suppression\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT) == IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT)
    																bOutput &= PrintString(hOutput, L"\t\t\'longjmp()\' target information\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_RF_INSTRUMENTED) == IMAGE_GUARD_RF_INSTRUMENTED)
    																bOutput &= PrintString(hOutput, L"\t\tReturn flow instrumentation and metadata\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_RF_ENABLE) == IMAGE_GUARD_RF_ENABLE)
    																bOutput &= PrintString(hOutput, L"\t\tReturn flow protection\r\n");
    
    															if ((lpLoadCfg32->GuardFlags & IMAGE_GUARD_RF_STRICT) == IMAGE_GUARD_RF_STRICT)
    																bOutput &= PrintString(hOutput, L"\t\tReturn flow protection, strict mode\r\n");
    
    															if (lpLoadCfg32->Size < 104)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCode Integrity Flags       = 0x%04hX\r\n"
    															                       L"\tCode Integrity Catalog     = 0x%04hX\r\n"
    															                       L"\tCode Integrity Offset      = 0x%08lX\r\n"
    															                       L"\tReserved                   = 0x%08lX\r\n",
    															                       lpLoadCfg32->CodeIntegrity.Flags,
    															                       lpLoadCfg32->CodeIntegrity.Catalog,
    															                       lpLoadCfg32->CodeIntegrity.CatalogOffset,
    															                       lpLoadCfg32->CodeIntegrity.Reserved);
    
    															if (lpLoadCfg32->Size < 120)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG IAT Entry Table        = 0x%08lX\r\n"
    															                       L"\tCFG IAT Entry Count        = %lu\r\n"
    															                       L"\tCFG Jump Target Table      = 0x%08lX\r\n"
    															                       L"\tCFG Jump Target Count      = %lu\r\n",
    															                       lpLoadCfg32->GuardAddressTakenIatEntryTable,
    															                       lpLoadCfg32->GuardAddressTakenIatEntryCount,
    															                       lpLoadCfg32->GuardLongJumpTargetTable,
    															                       lpLoadCfg32->GuardLongJumpTargetCount);
    
    															if (lpLoadCfg32->Size < 128)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tRelocation Table           = 0x%08lX\r\n"
    															                       L"\tCompiled Hybrid Metadata   = 0x%08lX\r\n",
    															                       lpLoadCfg32->DynamicValueRelocTable,
    															                       lpLoadCfg32->CHPEMetadataPointer);
    
    															if (lpLoadCfg32->Size < 152)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tRFG Failure Routine        = 0x%08lX\r\n"
    															                       L"\tRFG Failure Function       = 0x%08lX\r\n"
    															                       L"\tRelocation Table Offset    = 0x%08lX\r\n"
    															                       L"\tRelocation Table Section   = 0x%04hX\r\n"
    															                       L"\tReserved2                  = %hu\r\n"
    															                       L"\tRFG Stack Pointer Function = 0x%08lX\r\n"
    															                       L"\tHot Patch Table Offset     = 0x%08lX\r\n",
    															                       lpLoadCfg32->GuardRFFailureRoutine,
    															                       lpLoadCfg32->GuardRFFailureRoutineFunctionPointer,
    															                       lpLoadCfg32->DynamicValueRelocTableOffset,
    															                       lpLoadCfg32->DynamicValueRelocTableSection,
    															                       lpLoadCfg32->Reserved2,
    															                       lpLoadCfg32->GuardRFVerifyStackPointerFunctionPointer,
    															                       lpLoadCfg32->HotPatchTableOffset);
    
    															if (lpLoadCfg32->Size < 160)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tReserved3                  = %lu\r\n"
    															                       L"\tEnclave Configuration      = 0x%08lX\r\n",
    															                       lpLoadCfg32->Reserved3,
    															                       lpLoadCfg32->EnclaveConfigurationPointer);
    
    															if (lpLoadCfg32->Size < 164)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tVolatile Metadata Pointer  = 0x%08lX\r\n",
    															                       lpLoadCfg32->VolatileMetadataPointer);
    
    															if (lpLoadCfg32->Size < 172)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG EH Continuation Table  = 0x%08lX\r\n"
    															                       L"\tCFG EH Continuation Count  = %lu\r\n",
    															                       lpLoadCfg32->GuardEHContinuationTable,
    															                       lpLoadCfg32->GuardEHContinuationCount);
    
    															if (lpLoadCfg32->Size < 184)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tXFG Check Function         = 0x%08lX\r\n"
    															                       L"\tXFG Dispatch Function      = 0x%08lX\r\n"
    															                       L"\tXFG Function Table         = 0x%08lX\r\n",
    															                       lpLoadCfg32->GuardXFGCheckFunctionPointer,
    															                       lpLoadCfg32->GuardXFGDispatchFunctionPointer,
    															                       lpLoadCfg32->GuardXFGTableDispatchFunctionPointer);
    
    															if (lpLoadCfg32->Size < 188)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCast Guard OS Failure Mode = 0x%08lX\r\n",
    															                       lpLoadCfg32->CastGuardOsDeterminedFailureMode);
    
    															if (lpLoadCfg32->Size < 192)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG memcpy() Function      = 0x%08lX\r\n",
    															                       lpLoadCfg32->GuardMemcpyFunctionPointer);
    															break;
    														}
    													}
    													else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    													{
    														lpLoadCfg64 = (IMAGE_LOAD_CONFIGURATION_DIRECTORY64 *) RVA2Image(lpImage, lpSection, dwSection,
    														                                                                 lpDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress,
    														                                                                 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
    														                                                                 hConsole);
    														while (lpLoadCfg64 != NULL)
    														{
    															if (lpLoadCfg64->Size > sizeof(IMAGE_LOAD_CONFIGURATION_DIRECTORY64))
    																PrintConsole(hConsole,
    																             L"Size of \'%ls\' exceeds size of %ls structure!\n",
    																             L"_load_config_used", L"IMAGE_LOAD_CONFIGURATION_DIRECTORY64");
    
    															if (lpLoadCfg64->Size != lpDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size)
    																PrintConsole(hConsole,
    																             L"Size member of \'%ls\' differs from size member of %ls!\n",
    																             L"_load_config_used", L"IMAGE_DATA_DIRECTORY[10]");
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\r\n"
    															                       L"Load Configuration:\r\n"
    															                       L"\tSize                       = 0x%08lX\r\n"
    															                       L"\tTime/Date Stamp            = 0x%08lX\r\n"
    															                       L"\tVersion                    = %hu.%hu\r\n"
    															                       L"\tGlobal Flags Clear         = 0x%08lX\r\n",
    															                       lpLoadCfg64->Size,
    															                       lpLoadCfg64->TimeDateStamp,
    															                       lpLoadCfg64->MajorVersion,
    															                       lpLoadCfg64->MinorVersion,
    															                       lpLoadCfg64->GlobalFlagsClear);
    
    															for (dwFlags = lpLoadCfg64->GlobalFlagsClear; _BitScanForward(&dwIndex, dwFlags); dwFlags &= dwFlags - 1)
    																bOutput &= PrintFormat(hOutput, L"\t\t%ls\r\n", szGlobalFlags[dwIndex]);
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tGlobal Flags Set           = 0x%08lX\r\n",
    															                       lpLoadCfg64->GlobalFlagsSet);
    
    															for (dwFlags = lpLoadCfg64->GlobalFlagsSet; _BitScanForward(&dwIndex, dwFlags); dwFlags &= dwFlags - 1)
    																bOutput &= PrintFormat(hOutput, L"\t\t%ls\r\n", szGlobalFlags[dwIndex]);
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCritical Section Timeout   = %lu\r\n"
    															                       L"\tDecommit Block Threshold   = 0x%016I64X\r\n"
    															                       L"\tDecommit Total Threshold   = 0x%016I64X\r\n"
    															                       L"\tLock Prefix table Address  = 0x%016I64X\r\n"
    															                       L"\tMaximum Allocation Size    = 0x%016I64X\r\n"
    															                       L"\tVirtual Memory Threshold   = 0x%016I64X\r\n"
    															                       L"\tProcess Affinity Mask      = 0x%016I64X\r\n"
    															                       L"\tProcess Heap Flags         = 0x%08lX\r\n"
    															                       L"\tCSD Version                = %hu\r\n"
    															                       L"\tDependent Load Flags       = 0x%04hX\r\n",
    															                       lpLoadCfg64->CriticalSectionDefaultTimeout,
    															                       lpLoadCfg64->DeCommitFreeBlockThreshold,
    															                       lpLoadCfg64->DeCommitTotalFreeThreshold,
    															                       lpLoadCfg64->LockPrefixTable,
    															                       lpLoadCfg64->MaximumAllocationSize,
    															                       lpLoadCfg64->VirtualMemoryThreshold,
    															                       lpLoadCfg64->ProcessAffinityMask,
    															                       lpLoadCfg64->ProcessHeapFlags,
    															                       lpLoadCfg64->CSDVersion,
    															                       lpLoadCfg64->DependentLoadFlags);
    
    															if ((lpLoadCfg64->DependentLoadFlags & DONT_RESOLVE_DLL_REFERENCES) == DONT_RESOLVE_DLL_REFERENCES)
    																bOutput &= PrintString(hOutput, L"\t\tDon't resolve DLL references\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_AS_DATAFILE) == LOAD_LIBRARY_AS_DATAFILE)
    																bOutput &= PrintString(hOutput, L"\t\tLoad as data file\r\n");
    #ifdef LOAD_PACKAGED_LIBRARY
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_PACKAGED_LIBRARY) == LOAD_PACKAGED_LIBRARY)
    																bOutput &= PrintString(hOutput, L"\t\tLoad packaged library\r\n");
    #endif
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_WITH_ALTERED_SEARCH_PATH) == LOAD_WITH_ALTERED_SEARCH_PATH)
    																bOutput &= PrintString(hOutput, L"\t\tLoad with altered search path\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_IGNORE_CODE_AUTHZ_LEVEL) == LOAD_IGNORE_CODE_AUTHZ_LEVEL)
    																bOutput &= PrintString(hOutput, L"\t\tIgnore AUTHZ level\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) == LOAD_LIBRARY_AS_IMAGE_RESOURCE)
    																bOutput &= PrintString(hOutput, L"\t\tLoad as image resource\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) == LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
    																bOutput &= PrintString(hOutput, L"\t\tLoad as data file exclusively\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) == LOAD_LIBRARY_REQUIRE_SIGNED_TARGET)
    																bOutput &= PrintString(hOutput, L"\t\tRequire signed target\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) == LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)
    																bOutput &= PrintString(hOutput, L"\t\tSearch DLL directory\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) == LOAD_LIBRARY_SEARCH_APPLICATION_DIR)
    																bOutput &= PrintString(hOutput, L"\t\tSearch application directory\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_SEARCH_USER_DIRS) == LOAD_LIBRARY_SEARCH_USER_DIRS)
    																bOutput &= PrintString(hOutput, L"\t\tSearch user directories\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_SEARCH_SYSTEM32) == LOAD_LIBRARY_SEARCH_SYSTEM32)
    																bOutput &= PrintString(hOutput, L"\t\tSearch system directory\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) == LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)
    																bOutput &= PrintString(hOutput, L"\t\tSearch default directories\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_SEARCH_SAFE_CURRENT_DIRS) == LOAD_LIBRARY_SEARCH_SAFE_CURRENT_DIRS)
    																bOutput &= PrintString(hOutput, L"\t\tSearch safe current directory\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER) == LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER)
    																bOutput &= PrintString(hOutput, L"\t\tSearch system directory, exempt (reverse) forwarder modules\r\n");
    
    															if ((lpLoadCfg64->DependentLoadFlags & LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY) == LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY)
    																bOutput &= PrintString(hOutput, L"\t\tOS integrity continuity\r\n");
    
    															if (lpLoadCfg64->Size < 96)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tEdit List Address          = 0x%016I64X\r\n"
    															                       L"\tSecurity Cookie Address    = 0x%016I64X\r\n",
    															                       lpLoadCfg64->EditList,
    															                       lpLoadCfg64->SecurityCookie);
    
    															if (lpLoadCfg64->SecurityCookie != 0)
    															{
    																lpCookie64 = (DWORD64 *) RVA2Image(lpImage, lpSection, dwSection,
    																                                   (DWORD) (lpLoadCfg64->SecurityCookie - qwBase),
    																                                   IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
    																                                   hConsole);
    																if (lpCookie64 != NULL)
    																	bOutput &= PrintFormat(hOutput,
    																	                       L"\t\tSecurity Cookie    = 0x%016I64X (%ls)\r\n",
    																	                       *lpCookie64,
    																	                       *lpCookie64 == 0x00002B992DDFA232 ? L"default" : L"custom");
    															}
    
    															if (lpLoadCfg64->Size < 112)
    																break;
    
    															if ((lpLoadCfg64->SEHandlerTable != 0)
    															 || (lpLoadCfg64->SEHandlerCount != 0))
    																PrintConsole(hConsole,
    																             L"Structured exception handler table address or entry count not 0!\n");
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tSEH Table Address          = 0x%016I64X\r\n"
    															                       L"\tSEH Table Entries          = %I64u\r\n",
    															                       lpLoadCfg64->SEHandlerTable,
    															                       lpLoadCfg64->SEHandlerCount);
    
    															if (lpLoadCfg64->Size < 148)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG Check Function         = 0x%016I64X\r\n"
    															                       L"\tCFG Dispatch Function      = 0x%016I64X\r\n"
    															                       L"\tCFG Function Table         = 0x%016I64X\r\n"
    															                       L"\tCFG Function Count         = %I64u\r\n"
    															                       L"\tCFG Function Table Stride  = %lu\r\n"
    															                       L"\tCFG Flags                  = 0x%08lX\r\n",
    															                       lpLoadCfg64->GuardCFCheckFunctionPointer,
    															                       lpLoadCfg64->GuardCFDispatchFunctionPointer,
    															                       lpLoadCfg64->GuardCFFunctionTable,
    															                       lpLoadCfg64->GuardCFFunctionCount,
    															                       (lpLoadCfg64->GuardFlags & IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK) >> IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT,
    															                       lpLoadCfg64->GuardFlags & ~IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK);
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_CF_INSTRUMENTED) == IMAGE_GUARD_CF_INSTRUMENTED)
    																bOutput &= PrintString(hOutput, L"\t\tControl flow integrity checks using system-supplied support\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_CFW_INSTRUMENTED) == IMAGE_GUARD_CFW_INSTRUMENTED)
    																bOutput &= PrintString(hOutput, L"\t\tControl flow and write integrity checks\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT) == IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT)
    																bOutput &= PrintString(hOutput, L"\t\tControl flow target metadata\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_SECURITY_COOKIE_UNUSED) == IMAGE_GUARD_SECURITY_COOKIE_UNUSED)
    																bOutput &= PrintString(hOutput, L"\t\t/GS security cookie not used\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_PROTECT_DELAYLOAD_IAT) == IMAGE_GUARD_PROTECT_DELAYLOAD_IAT)
    																bOutput &= PrintString(hOutput, L"\t\tRead-only delay-load IAT\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION) == IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION)
    																bOutput &= PrintString(hOutput, L"\t\tDelay-load import table in own \'.didat\' section\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT) == IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT)
    																bOutput &= PrintString(hOutput, L"\t\tExport suppression information\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION) == IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION)
    																bOutput &= PrintString(hOutput, L"\t\tExport suppression\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT) == IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT)
    																bOutput &= PrintString(hOutput, L"\t\t\'longjmp()\' target information\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_RF_INSTRUMENTED) == IMAGE_GUARD_RF_INSTRUMENTED)
    																bOutput &= PrintString(hOutput, L"\t\tReturn flow instrumentation and metadata\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_RF_ENABLE) == IMAGE_GUARD_RF_ENABLE)
    																bOutput &= PrintString(hOutput, L"\t\tReturn flow protection\r\n");
    
    															if ((lpLoadCfg64->GuardFlags & IMAGE_GUARD_RF_STRICT) == IMAGE_GUARD_RF_STRICT)
    																bOutput &= PrintString(hOutput, L"\t\tReturn flow protection, strict mode\r\n");
    
    															if (lpLoadCfg64->Size < 160)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCode Integrity Flags       = 0x%04hX\r\n"
    															                       L"\tCode Integrity Catalog     = 0x%04hX\r\n"
    															                       L"\tCode Integrity Offset      = 0x%08lX\r\n"
    															                       L"\tReserved                   = 0x%08lX\r\n",
    															                       lpLoadCfg64->CodeIntegrity.Flags,
    															                       lpLoadCfg64->CodeIntegrity.Catalog,
    															                       lpLoadCfg64->CodeIntegrity.CatalogOffset,
    															                       lpLoadCfg64->CodeIntegrity.Reserved);
    
    															if (lpLoadCfg64->Size < 192)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG IAT Entry Table        = 0x%016I64X\r\n"
    															                       L"\tCFG IAT Entry Count        = %I64u\r\n"
    															                       L"\tCFG Jump Target Table      = 0x%016I64X\r\n"
    															                       L"\tCFG Jump Target Count      = %I64u\r\n",
    															                       lpLoadCfg64->GuardAddressTakenIatEntryTable,
    															                       lpLoadCfg64->GuardAddressTakenIatEntryCount,
    															                       lpLoadCfg64->GuardLongJumpTargetTable,
    															                       lpLoadCfg64->GuardLongJumpTargetCount);
    
    															if (lpLoadCfg64->Size < 208)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tRelocation Table           = 0x%016I64X\r\n"
    															                       L"\tCompiled Hybrid Metadata   = 0x%016I64X\r\n",
    															                       lpLoadCfg64->DynamicValueRelocTable,
    															                       lpLoadCfg64->CHPEMetadataPointer);
    
    															if (lpLoadCfg64->Size < 244)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tRFG Failure Routine        = 0x%016I64X\r\n"
    															                       L"\tRFG Failure Function       = 0x%016I64X\r\n"
    															                       L"\tRelocation Table Offset    = 0x%08lX\r\n"
    															                       L"\tRelocation Table Section   = 0x%04hX\r\n"
    															                       L"\tReserved2                  = %hu\r\n"
    															                       L"\tRFG Stack Pointer Function = 0x%016I64X\r\n"
    															                       L"\tHot Patch Table Offset     = 0x%08lX\r\n",
    															                       lpLoadCfg64->GuardRFFailureRoutine,
    															                       lpLoadCfg64->GuardRFFailureRoutineFunctionPointer,
    															                       lpLoadCfg64->DynamicValueRelocTableOffset,
    															                       lpLoadCfg64->DynamicValueRelocTableSection,
    															                       lpLoadCfg64->Reserved2,
    															                       lpLoadCfg64->GuardRFVerifyStackPointerFunctionPointer,
    															                       lpLoadCfg64->HotPatchTableOffset);
    
    															if (lpLoadCfg64->Size < 256)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tReserved3                  = %lu\r\n"
    															                       L"\tEnclave Configuration      = 0x%016I64X\r\n",
    															                       lpLoadCfg64->Reserved3,
    															                       lpLoadCfg64->EnclaveConfigurationPointer);
    
    															if (lpLoadCfg64->Size < 264)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tVolatile Metadata Pointer  = 0x%016I64X\r\n",
    															                       lpLoadCfg64->VolatileMetadataPointer);
    
    															if (lpLoadCfg64->Size < 280)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG EH Continuation Table  = 0x%016I64X\r\n"
    															                       L"\tCFG EH Continuation Count  = %I64u\r\n",
    															                       lpLoadCfg64->GuardEHContinuationTable,
    															                       lpLoadCfg64->GuardEHContinuationCount);
    
    															if (lpLoadCfg64->Size < 304)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tXFG Check Function         = 0x%016I64X\r\n"
    															                       L"\tXFG Dispatch Function      = 0x%016I64X\r\n"
    															                       L"\tXFG Function Table         = 0x%016I64X\r\n",
    															                       lpLoadCfg64->GuardXFGCheckFunctionPointer,
    															                       lpLoadCfg64->GuardXFGDispatchFunctionPointer,
    															                       lpLoadCfg64->GuardXFGTableDispatchFunctionPointer);
    
    															if (lpLoadCfg64->Size < 312)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCast Guard OS Failure Mode = 0x%016I64X\r\n",
    															                       lpLoadCfg64->CastGuardOsDeterminedFailureMode);
    
    															if (lpLoadCfg64->Size < 320)
    																break;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tCFG memcpy() Function      = 0x%016I64X\r\n",
    															                       lpLoadCfg64->GuardMemcpyFunctionPointer);
    															break;
    														}
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size != 0))
    												{
    													bOutput &= PrintString(hOutput,
    													                       L"\r\n"
    													                       L"Bound Import Directory:\r\n");
    
    													lpBound = lpImage
    													        + lpDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
    													dwDescriptor = 0;
    													lpDescriptor = (IMAGE_BOUND_IMPORT_DESCRIPTOR *) lpBound;
    
    													while (lpDescriptor->TimeDateStamp != 0)
    													{
    														qw = __emulu(lpDescriptor->TimeDateStamp, 10000000)	// seconds since 1970-01-01 to
    														   + 116444736000000000;				//  100 nano-seconds since 1601-01-01
    
    														if (!FileTimeToSystemTime((FILETIME *) &qw, &st))
    															PrintConsole(hConsole,
    															             L"FileTimeToSystemTime() returned error %lu for module \'%hs\'\n",
    															             dwError = GetLastError(), lpBound + lpDescriptor->OffsetModuleName);
    
    														if (dwDescriptor == 0)
    														{
    															dwDescriptor = lpDescriptor->NumberOfModuleForwarderRefs;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tBound Import Entry:\r\n"
    															                       L"\t\tModule Name     = %hs\r\n"
    															                       L"\t\tTime/Date Stamp = 0x%08lX (%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu UTC)\r\n",
    															                       lpBound + lpDescriptor->OffsetModuleName,
    															                       lpDescriptor->TimeDateStamp,
    															                       szDayOfWeek[st.wDayOfWeek], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    														}
    														else
    														{
    															dwDescriptor--;
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\t\t\tModule Name     = %hs\r\n"
    															                       L"\t\t\tTime/Date Stamp = 0x%08lX (%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu UTC)\r\n",
    															                       lpBound + lpDescriptor->OffsetModuleName,
    															                       lpDescriptor->TimeDateStamp,
    															                       szDayOfWeek[st.wDayOfWeek], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    														}
    
    														lpDescriptor++;
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size != 0))
    												{
    													if ((dwArray & (1 << IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT)) == 0)
    														PrintConsole(hConsole,
    														             L"No \'%hs\' section for IMAGE_DATA_DIRECTORY[%lu]!\n",
    														             ".didat", IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
    
    													lpDelay = (IMAGE_DELAYLOAD_DESCRIPTOR *) RVA2Image(lpImage, lpSection, dwSection,
    													                                                   lpDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress,
    													                                                   IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
    													                                                   hConsole);
    													if (lpDelay != NULL)
    													{
    														bOutput &= PrintString(hOutput,
    														                       L"\r\n"
    														                       L"Delay Load Import Directory:\r\n");
    
    														while (lpDelay->DllNameRVA != 0)
    														{
    															if (lpDelay->Attributes.RvaBased)
    																dwRVA = lpDelay->DllNameRVA;
    															else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    																dwRVA = lpDelay->DllNameRVA - dwBase;
    															else
    																dwRVA = ~0UL;
    
    															lpModule = (CHAR *) RVA2Image(lpImage, lpSection, dwSection,
    															                              dwRVA,
    															                              IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
    															                              hConsole);
    
    															bOutput &= PrintFormat(hOutput,
    															                       L"\tDelay Load Import Descriptor:\r\n"
    															                       L"\t\tAttributes        = 0x%08lX\r\n"
    															                       L"\t\tModule Name       = %hs\r\n"
    															                       L"\t\tTime/Date Stamp   = 0x%08lX\r\n"
    															                       L"\t\tHandle Address    = 0x%08lX\r\n"
    															                       L"\t\tAddress Table     = 0x%08lX\r\n"
    															                       L"\t\tName Table        = 0x%08lX\r\n"
    															                       L"\t\tBound Name Table  = 0x%08lX\r\n"
    															                       L"\t\tUnload Name Table = 0x%08lX\r\n"
    															                       L"\t\tImports:\r\n",
    															                       lpDelay->Attributes.AllAttributes,
    															                       lpModule,
    															                       lpDelay->TimeDateStamp,
    															                       lpDelay->ModuleHandleRVA,
    															                       lpDelay->ImportAddressTableRVA,
    															                       lpDelay->ImportNameTableRVA,
    															                       lpDelay->BoundImportAddressTableRVA,
    															                       lpDelay->UnloadInformationTableRVA);
    
    															if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    															{
    																lpThunk32 = (IMAGE_THUNK_DATA32 *) RVA2Image(lpImage, lpSection, dwSection,
    																                                             lpDelay->Attributes.RvaBased ? lpDelay->ImportNameTableRVA : lpDelay->ImportNameTableRVA - dwBase,
    																                                             IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
    																                                             hConsole);
    																if (lpThunk32 != NULL)
    																	while (lpThunk32->u1.AddressOfData != 0)
    																	{
    																		if ((lpThunk32->u1.Ordinal & IMAGE_ORDINAL_FLAG32) == IMAGE_ORDINAL_FLAG32)
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t\t%hu\r\n",
    																			                       LOWORD(lpThunk32->u1.Ordinal));
    																		else
    																		{
    																			lpAddress = (IMAGE_IMPORT_BY_NAME *) RVA2Image(lpImage, lpSection, dwSection,
    																			                                               lpDelay->Attributes.RvaBased ? lpThunk32->u1.AddressOfData : lpThunk32->u1.AddressOfData - dwBase,
    																			                                               IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
    																			                                               hConsole);
    																			if (lpAddress != NULL)
    																				bOutput &= PrintFormat(hOutput,
    																				                       L"\t\t\t%hu\t%hs\r\n",
    																				                       lpAddress->Hint,
    																				                       lpAddress->Name);
    																		}
    
    																		lpThunk32++;
    																	}
    															}
    															else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    															{
    																lpThunk64 = (IMAGE_THUNK_DATA64 *) RVA2Image(lpImage, lpSection, dwSection,
    																                                             lpDelay->ImportNameTableRVA,
    																                                             IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
    																                                             hConsole);
    																if (lpThunk64 != NULL)
    																	while (lpThunk64->u1.AddressOfData != 0)
    																	{
    																		if ((lpThunk64->u1.Ordinal & IMAGE_ORDINAL_FLAG64) == IMAGE_ORDINAL_FLAG64)
    																			bOutput &= PrintFormat(hOutput,
    																			                       L"\t\t\t%hu\r\n",
    																			                       LOWORD(lpThunk64->u1.Ordinal));
    																		else
    																		{
    																			lpAddress = (IMAGE_IMPORT_BY_NAME *) RVA2Image(lpImage, lpSection, dwSection,
    																			                                               (DWORD) lpThunk64->u1.AddressOfData,
    																			                                               IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
    																			                                               hConsole);
    																			if (lpAddress != NULL)
    																				bOutput &= PrintFormat(hOutput,
    																				                       L"\t\t\t%hu\t%hs\r\n",
    																				                       lpAddress->Hint,
    																				                       lpAddress->Name);
    																		}
    
    																		lpThunk64++;
    																	}
    															}
    
    															lpDelay++;
    														}
    													}
    												}
    
    												if ((dwDirectory > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress != 0)
    												 && (lpDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size != 0))
    												{
    													lpCOMPlus = (IMAGE_COR20_HEADER *) RVA2Image(lpImage, lpSection, dwSection,
    													                                             lpDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress,
    													                                             IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
    													                                             hConsole);
    													if (lpCOMPlus != NULL)
    													{
    														bOutput &= PrintFormat(hOutput,
    														                       L"\r\n"
    														                       L"COM+ Directory:\r\n"
    														                       L"\tRuntime Version            = %hu.%hu\r\n"
    														                       L"\tFlags                      = 0x%08lX\r\n"
    														                       L"\tEntry Point Token          = 0x%08lX\r\n"
    														                       L"\tMetadata                   = 0x%08lX\r\n"
    														                       L"\tResources                  = 0x%08lX\r\n"
    														                       L"\tStrong Name Signature      = 0x%08lX\r\n"
    														                       L"\tCode Manager Table         = 0x%08lX\r\n"
    														                       L"\tVTable Fixups              = 0x%08lX\r\n"
    														                       L"\tExport Address Table Jumps = 0x%08lX\r\n"
    														                       L"\tManaged Native Header      = 0x%08lX\r\n",
    														                       lpCOMPlus->MajorRuntimeVersion,
    														                       lpCOMPlus->MinorRuntimeVersion,
    														                       lpCOMPlus->Flags,
    														                       lpCOMPlus->EntryPointToken,
    														                       lpCOMPlus->MetaData,
    														                       lpCOMPlus->Resources,
    														                       lpCOMPlus->StrongNameSignature,
    														                       lpCOMPlus->CodeManagerTable,
    														                       lpCOMPlus->VTableFixups,
    														                       lpCOMPlus->ExportAddressTableJumps,
    														                       lpCOMPlus->ManagedNativeHeader);
    													}
    												}
    
    												if (!bOutput)
    													PrintConsole(hConsole,
    													             L"WriteFile() returned error %lu\n",
    													             dwError = GetLastError());
    											}
    										}
    
    										if (!UnmapViewOfFile(lpImage))
    											PrintConsole(hConsole,
    											             L"UnmapViewOfFile() returned error %lu\n",
    											             GetLastError());
    									}
    
    									if (!CloseHandle(hImage))
    										PrintConsole(hConsole,
    										             L"CloseHandle() returned error %lu\n",
    										             GetLastError());
    								}
    							}
    
    							if (!CloseHandle(hInput))
    								PrintConsole(hConsole,
    								             L"CloseHandle() returned error %lu\n",
    								             GetLastError());
    						}
    					}
    
    					if (!CloseHandle(hOutput))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file PE32PLUS.C created in step 1., link the compiled object file PE32PLUS.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FePE32PLUS.COM PE32PLUS.C CRYPT32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE PE32PLUS.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    PE32PLUS.C
    PE32PLUS.C(182) : warning C4214: nonstandard extension used : bit field types other than int
    PE32PLUS.C(183) : warning C4214: nonstandard extension used : bit field types other than int
    PE32PLUS.C(184) : warning C4201: nonstandard extension used : nameless struct/union
    PE32PLUS.C(1245) : warning C4701: potentially uninitialized local variable 'dwRich' used
    PE32PLUS.C(1884) : warning C4701: potentially uninitialized local variable 'lpPE64' used
    PE32PLUS.C(1662) : warning C4701: potentially uninitialized local variable 'lpDirectory' used
    PE32PLUS.C(3263) : warning C4701: potentially uninitialized local variable 'qwBase' used
    PE32PLUS.C(1455) : warning C4701: potentially uninitialized local variable 'dwCode' used
    PE32PLUS.C(1462) : warning C4701: potentially uninitialized local variable 'dwData' used
    PE32PLUS.C(1469) : warning C4701: potentially uninitialized local variable 'dwNone' used
    PE32PLUS.C(1579) : warning C4701: potentially uninitialized local variable 'dwSize' used
    PE32PLUS.C(1406) : warning C4701: potentially uninitialized local variable 'dwOffset' used
    PE32PLUS.C(1400) : warning C4701: potentially uninitialized local variable 'dwMemory' used
    PE32PLUS.C(1385) : warning C4701: potentially uninitialized local variable 'dwFile' used
    PE32PLUS.C(1748) : warning C4701: potentially uninitialized local variable 'lpPE32' used
    PE32PLUS.C(3568) : warning C4701: potentially uninitialized local variable 'dwBase' used
    PE32PLUS.C(1993) : warning C4701: potentially uninitialized local variable 'dwDirectory' used
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Product Key Validator

Purpose
Background Information
Synopsis
Demonstration
Downloads
Implementation and Build Details
Variant 1
Variant 2
Source and Build Instructions – Variant 1
Source and Build Instructions – Variant 2

Purpose

Test (and decode) product keys for Windows Vista and newer versions of Windows NT as well as Microsoft Office 2010 and newer versions.

Background Information

The following eleven product key types are currently known:
OEM:SLP (System Locked Preinstallation)
Manufacturer-specific product key for offline activation of Windows Vista or Windows 7 per external certificate provided in a XrML (.xrm-ms) digital license file on factory installed OEM machines with version 2.0 or 2.1 marker embedded in the SLIC ACPI table of their BIOS.
OEM:COA (Certificate of Authenticity)
Individual product key for online activation of Windows Vista or Windows 7, supplied on a sticker attached to factory installed OEM machines; Windows 7 COA keys are were for online activation of Windows 10 1511 and newer too.
OEM:NONSLP (Non-System Locked Preinstallation)
Individual product key for online activation of a single system, supplied on a sticker attached to System Builder installed machines.
OEM:DM (Data Management)
Device-specific individual product key for online activation of Windows 8 and newer versions of client editions, embedded in the MSDM ACPI table of factory installed OEM machines.
Retail (Full Packaged Product)
Individual product key for online activation of a single system.
Retail (Generic Setup)
Generic setup product key provided with OEM and retail channel installation media for online activation per hardware identification gathered on activated previous installation of Windows 7 and newer versions and stored on Microsoft’s activation servers.
Retail:TB:Eval (Time-Bombed Evaluation)
Volume:CSVLK (Customer-Specific Volume License Key)
Customer-specific KMS host product key.
Volume:GVLK (Generic Volume License Key)
Generic product key provided with VL channel installation media for offline activation of KMS clients per KMS host.
Volume:MAK (Multiple Activation Key)
Individual product key for online activation of a fixed number of systems.
WAU (Windows Anytime Upgrade)
Individual product key for upgrading an activated lower edition of Windows Vista and newer versions.

Synopsis

PIDGENX.COM [‹pidgenx.dll›] ‹pkeyconfig.xrm-ms› ‹product key› …

Demonstration

Decode the well-known generic setup product keys YTMG3-N6DKC-DKB77-7M9GH-8HVX7 and VK7JG-NPHTM-C97JM-9MPGT-3V66T for the Core alias Home and Professional editions of Windows 10 and Windows 11:
.\PIDGENX.COM "%SystemRoot%\System32\SPP\Tokens\PKeyConfig\PKeyConfig.xrm-ms" YTMG3-N6DKC-DKB77-7M9GH-8HVX7 VK7JG-NPHTM-C97JM-9MPGT-3V66T
Module 'C:\Windows\System32\PIDGENX.dll'
	Module version:		10.0:22621.1
	Product version:	10.0:22621.1

Product key 'YTMG3-N6DKC-DKB77-7M9GH-8HVX7' is valid!

DigitalProductId: size = 164
	Product ID:		00326-10000-00000-AA527
	Edition ID:		[TH]X19-98868
	OEM ID:			
	Hardware ID (static):	
	Hardware ID (dynamic):	

DigitalProductId4: size = 1272
	Advanced Product ID:	DUMMY-03261-000-000000-00-1033-9200.0000-3212022
	Activation ID:		2b1f36bb-c1cd-4306-bf5c-a0367c2d97d8
	OEM ID:			
	Edition Type:		Core
	Edition ID:		[TH]X19-98868
	Key Type:		Retail
	EULA:			Retail

Product key 'VK7JG-NPHTM-C97JM-9MPGT-3V66T' is valid!

DigitalProductId: size = 164
	Product ID:		00330-80000-00000-AA779
	Edition ID:		[TH]X19-98841
	OEM ID:			
	Hardware ID (static):	
	Hardware ID (dynamic):	

DigitalProductId4: size = 1272
	Advanced Product ID:	DUMMY-03308-000-000000-00-1033-9200.0000-3212022
	Activation ID:		4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c
	OEM ID:			
	Edition Type:		Professional
	Edition ID:		[TH]X19-98841
	Key Type:		Retail
	EULA:			Retail

Downloads

The console application is available in two functional identical forms: PIDGENX.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and PIDGENX.COM, a small form without these extras.

Implementation and Build Details

Product Key Validator is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Variant 1

The first variant is statically linked with an import library built from scratch; PIDGENX.DLL is located per DLL search order and loaded with the application PIDGENX.COM.

Variant 2

The second variant loads the module specified as first command-line argument dynamically; unless specified with an absolute path name it is located per DLL search order too but restricted to safe directories.

Source and Build Instructions – Variant 1

Perform the following three simple steps to build the first variant of the console application Product Key Validator from the source presented hereafter.
  1. Create the text file PIDGENX.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #ifndef _DLL
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #ifndef E_FILENOTFOUND
    #define E_FILENOTFOUND	0x80070002L	// file not found
    #endif
    
    #ifndef E_PATHNOTFOUND
    #define E_PATHNOTFOUND	0x80070003L	// path not found
    #endif
    
    #ifndef E_RESERVEDKEY
    #define E_RESERVEDKEY	0x8A010001L	// reserved product key
    #endif
    
    #ifndef E_INVALIDKEY
    #define E_INVALIDKEY	0x8A010101L	// invalid product key
    #endif
    
    #define VS_BINARY	0U
    #define VS_TEXT		1U
    
    typedef	struct	_VS_VERSIONINFO
    {
    	WORD	wSize;			// size of 'VERSION' resource
    	WORD	wCount;			// = sizeof(VS_FIXEDFILEINFO)
    					//   (number of bytes in binary value)
    	WORD	wType;			// = VS_BINARY
    	WCHAR	szKey[16];		// = L"VS_VERSION_INFO"
    	WORD	wPadding;		// = 0 (alignment to DWORD)
    
    	VS_FIXEDFILEINFO	vsFFI;
    } VS_VERSIONINFO;
    
    typedef	struct	_DigitalProductId
    {
    	DWORD	dwSize;			// 0x000000A4 = 164
    	WORD	wMajorVersion;		// 0x0003
    	WORD	wMinorVersion;		// 0x0000
    	CHAR	szProductId[24];	// "DUMMY-OEM-0123456-78901"
    	DWORD	dwKeyIdx;
    	CHAR	szEditionId[16];
    	BYTE	bCdKey[16];
    	DWORD	dwCloneStatus;
    	DWORD	dwTime;
    	DWORD	dwRandom;
    	DWORD	dwLt;
    	DWORD	dwLicenseData[2];
    	CHAR	sOemId[8];
    	DWORD	dwBundleId;
    	CHAR	sHardwareIdStatic[8];
    	DWORD	dwHardwareIdTypeStatic;
    	DWORD	dwBiosChecksumStatic;
    	DWORD	dwVolumeSerialStatic;
    	DWORD	dwTotalRamStatic;
    	DWORD	dwVideoBiosChecksumStatic;
    	CHAR	sHardwareIdDynamic[8];
    	DWORD	dwHardwareIdTypeDynamic;
    	DWORD	dwBiosChecksumDynamic;
    	DWORD	dwVolumeSerialDynamic;
    	DWORD	dwTotalRamDynamic;
    	DWORD	dwVideoBiosChecksumDynamic;
    	DWORD	dwCRC32;
    } DPI, *LPDPI;
    
    typedef	struct	_DigitalProductId4
    {
    	DWORD	dwSize;			// 0x000004F8 = 1272
    	WORD	wMajorVersion;		// 0x0004
    	WORD	wMinorVersion;		// 0x0000
    	WCHAR	szAdvancedPid[64];
    	WCHAR	szActivationId[64];
    	WCHAR	szOemId[8];
    	WCHAR	szEditionType[260];
    	BYTE	bIsUpgrade;
    	BYTE	bReserved[7];
    	BYTE	bCdKey[16];
    	BYTE	bCdKey256Hash[32];
    	BYTE	b256Hash[32];
    	WCHAR	szEditionId[64];
    	WCHAR	szKeyType[64];
    	WCHAR	szEULA[64];
    } DPI4, *LPDPI4;
    
    __declspec(dllimport)
    HRESULT	WINAPI	PidGenX(LPCWSTR lpProductKey,
    		        LPCWSTR lpPKeyConfig,
    		        LPCWSTR lpMPC,
    		        LPCWSTR lpOEMId,
    		        LPCWSTR lpProductId,
    		        LPDPI   lpDigitalProductId,
    		        LPDPI4  lpDigitalProductId4);
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	VS_VERSIONINFO	*lpVersion;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 2;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	HMODULE	hPidGenX;
    	HRSRC	hResInfo;
    	HGLOBAL	hResData;
    	WCHAR	szPidGenX[MAX_PATH];
    	WCHAR	szPid[24];
    	DPI	dpi;
    	DPI4	dpi4;
    	HRESULT	hr;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 3)
    				PrintConsole(hConsole,
    				             L"Bad arguments: the file or path name of a \'PKeyConfig[*].xrm-ms\' XrML file plus\n"
    				             L"               at least one product key must be given!\n");
    			else
    			{
    				hPidGenX = GetModuleHandle(L"PidGenX");
    
    				if (hPidGenX == NULL)
    					PrintConsole(hConsole,
    					             L"GetModuleHandle() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (GetModuleFileName(hPidGenX, szPidGenX, sizeof(szPidGenX) / sizeof(*szPidGenX)) == 0)
    						PrintConsole(hConsole,
    						             L"GetModuleFileName() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						PrintConsole(hConsole,
    						             L"Module \'%ls\'\n",
    						             szPidGenX);
    
    					hResInfo = FindResource(hPidGenX, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
    
    					if (hResInfo == NULL)
    						PrintConsole(hConsole,
    						             L"FindResource() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    					{
    						hResData = LoadResource(hPidGenX, hResInfo);
    
    						if (hResData == NULL)
    							PrintConsole(hConsole,
    							             L"LoadResource() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							lpVersion = LockResource(hResData);
    
    							if (lpVersion == NULL)
    								PrintConsole(hConsole,
    								             L"LockResource() returned NULL\n");
    							else
    								PrintConsole(hConsole,
    								             L"\tModule version:\t\t%hu.%hu:%hu.%hu\n"
    								             L"\tProduct version:\t%hu.%hu:%hu.%hu\n",
    								             HIWORD(lpVersion->vsFFI.dwFileVersionMS), LOWORD(lpVersion->vsFFI.dwFileVersionMS),
    								             HIWORD(lpVersion->vsFFI.dwFileVersionLS), LOWORD(lpVersion->vsFFI.dwFileVersionLS),
    								             HIWORD(lpVersion->vsFFI.dwProductVersionMS), LOWORD(lpVersion->vsFFI.dwProductVersionMS),
    								             HIWORD(lpVersion->vsFFI.dwProductVersionLS), LOWORD(lpVersion->vsFFI.dwProductVersionLS));
    						}
    					}
    				}
    
    				dpi.dwSize = sizeof(dpi);
    				dpi4.dwSize = sizeof(dpi4);
    
    				do
    				{
    					hr = PidGenX(lpArguments[nArgument],
    					             lpArguments[1],
    					             L"DUMMY",
    					             (LPCWSTR) NULL,
    					             szPid,
    					             &dpi,
    					             &dpi4);
    
    					switch (hr)
    					{
    					case ERROR_FILE_NOT_FOUND:
    					case ERROR_PATH_NOT_FOUND:
    					case E_FILENOTFOUND:		// file 'PKeyConfig.xrm-ms' not found
    					case E_PATHNOTFOUND:		// path of 'PKeyConfig.xrm-ms' not found
    
    						nArguments = 0;
    
    						PrintConsole(hConsole,
    						             L"Data file \'%ls\' not found!\n",
    						             lpArguments[1]);
    						break;
    
    					case ERROR_INVALID_PARAMETER:
    					case E_INVALIDARG:		// malformed product key
    
    						PrintConsole(hConsole,
    						             L"Product key \'%ls\' is malformed!\n",
    						             lpArguments[nArgument]);
    						break;
    
    					case E_RESERVEDKEY:		// reserved product key
    
    						PrintConsole(hConsole,
    						             L"Product key \'%ls\' is reserved!\n",
    						             lpArguments[nArgument]);
    						break;
    
    					case E_INVALIDKEY:		// invalid product key
    
    						PrintConsole(hConsole,
    						             L"Product key \'%ls\' is invalid!\n",
    						             lpArguments[nArgument]);
    						break;
    
    					case S_OK:
    
    						PrintConsole(hConsole,
    						             L"Product key \'%ls\' is valid!\n",
    						             lpArguments[nArgument]);
    #ifdef VERBOSE
    						if ((dpi.dwSize != sizeof(dpi))
    						 || (dpi.wMajorVersion != 3)
    						 || (dpi.wMinorVersion != 0))
    							PrintConsole(hConsole,
    							             L"Size of \'DigitalProductId\' not equal %lu or version not equal 3.0\n",
    							             sizeof(dpi));
    						else
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"DigitalProductId: size = %lu\n"
    							             L"\tProduct ID:\t\t%hs\n"
    							             L"\tEdition ID:\t\t%hs\n"
    							             L"\tOEM ID:\t\t\t%.8hs\n"
    							             L"\tHardware ID (static):\t%.8hs\n"
    							             L"\tHardware ID (dynamic):\t%.8hs\n",
    							             dpi.dwSize,
    							             dpi.szProductId,
    							             dpi.szEditionId,
    							             dpi.sOemId,
    							             dpi.sHardwareIdStatic,
    							             dpi.sHardwareIdDynamic);
    
    						if ((dpi4.dwSize != sizeof(dpi4))
    						 || (dpi4.wMajorVersion != 4)
    						 || (dpi4.wMinorVersion != 0))
    							PrintConsole(hConsole,
    							             L"Size of \'DigitalProductId4\' not equal %lu or version not equal 4.0\n",
    							             sizeof(dpi4));
    						else
    							PrintConsole(hConsole,
    							             L"\n"
    							             L"DigitalProductId4: size = %lu\n"
    							             L"\tAdvanced Product ID:\t%ls\n"
    							             L"\tActivation ID:\t\t%ls\n"
    							             L"\tOEM ID:\t\t\t%ls\n"
    							             L"\tEdition Type:\t\t%ls\n"
    							             L"\tEdition ID:\t\t%ls\n"
    							             L"\tKey Type:\t\t%ls\n"
    							             L"\tEULA:\t\t\t%ls\n",
    							             dpi4.dwSize,
    							             dpi4.szAdvancedPid,
    							             dpi4.szActivationId,
    							             dpi4.szOemId,
    							             dpi4.szEditionType,
    							             dpi4.szEditionId,
    							             dpi4.szKeyType,
    							             dpi4.szEULA);
    #endif
    						break;
    
    					default:
    						PrintConsole(hConsole,
    						             L"PidGenX() returned error 0x%08lX\n",
    						             dwError = hr);
    					}
    				} while (++nArgument < nArguments);
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
    #else // _DLL
    __declspec(dllexport)
    long	PidGenX(void *_1, void *_2, void *_3, void *_4, void *_5, void *_6, void *_7)
    { return 0; }
    #endif // _DLL
  2. Run the following four command lines to compile the source file PIDGENX.C created in step 1. a first time, generate the import library PIDGENX.LIB from the compiled object file PIDGENX.OBJ and cleanup afterwards:

    SET CL=/Gz /LD /MD /W4 /wd4100 /X /Zl
    SET LINK=/EXPORT:PidGenX /NODEFAULTLIB /NOENTRY
    CL.EXE PIDGENX.C
    ERASE PIDGENX.DLL PIDGENX.EXP PIDGENX.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    PIDGENX.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …
       Creating library PIDGENX.lib and object PIDGENX.exp
  3. Run the following four command lines to compile the source file PIDGENX.C created in step 1. a second time, link the compiled object file PIDGENX.OBJ with the import library PIDGENX.LIB generated in step 2. and cleanup afterwards:

    SET CL=/DVERBOSE /GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.1 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FePIDGENX.COM PIDGENX.C KERNEL32.LIB PIDGENX.LIB SHELL32.LIB USER32.LIB
    ERASE PIDGENX.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    PIDGENX.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Source and Build Instructions – Variant 2

Perform the following two simple steps to build the second variant of the console application Product Key Validator from the source presented hereafter.
  1. Overwrite the text file PIDGENX.C with the following content:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #ifndef LOAD_LIBRARY_SAFE_CURRENT_DIRS
    #define LOAD_LIBRARY_SAFE_CURRENT_DIRS	0x00002000UL
    #endif
    
    #ifndef E_FILENOTFOUND
    #define E_FILENOTFOUND	0x80070002L	// file not found
    #endif
    
    #ifndef E_PATHNOTFOUND
    #define E_PATHNOTFOUND	0x80070003L	// path not found
    #endif
    
    #ifndef E_RESERVEDKEY
    #define E_RESERVEDKEY	0x8A010001L	// reserved product key
    #endif
    
    #ifndef E_INVALIDKEY
    #define E_INVALIDKEY	0x8A010101L	// invalid product key
    #endif
    
    #define VS_BINARY	0U
    #define VS_TEXT		1U
    
    typedef	struct	_VS_VERSIONINFO
    {
    	WORD	wSize;			// size of 'VERSION' resource
    	WORD	wCount;			// = sizeof(VS_FIXEDFILEINFO)
    					//   (number of bytes in binary value)
    	WORD	wType;			// = VS_BINARY
    	WCHAR	szKey[16];		// = L"VS_VERSION_INFO"
    	WORD	wPadding;		// = 0 (alignment to DWORD)
    
    	VS_FIXEDFILEINFO	vsFFI;
    } VS_VERSIONINFO;
    
    typedef	struct	_DigitalProductId
    {
    	DWORD	dwSize;			// 0x000000A4 = 164
    	WORD	wMajorVersion;		// 0x0003
    	WORD	wMinorVersion;		// 0x0000
    	CHAR	szProductId[24];	// "DUMMY-OEM-0123456-78901"
    	DWORD	dwKeyIdx;
    	CHAR	szEditionId[16];
    	BYTE	bCdKey[16];
    	DWORD	dwCloneStatus;
    	DWORD	dwTime;
    	DWORD	dwRandom;
    	DWORD	dwLt;
    	DWORD	dwLicenseData[2];
    	CHAR	sOemId[8];
    	DWORD	dwBundleId;
    	CHAR	sHardwareIdStatic[8];
    	DWORD	dwHardwareIdTypeStatic;
    	DWORD	dwBiosChecksumStatic;
    	DWORD	dwVolumeSerialStatic;
    	DWORD	dwTotalRamStatic;
    	DWORD	dwVideoBiosChecksumStatic;
    	CHAR	sHardwareIdDynamic[8];
    	DWORD	dwHardwareIdTypeDynamic;
    	DWORD	dwBiosChecksumDynamic;
    	DWORD	dwVolumeSerialDynamic;
    	DWORD	dwTotalRamDynamic;
    	DWORD	dwVideoBiosChecksumDynamic;
    	DWORD	dwCRC32;
    } DPI, *LPDPI;
    
    typedef	struct	_DigitalProductId4
    {
    	DWORD	dwSize;			// 0x000004F8 = 1272
    	WORD	wMajorVersion;		// 0x0004
    	WORD	wMinorVersion;		// 0x0000
    	WCHAR	szAdvancedPid[64];
    	WCHAR	szActivationId[64];
    	WCHAR	szOemId[8];
    	WCHAR	szEditionType[260];
    	BYTE	bIsUpgrade;
    	BYTE	bReserved[7];
    	BYTE	bCdKey[16];
    	BYTE	bCdKey256Hash[32];
    	BYTE	b256Hash[32];
    	WCHAR	szEditionId[64];
    	WCHAR	szKeyType[64];
    	WCHAR	szEULA[64];
    } DPI4, *LPDPI4;
    
    typedef	HRESULT	(WINAPI	PIDGENX) (LPCWSTR lpProductKey,
    			          LPCWSTR lpPKeyConfig,
    			          LPCWSTR lpMPC,
    			          LPCWSTR lpOEMId,
    			          LPCWSTR lpProductId,
    			          LPDPI   lpDigitalProductId,
    			          LPDPI4  lpDigitalProductId4);
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	VS_VERSIONINFO	*lpVersion;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 3;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	WCHAR	szPid[24];
    	DPI	dpi;
    	DPI4	dpi4;
    	HMODULE	hPidGenX;
    	FARPROC	fpPidGenX;
    	HRESULT	hr;
    	HRSRC	hResInfo;
    	HGLOBAL	hResData;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 4)
    				PrintConsole(hConsole,
    				             L"Bad arguments: the (absolute or relative) path names of a \'PidGenX.dll\' and\n"
    				             L"               its associated \'PKeyConfig[*].xrm-ms\' XrML file plus at least\n"
    				             L"               one product key \'23467-89BCD-FGHJK-MNPQR-TVWXY\' must be given!\n");
    			else
    			{
    				hPidGenX = LoadLibraryEx(lpArguments[1], (HANDLE) NULL, LOAD_LIBRARY_SAFE_CURRENT_DIRS);
    
    				if (hPidGenX == NULL)
    					PrintConsole(hConsole,
    					             L"LoadLibraryEx() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					fpPidGenX = GetProcAddress(hPidGenX, "PidGenX");
    
    					if (fpPidGenX == NULL)
    						PrintConsole(hConsole,
    						             L"GetProcAddress() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    					{
    						hResInfo = FindResource(hPidGenX, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
    
    						if (hResInfo == NULL)
    							PrintConsole(hConsole,
    							             L"FindResource() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							hResData = LoadResource(hPidGenX, hResInfo);
    
    							if (hResData == NULL)
    								PrintConsole(hConsole,
    								             L"LoadResource() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								lpVersion = LockResource(hResData);
    
    								if (lpVersion == NULL)
    									PrintConsole(hConsole,
    									             L"LockResource() returned NULL\n");
    								else
    									PrintConsole(hConsole,
    									             L"Library version = %hu.%hu:%hu.%hu\n"
    									             L"Product version = %hu.%hu:%hu.%hu\n",
    									             HIWORD(lpVersion->vsFFI.dwFileVersionMS), LOWORD(lpVersion->vsFFI.dwFileVersionMS),
    									             HIWORD(lpVersion->vsFFI.dwFileVersionLS), LOWORD(lpVersion->vsFFI.dwFileVersionLS),
    									             HIWORD(lpVersion->vsFFI.dwProductVersionMS), LOWORD(lpVersion->vsFFI.dwProductVersionMS),
    									             HIWORD(lpVersion->vsFFI.dwProductVersionLS), LOWORD(lpVersion->vsFFI.dwProductVersionLS));
    							}
    						}
    
    						dpi.dwSize = sizeof(dpi);
    						dpi4.dwSize = sizeof(dpi4);
    
    						do
    						{
    							hr = ((PIDGENX *) fpPidGenX)(lpArguments[nArgument],
    							                             lpArguments[2],
    							                             L"DUMMY",
    							                             (LPCWSTR) NULL,
    							                             szPid,
    							                             &dpi,
    							                             &dpi4);
    
    							switch (hr)
    							{
    							case ERROR_FILE_NOT_FOUND:
    							case ERROR_PATH_NOT_FOUND:
    							case E_FILENOTFOUND:		// file 'PKeyConfig.xrm-ms' not found
    							case E_PATHNOTFOUND:		// path of 'PKeyConfig.xrm-ms' not found
    
    								nArguments = 0;
    
    								PrintConsole(hConsole,
    								             L"Data file \'%ls\' not found!\n",
    								             lpArguments[2]);
    								break;
    
    							case ERROR_INVALID_PARAMETER:
    							case E_INVALIDARG:		// malformed product key
    
    								PrintConsole(hConsole,
    								             L"Product key \'%ls\' is malformed!\n",
    								             lpArguments[nArgument]);
    								break;
    
    							case E_RESERVEDKEY:		// reserved product key
    
    								PrintConsole(hConsole,
    								             L"Product key \'%ls\' is reserved!\n",
    								             lpArguments[nArgument]);
    								break;
    
    							case E_INVALIDKEY:		// invalid product key
    
    								PrintConsole(hConsole,
    								             L"Product key \'%ls\' is invalid!\n",
    								             lpArguments[nArgument]);
    								break;
    
    							case S_OK:
    
    								PrintConsole(hConsole,
    								             L"Product key \'%ls\' is valid!\n",
    								             lpArguments[nArgument]);
    #ifdef VERBOSE
    								if ((dpi.dwSize != sizeof(dpi))
    								 || (dpi.wMajorVersion != 3)
    								 || (dpi.wMinorVersion != 0))
    									PrintConsole(hConsole,
    									             L"Size of \'DigitalProductId\' not equal %lu or version not equal 3.0\n",
    									             sizeof(dpi));
    								else
    									PrintConsole(hConsole,
    									             L"\n"
    									             L"DigitalProductId: size = %lu\n"
    									             L"\tProduct ID:\t\t%hs\n"
    									             L"\tEdition ID:\t\t%hs\n"
    									             L"\tOEM ID:\t\t\t%.8hs\n"
    									             L"\tHardware ID (static):\t%.8hs\n"
    									             L"\tHardware ID (dynamic):\t%.8hs\n",
    									             dpi.dwSize,
    									             dpi.szProductId,
    									             dpi.szEditionId,
    									             dpi.sOemId,
    									             dpi.sHardwareIdStatic,
    									             dpi.sHardwareIdDynamic);
    
    								if ((dpi4.dwSize != sizeof(dpi4))
    								 || (dpi4.wMajorVersion != 4)
    								 || (dpi4.wMinorVersion != 0))
    									PrintConsole(hConsole,
    									             L"Size of \'DigitalProductId4\' not equal %lu or version not equal 4.0\n",
    									             sizeof(dpi4));
    								else
    									PrintConsole(hConsole,
    									             L"\n"
    									             L"DigitalProductId4: size = %lu\n"
    									             L"\tAdvanced Product ID:\t%ls\n"
    									             L"\tActivation ID:\t\t%ls\n"
    									             L"\tOEM ID:\t\t\t%ls\n"
    									             L"\tEdition Type:\t\t%ls\n"
    									             L"\tEdition ID:\t\t%ls\n"
    									             L"\tKey Type:\t\t%ls\n"
    									             L"\tEULA:\t\t\t%ls\n",
    									             dpi4.dwSize,
    									             dpi4.szAdvancedPid,
    									             dpi4.szActivationId,
    									             dpi4.szOemId,
    									             dpi4.szEditionType,
    									             dpi4.szEditionId,
    									             dpi4.szKeyType,
    									             dpi4.szEULA);
    #endif
    								break;
    
    							default:
    								PrintConsole(hConsole,
    								             L"PidGenX() returned error 0x%08lX\n",
    								             dwError = hr);
    							}
    						} while (++nArgument < nArguments);
    					}
    
    					if (!FreeLibrary(hPidGenX))
    						PrintConsole(hConsole,
    						             L"FreeLibrary() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file PIDGENX.C created in step 1., link the compiled object file PIDGENX.OBJ and cleanup afterwards:

    SET CL=/DVERBOSE /GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FePIDGENX.COM PIDGENX.C KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE PIDGENX.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    PIDGENX.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Registry Policy Reader

Purpose
Background Information
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source, Build Instructions and Demonstration

Purpose

Display the content of Registry Policy files in text format similar to that of Registry Editor script files, and optionally compare their contents against the machines’s or the (current) user’s Registry.

Background Information

Registry Policy files, typically created with the extension .pol, are used either to store the Registry keys and entries (to be) applied by Group Policies as well as Local Security Policies, or to restore the previous contents of Registry keys and entries modified by Group Policies as well as Local Security Policies.

The MSDN article Registry Policy File Format documents their format.

The MSKB article How to add, modify, or delete registry subkeys and values by using a .reg file documents the format of Registry Editor script files, typically created with the extension .reg.

Synopsis

POLYGLOT.COM [ /MACHINE | /USER ] ‹file name› …

Demonstration

Display the contents of some NTUser.pol and Registry.pol files that are (eventually) present on your machine:
VER
.\POLYGLOT.COM "%USERPROFILE%\NTUser.pol" "%ALLUSERSPROFILE%\NTUser.pol" "%SystemRoot%\System32\GroupPolicy\Machine\Registry.pol" "%SystemRoot%\System32\GroupPolicy\User\Registry.pol"
NET.EXE HelpMsg %ERRORLEVEL%
Microsoft Windows [Version 10.0.19044.2486]

Windows Registry Editor Version 5.00

; Registry Policy File 'C:\Users\Stefan\NTUser.pol'

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Group Policy Objects\Local Group Policy Objects]
'**Comment:GPO Name: Local Group Policy Objects'=

[HKEY_RELATIVE\Software\Microsoft\Windows\CurrentVersion\Policies\System]
'LogonHoursAction'=dword:00000002
'DontDisplayLogonHoursWarnings'=dword:00000001

Windows Registry Editor Version 5.00

; Registry Policy File 'C:\ProgramData\NTUser.pol'

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Group Policy Objects\Local Group Policy Objects]
'**Comment:GPO Name: Local Group Policy Objects'=

Windows Registry Editor Version 5.00

; Registry Policy File 'C:\Windows\System32\GroupPolicy\Machine\Registry.pol'

[HKEY_RELATIVE\Software\Policies\Microsoft\SystemCertificates\TrustedPublisher\Safer]
'AuthentiCodeFlags'=dword:00000300

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Safer\CodeIdentifiers]
'PolicyScope'=dword:00000001
'TransparentEnabled'=dword:00000002
'ExecutableTypes'=multi:'WSF','WSC','VBS','VBE','VB','TMP','SHS','SCR','PIF','PCD','OCX','MST','MSP','MSI','MDE','MDB','JSE','JS','ISP','INS','HTA','HLP','EXE','DLL','CRT','CPL','COM','CMD','BAT','BAS','AX','ADP','ADE'
'DefaultLevel'=dword:00000000
'Levels'=dword:00071000
'LogFileName'='C:\Windows\System32\LogFiles\SAFER.Log'
'AuthenticodeEnabled'=dword:00000001

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Safer\CodeIdentifiers\0\Hashes]
@=none:

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Safer\CodeIdentifiers\262144\Paths\{191cd7fa-f240-4a17-8986-94d480a6c8ca}]
'LastModified'=qword:01cf68d87b202417
'Description'=''
'SaferFlags'=dword:00000000
'ItemData'=expand:'%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%'

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Safer\CodeIdentifiers\262144\Paths\{d2c34ab2-529a-46b2-b293-fc853fce72ea}]
'LastModified'=qword:01cf68d87b202417
'Description'=''
'SaferFlags'=dword:00000000
'ItemData'=expand:'%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir%'

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Safer\CodeIdentifiers\262144\Paths\{4fcf2556-cf02-4356-ad71-f82ca93ccd0b}]
'LastModified'=qword:01cf68d979215214
'Description'=''
'SaferFlags'=dword:00000000
'ItemData'=expand:'%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir (x86)%'

[HKEY_RELATIVE\Software\Policies\Microsoft\Windows\Safer\CodeIdentifiers\262144\Paths\{21c0b260-2d89-4fe0-8275-1c76746b3d2b}]
'LastModified'=qword:01d57587bb48c5c4
'Description'=''
'SaferFlags'=dword:00000000
'ItemData'=expand:'%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramW6432Dir%'

CreateFile() returned error 3 for file 'C:\Windows\System32\GroupPolicy\User\Registry.pol'

The system cannot find the path specified.

Downloads

The console application is available in two functional identical forms: POLYGLOT.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and POLYGLOT.COM, a small form without these extras.

Implementation and Build Details

Registry Policy Reader is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source, Build Instructions and Demonstration

Perform the following two simple steps to build the console application Registry Policy Reader from the source presented hereafter.
  1. Create the text file POLYGLOT.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #define REGFILE_SIGNATURE	'geRP'
    #define REGISTRY_FILE_VERSION	1UL
    
    typedef	unsigned long long	QWORD, *LPQWORD;
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    const	LPCWSTR	szHKEY[8] = {L"HKEY_CLASSES_ROOT",
    		             L"HKEY_CURRENT_USER",
    		             L"HKEY_LOCAL_MACHINE",
    		             L"HKEY_USERS",
    		             L"HKEY_PERFORMANCE_DATA",
    		             L"HKEY_CURRENT_CONFIG",
    		             L"HKEY_DYN_DATA",
    		             L"HKEY_CURRENT_USER_LOCAL_SETTINGS"};
    
    const	LPCWSTR	szTYPE[12] = {L"NONE",
    		              L"SZ",
    		              L"EXPAND_SZ",
    		              L"BINARY",
    		              L"DWORD",		// alias DWORD_LITTLE_ENDIAN
    		              L"DWORD_BIG_ENDIAN",
    		              L"LINK",
    		              L"MULTI_SZ",
    		              L"RESOURCE_LIST",
    		              L"FULL_RESOURCE_DESCRIPTOR",
    		              L"RESOURCE_REQUIREMENTS_LIST",
    		              L"QWORD"};	// alias QWORD_LITTLE_ENDIAN
    
    const	LPCWSTR	szType[12] = {L"none:",
    		              L"",
    		              L"expand:",
    		              L"hex:",
    		              L"dword:",
    		              L"dword:",
    		              L"link:",
    		              L"multi:",
    		              L"hex(8):",
    		              L"hex(9):",
    		              L"hex(a):",
    		              L"qword:"};
    
    DWORD	WINAPI	Polyglot(HANDLE hConsole, HKEY hkHKEY, LPCWSTR lpArgument)
    {
    #ifdef REGISTRY
    	LPCWSTR	lpHKEY = szHKEY[(DWORD) hkHKEY ^ (DWORD) HKEY_CLASSES_ROOT];
    	HKEY	hkKey;
    	BYTE	cbData[65536];
    #endif
    	HANDLE	hInput;
    	DWORD	dwInput;
    	LPCWSTR	lpInput;
    	WCHAR	cwInput;
    	HANDLE	hPolicy;
    	DWORD	dwPolicy;
    	LPDWORD	lpPolicy;
    	LPCWSTR	lpKey, lpValue, lpData, lp;
    	DWORD	dwKey, dwValue, dwData, dwType, dwSize;
    	DWORD	dwError = ERROR_SUCCESS;
    
    	hInput = CreateFile(lpArgument,
    	                    FILE_READ_DATA,
    	                    FILE_SHARE_READ,
    	                    (LPSECURITY_ATTRIBUTES) NULL,
    	                    OPEN_EXISTING,
    	                    FILE_FLAG_SEQUENTIAL_SCAN,
    	                    (HANDLE) NULL);
    
    	if (hInput == INVALID_HANDLE_VALUE)
    		PrintConsole(hConsole,
    		             L"CreateFile() returned error %lu for file \'%ls\'\n",
    		             dwError = GetLastError(), lpArgument);
    	else
    	{
    		dwInput = GetFileSize(hInput, (LPDWORD) NULL);
    
    		if (dwInput == INVALID_FILE_SIZE)
    			PrintConsole(hConsole,
    			             L"GetFileSize() returned error %lu for file \'%ls\'\n",
    			             dwError = GetLastError(), lpArgument);
    		else
    		{
    			hPolicy = CreateFileMapping(hInput,
    			                            (LPSECURITY_ATTRIBUTES) NULL,
    			                            PAGE_READONLY,
    			                            0, 0,
    			                            (LPCWSTR) NULL);
    
    			if (hPolicy == NULL)
    				PrintConsole(hConsole,
    				             L"CreateFileMapping() returned error %lu for file \'%ls\'\n",
    				             dwError = GetLastError(), lpArgument);
    			else
    			{
    				lpPolicy = MapViewOfFile(hPolicy,
    				                         FILE_MAP_READ,
    				                         0, 0,
    				                         (SIZE_T) 0);
    
    				if (lpPolicy == NULL)
    					PrintConsole(hConsole,
    					             L"MapViewOfFile() returned error %lu for file \'%ls\'\n",
    					             dwError = GetLastError(), lpArgument);
    				else
    				{
    					if ((lpPolicy[0] != REGFILE_SIGNATURE)
    					 || (lpPolicy[1] != REGISTRY_FILE_VERSION))
    						PrintConsole(hConsole,
    						             L"Signature \'PReg\\1\\0\\0\\0\' missing in file \'%ls\'!\n",
    						             lpArgument);
    					else
    					{
    						PrintConsole(hConsole,
    						             L"Windows Registry Editor Version 5.00\n"
    						             L"\n"
    						             L"; Registry Policy File \'%ls\'\n",
    						             lpArgument);
    
    						// L'[' key L']'
    						// L'[' key L';'           value L';' type L';' size L';' data L']'
    						// L'[' key L';' L"**Del." value L';' type L';' size L';' data L']'
    						// L'[' key L';' L"**DeleteKeys" { L';' key } ... L']'
    						// L'[' key L';' L"**DeleteVals" L']'
    						// L'[' key L';' L"**DeleteValues" { L';' value } ... L']'
    						// L'[' key L';' L"**SecureKey=0" L']'
    						// L'[' key L';' L"**SecureKey=1" L']'
    						//
    						// WCHAR key[]    NUL-terminated path of registry key beneath
    						//                HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER
    						//
    						// WCHAR value[]  NUL-terminated name of registry entry
    						//
    						// DWORD type     registry data type
    						//
    						// DWORD size     size of registry data in bytes
    						//
    						// BYTE  data[]   registry data
    
    						lpInput = (LPCWSTR) (lpPolicy + 2);
    						lpKey = NULL;
    						dwKey = 0;
    						dwPolicy = dwInput;
    
    						while ((LPBYTE) lpInput < (LPBYTE) lpPolicy + dwPolicy)
    						{
    							if (*lpInput++ != L'[')
    								break;
    
    							dwInput = wcslen(lpInput);
    
    							if ((dwKey == 0)
    							 || (dwKey != dwInput)
    							 || (memcmp(lpInput, lpKey, dwKey * sizeof(L'\0')) != 0))
    								PrintConsole(hConsole,
    								             L"\n"
    								             L"[HKEY_RELATIVE\\%ls]\n",
    								             lpInput);
    
    							lpKey = lpInput;
    							dwKey = dwInput;
    							lpInput += dwInput + 1;
    							cwInput = *lpInput++;
    
    							if (cwInput == L']')
    								continue;
    
    							if (cwInput != L';')
    								break;
    
    							lpValue = lpInput;
    							dwValue = wcslen(lpInput);
    							lpInput += dwValue + 1;
    
    							if ((dwValue == sizeof("**securekey=1") - 1)
    							 && ((memcmp(lpValue, L"**securekey=1", sizeof(L"**securekey=1") - sizeof(L"")) == 0)
    							  || (memcmp(lpValue, L"**SecureKey=1", sizeof(L"**Securekey=1") - sizeof(L"")) == 0)))
    							{
    								PrintConsole(hConsole,
    								             L"; SecureKey=1\n");
    
    								if (*lpInput++ != L']')
    									break;
    							}
    							else if ((dwValue == sizeof("**securekey=0") - 1)
    							      && ((memcmp(lpValue, L"**securekey=0", sizeof(L"**securekey=0") - sizeof(L"")) == 0)
    							       || (memcmp(lpValue, L"**SecureKey=0", sizeof(L"**Securekey=0") - sizeof(L"")) == 0)))
    							{
    								PrintConsole(hConsole,
    								             L"; SecureKey=0\n");
    
    								if (*lpInput++ != L']')
    									break;
    							}
    							else if ((dwValue == sizeof("**deletevals") - 1)
    							      && ((memcmp(lpValue, L"**deletevals", sizeof(L"**deletevals") - sizeof(L"")) == 0)
    							       || (memcmp(lpValue, L"**Deletevals", sizeof(L"**Deletevals") - sizeof(L"")) == 0)))
    							{
    								PrintConsole(hConsole,
    								             L"*=-\n");
    
    								if (*lpInput++ != L']')
    									break;
    							}
    							else if ((dwValue == sizeof("**deletevalues") - 1)
    							      && ((memcmp(lpValue, L"**deletevalues", sizeof(L"**deletevalues") - sizeof(L"")) == 0)
    							       || (memcmp(lpValue, L"**Deletevalues", sizeof(L"**Deletevalues") - sizeof(L"")) == 0)))
    							{
    								while (*lpInput == L';')
    								{
    									PrintConsole(hConsole,
    									             L"\'%ls\'=-\n",
    									             ++lpInput);
    
    									lpInput += wcslen(lpInput) + 1;
    								}
    
    								if (*lpInput++ != L']')
    									break;
    							}
    							else if ((dwValue == sizeof("**deletekeys") - 1)
    							      && ((memcmp(lpValue, L"**deletekeys", sizeof(L"**deletekeys") - sizeof(L"")) == 0)
    							       || (memcmp(lpValue, L"**Deletekeys", sizeof(L"**Deletekeys") - sizeof(L"")) == 0)))
    							{
    								while (*lpInput == L';')
    								{
    									PrintConsole(hConsole,
    									             L"[-HKEY_RELATIVE\\%ls\\%ls]\n",
    									             lpKey, ++lpInput);
    
    									lpInput += wcslen(lpInput) + 1;
    								}
    
    								if (*lpInput++ != L']')
    									break;
    							}
    							else
    							{
    								if ((dwValue > sizeof("**del."))
    								 && ((memcmp(lpValue, L"**del.", sizeof(L"**del.") - sizeof(L"")) == 0)
    								  || (memcmp(lpValue, L"**Del.", sizeof(L"**Del.") - sizeof(L"")) == 0)))
    								{
    									lpValue += sizeof("**Del.") - 1;
    
    									if (dwValue == sizeof("**Del.") - 1)
    										PrintConsole(hConsole,
    										             L"@=- ; =");
    									else
    										PrintConsole(hConsole,
    										             L"\'%ls\'=- ; =", lpValue);
    								}
    								else
    									if (dwValue == 0)
    										PrintConsole(hConsole,
    										             L"@=");
    									else
    										PrintConsole(hConsole,
    										             L"\'%ls\'=", lpValue);
    
    								cwInput = *lpInput++;
    
    								if (cwInput == L']')
    									continue;
    
    								if (cwInput != L';')
    									break;
    
    								dwType = *((LPDWORD) lpInput)++;
    
    								if (dwType < sizeof(szType) / sizeof(*szType))
    									PrintConsole(hConsole,
    									             L"%ls", szType[dwType]);
    								else
    									PrintConsole(hConsole,
    									             L"hex(%lx):", dwType);
    
    								cwInput = *lpInput++;
    
    								if (cwInput == L']')
    									continue;
    
    								if (cwInput != L';')
    									break;
    
    								dwSize = *((LPDWORD) lpInput)++;
    
    								cwInput = *lpInput++;
    
    								if (cwInput == L']')
    									continue;
    
    								if (cwInput != L';')
    									break;
    
    								lpData = lpInput;
    								(LPBYTE) lpInput += dwSize;
    
    								switch (dwType)
    								{
    								case REG_SZ:
    								case REG_EXPAND_SZ:
    								case REG_LINK:
    
    									if (dwSize == 0)
    										goto NEWLINE;
    
    									PrintConsole(hConsole,
    									             L"\'%ls\'\n",
    									             lpData);
    
    									dwData = wcslen(lpData);
    
    									if (dwSize != (dwData + 1) * sizeof(L'\0'))
    										PrintConsole(hConsole,
    										             L"Size %lu of REG_%ls value data not equal length %lu of string plus terminating \'NUL\' character!\n",
    										             dwSize, szTYPE[dwType], dwData);
    									break;
    
    								case REG_DWORD_BIG_ENDIAN:
    
    									*(LPDWORD) lpData = _byteswap_ulong(*(LPDWORD) lpData);
    
    								case REG_DWORD_LITTLE_ENDIAN:
    							//	case REG_DWORD:
    
    									PrintConsole(hConsole,
    									             L"%08lx\n",
    									             *(LPDWORD) lpData);
    
    									if (dwSize != sizeof(DWORD))
    										PrintConsole(hConsole,
    										             L"Size %lu of REG_%ls value data not equal \'sizeof(DWORD)\'!\n",
    										             dwSize, szTYPE[dwType]);
    									break;
    
    								case REG_QWORD_LITTLE_ENDIAN:
    							//	case REG_QWORD:
    
    									PrintConsole(hConsole,
    									             L"%016I64x\n",
    									             *(LPQWORD) lpData);
    
    									if (dwSize != sizeof(QWORD))
    										PrintConsole(hConsole,
    										             L"Size %lu of REG_QWORD value data not equal \'sizeof(QWORD)\'!\n",
    										             dwSize);
    									break;
    
    								case REG_MULTI_SZ:
    
    									if (dwSize == 0)
    										goto NEWLINE;
    
    									for (lp = lpData; (lp < lpInput) && (*lp != L'\0'); lp += wcslen(lp) + 1)
    										PrintConsole(hConsole,
    										             L",\'%ls\'" + (lp == lpData),
    										             lp);
    
    									PrintConsole(hConsole,
    									             L"\n");
    
    									if ((lp > lpInput) || (*lp != L'\0'))
    										PrintConsole(hConsole,
    										             L"REG_MULTI_SZ value data not terminated with extra \'NUL\' character!\n");
    									else
    										lp++;
    
    									if (lp != lpInput)
    										PrintConsole(hConsole,
    										             L"Size %lu of REG_MULTI_SZ value data not equal sum of string lengths plus terminating \'NUL\' characters!\n",
    										             dwSize);
    									break;
    
    							//	case REG_NONE:
    							//	case REG_BINARY:
    							//	case REG_RESOURCE_LIST:
    							//	case REG_FULL_RESOURCE_DESCRIPTOR:
    							//	case REG_RESOURCE_REQUIREMENTS_LIST:
    								default:
    									for (lp = lpData; lp < lpInput; (LPBYTE) lp += 1)
    										PrintConsole(hConsole,
    										             L",%02x" + (lp == lpData),
    										             *(LPBYTE) lp);
    								NEWLINE:
    									PrintConsole(hConsole,
    									             L"\n");
    								}
    #ifdef REGISTRY
    								if (hkHKEY != HKEY_CLASSES_ROOT)
    								{
    									dwError = RegOpenKeyEx(hkHKEY,
    									                       lpKey,
    									                       REG_OPTION_RESERVED,
    									                       KEY_QUERY_VALUE,
    									                       &hkKey);
    
    									if (dwError != ERROR_SUCCESS)
    										PrintConsole(hConsole,
    										             L"RegOpenKeyEx() returned error %lu for registry key \'%ls\\%ls\'\n",
    										             dwError, lpHKEY, lpKey);
    									else
    									{
    										dwData = sizeof(cbData);
    
    										dwError = RegQueryValueEx(hkKey,
    										                          lpValue,
    										                          (LPDWORD) NULL,
    										                          &dwValue,
    										                          cbData,
    										                          &dwData);
    
    										if (dwError != ERROR_SUCCESS)
    											PrintConsole(hConsole,
    											             L"RegQueryValueEx() returned error %lu for value \'%ls\' of registry key \'%ls\\%ls\'\n",
    											             dwError, lpValue, lpHKEY, lpKey);
    										else
    											if ((dwValue != dwType)
    											 || (dwData != dwSize)
    											 || (memcmp(lpData, cbData, dwData) != 0))
    												PrintConsole(hConsole,
    												             L"MISMATCH: data type, size or value in policy file differs from registry!\n");
    
    										dwError = RegCloseKey(hkKey);
    
    										if (dwError != ERROR_SUCCESS)
    											PrintConsole(hConsole,
    											             L"RegCloseKey() returned error %lu for registry key \'%ls\\%ls\'\n",
    											             dwError, lpHKEY, lpKey);
    									}
    								}
    #endif // REGISTRY
    								if (*lpInput++ != L']')
    									break;
    							}
    						}
    
    						if ((LPBYTE) lpInput != (LPBYTE) lpPolicy + dwPolicy)
    							PrintConsole(hConsole,
    							             L"Format error in policy file \'%ls\'!\n",
    							             lpArgument);
    					}
    
    					if (!UnmapViewOfFile(lpPolicy))
    						PrintConsole(hConsole,
    						             L"UnmapViewOfFile() returned error %lu for file \'%ls\'\n",
    						             GetLastError(), lpArgument);
    				}
    
    				if (!CloseHandle(hPolicy))
    					PrintConsole(hConsole,
    					             L"CloseHandle() returned error %lu for file mapping \'%ls\'\n",
    					             GetLastError(), lpArgument);
    			}
    		}
    
    		if (!CloseHandle(hInput))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu for file \'%ls\'\n",
    			             GetLastError(), lpArgument);
    	}
    
    	return dwError;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    #ifdef WILDCARD
    	WIN32_FIND_DATA	wfd;
    
    	HANDLE	hArgument;
    	DWORD	dwArgument;
    	WCHAR	szArgument[32768];
    	LPWSTR	lpArgument;
    #endif
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 1;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	HKEY	hkHKEY = HKEY_CLASSES_ROOT;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    #ifdef REGISTRY
    			if ((nArguments > 1)
    			 && (*lpArguments[1] == L'/'))
    #if 0
    				if (wcscmp(lpArguments[1], L"/MACHINE") == 0)
    #elif 0
    				if (wmemcmp(lpArguments[1], L"/MACHINE", sizeof("/MACHINE")) == 0)
    #else
    				if (memcmp(lpArguments[1], L"/MACHINE", sizeof(L"/MACHINE")) == 0)
    #endif
    				{
    					hkHKEY = HKEY_LOCAL_MACHINE;
    					nArgument = 2;
    				}
    #if 0
    				else if (wcscmp(lpArguments[1], L"/USER") == 0)
    #elif 0
    				else if (wmemcmp(lpArguments[1], L"/USER", sizeof("/USER")) == 0)
    #else
    				else if (memcmp(lpArguments[1], L"/USER", sizeof(L"/USER")) == 0)
    #endif
    				{
    					hkHKEY = HKEY_CURRENT_USER;
    					nArgument = 2;
    				}
    				else
    				{
    					PrintConsole(hConsole,
    					             L"Bad arguments: optional first argument must be \'%ls\' or \'%ls\'!\n",
    					             L"/MACHINE", L"/USER");
    					nArguments = 0;
    				}
    
    			if (nArguments <= nArgument)
    #else
    			if (nArguments < 2)
    #endif
    				PrintConsole(hConsole,
    				             L"No arguments: at least one \'.pol\' file name must be given!\n");
    			else
    #ifndef WILDCARD
    				do
    					dwError = Polyglot(hConsole, hkHKEY, lpArguments[nArgument]);
    				while (++nArgument < nArguments);
    #else
    				do
    				{
    					hArgument = FindFirstFile(lpArguments[nArgument], &wfd);
    
    					if (hArgument == INVALID_HANDLE_VALUE)
    						PrintConsole(hConsole,
    						             L"FindFirstFile() returned error %lu for argument \'%ls\'\n",
    						             dwError = GetLastError(), lpArguments[nArgument]);
    					else
    					{
    						dwArgument = 0;
    						lpArgument = NULL;
    
    						do
    						{
    							szArgument[dwArgument] = lpArguments[nArgument][dwArgument];
    
    							if (szArgument[dwArgument] == L'\\')
    								lpArgument = szArgument + dwArgument;
    						}
    						while (szArgument[dwArgument++] != L'\0');
    
    						if (dwArgument > MAX_PATH)
    							PrintConsole(hConsole,
    							             L"Argument \'%ls\' exceeds MAX_PATH!\n",
    							             lpArguments[nArgument]);
    
    						if (lpArgument != NULL)
    							lpArgument++;
    						else
    							lpArgument = szArgument + 2 * (szArgument[1] == L':');
    
    						dwArgument = 0;
    
    						do
    						{
    							if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
    								continue;
    
    							dwArgument++;
    
    							wcscpy(lpArgument, wfd.cFileName);
    
    							dwError = Polyglot(hConsole, hkHKEY, szArgument);
    						}
    						while (FindNextFile(hArgument, &wfd));
    
    						dwError = GetLastError();
    
    						if (dwError == ERROR_NO_MORE_FILES)
    							dwError = ERROR_SUCCESS;
    						else
    							PrintConsole(hConsole,
    							             L"FindNextFile() returned error %lu for argument \'%ls\'\n",
    							             dwError, lpArguments[nArgument]);
    
    						if (dwArgument == 0)
    							PrintConsole(hConsole,
    							             L"No wildcard match for argument \'%ls\'!\n",
    							             lpArguments[nArgument]);
    
    						if (!FindClose(hArgument))
    							PrintConsole(hConsole,
    							             L"FindClose() returned error %lu for argument \'%ls\'\n",
    							             GetLastError(), lpArguments[nArgument]);
    					}
    				} while (++nArgument < nArguments);
    #endif // WILDCARD
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
    Note: with the preprocessor macro REGISTRY defined, an optional /MACHINE or /USER is accepted as first command line argument to compare the settings against the HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER branch of the Registry!

    Note: with the preprocessor macro WILDCARD defined, wildcard expansion of matching file names is performed for the command line arguments!

  2. Run the following four command lines to compile the source file POLYGLOT.C created in step 1., link the compiled object file POLYGLOT.OBJ and cleanup afterwards:

    SET CL=/DREGISTRY /GAFS /Gs69632 /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /STACK:1048576,65536 /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FePOLYGLOT.COM POLYGLOT.C ADVAPI32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE POLYGLOT.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    POLYGLOT.C
    POLYGLOT.C(313) : warning C4213: nonstandard extension used : cast on l-value
    POLYGLOT.C(330) : warning C4213: nonstandard extension used : cast on l-value
    POLYGLOT.C(341) : warning C4213: nonstandard extension used : cast on l-value
    POLYGLOT.C(425) : warning C4213: nonstandard extension used : cast on l-value
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Offline Registry Reader

Purpose
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Print an offline registry hive formatted as .inf file in UTF-16LE encoding on standard output (which must be redirected to a file or piped into an application that reads from standard input, like Clip, Find or More).

Synopsis

OFFREG.COM ‹input file name› >‹output file name›
OFFREG.COM ‹input file name› | CLIP.COM
OFFREG.COM ‹input file name› | MORE.COM

Demonstration

Dump the contents of the registry hive %SystemDrive%\Users\Default\NTUSER.DAT to the file ntuser.inf and display it afterwards:
VER
.\OFFREG.COM "%SystemDrive%\Users\Default\NTUSER.DAT" 1>ntuser.inf
NET.EXE HelpMsg %ERRORLEVEL%
TYPE ntuser.inf
Microsoft Windows [Version 10.0.19044.2486]

OFFREG.DLL version 1.0

The operation completed successfully.

[Version]
DriverVer = 08/15/2021,12.34.56.789 ; UTC
Provider  = "Stefan Kanthak"
Signature = "$Windows NT$"

[Strings]
REG_SZ                         = 0x00000000
REG_BINARY                     = 0x00000001
REG_KEYONLY                    = 0x00000010
REG_MULTI_SZ                   = 0x00010000
REG_DWORD                      = 0x00010001
REG_EXPAND_SZ                  = 0x00020000
REG_NONE                       = 0x00020001
REG_COMPATIBLE                 = 0x00030001 ; same as REG_BINARY
REG_DWORD_LITTLE_ENDIAN        = 0x00040001 ; same as REG_DWORD
REG_DWORD_BIG_ENDIAN           = 0x00050001
REG_LINK                       = 0x00060000
REG_RESOURCE_LIST              = 0x00080001
REG_FULL_RESOURCE_DESCRIPTOR   = 0x00090001
REG_RESOURCE_REQUIREMENTS_LIST = 0x000a0001
REG_QWORD                      = 0x000b0001
REG_QWORD_LITTLE_ENDIAN        = 0x000b0001 ; same as REG_QWORD

[DefaultInstall.NT]
;AddReg = AddReg.HKO

[AddReg.HKO]
HKO,"AppEvents\EventLabels\.Default",,%REG_SZ%,"Default Beep"
HKO,"AppEvents\EventLabels\.Default","DispFileName",%REG_SZ%,"@mmres.dll,-5824"
HKO,"AppEvents\EventLabels\ActivatingDocument",,%REG_SZ%,"Complete Navigation"
HKO,"AppEvents\EventLabels\ActivatingDocument","DispFileName",%REG_SZ%,"@ieframe.dll,-10321"
HKO,"AppEvents\EventLabels\AppGPFault",,%REG_SZ%,"Program Error"
HKO,"AppEvents\EventLabels\AppGPFault","DispFileName",%REG_SZ%,"@mmres.dll,-5825"
HKO,"AppEvents\EventLabels\BlockedPopup",,%REG_SZ%,"Blocked Pop-up Window"
HKO,"AppEvents\EventLabels\BlockedPopup","DispFileName",%REG_SZ%,"@ieframe.dll,-10325"
HKO,"AppEvents\EventLabels\CCSelect",,%REG_SZ%,"Select"
HKO,"AppEvents\EventLabels\CCSelect","DispFileName",%REG_SZ%,"@ieframe.dll,-10323"
HKO,"AppEvents\EventLabels\ChangeTheme",,%REG_SZ%,"Change Theme"
HKO,"AppEvents\EventLabels\ChangeTheme","DispFileName",%REG_SZ%,"@mmres.dll,-5860"
HKO,"AppEvents\EventLabels\Close",,%REG_SZ%,"Close Program"
HKO,"AppEvents\EventLabels\Close","DispFileName",%REG_SZ%,"@mmres.dll,-5826"
HKO,"AppEvents\EventLabels\CriticalBatteryAlarm",,%REG_SZ%,"Critical Battery Alarm"
HKO,"AppEvents\EventLabels\CriticalBatteryAlarm","DispFileName",%REG_SZ%,"@mmres.dll,-5827"
HKO,"AppEvents\EventLabels\DeviceConnect",,%REG_SZ%,"Device Connect"
HKO,"AppEvents\EventLabels\DeviceConnect","DispFileName",%REG_SZ%,"@mmres.dll,-5828"
HKO,"AppEvents\EventLabels\DeviceDisconnect",,%REG_SZ%,"Device Disconnect"
HKO,"AppEvents\EventLabels\DeviceDisconnect","DispFileName",%REG_SZ%,"@mmres.dll,-5829"
HKO,"AppEvents\EventLabels\DeviceFail",,%REG_SZ%,"Device Failed to Connect"
HKO,"AppEvents\EventLabels\DeviceFail","DispFileName",%REG_SZ%,"@mmres.dll,-5830"
HKO,"AppEvents\EventLabels\DisNumbersSound",,%REG_SZ%,"Disambiguation Numbers"
HKO,"AppEvents\EventLabels\DisNumbersSound","DispFileName",%REG_SZ%,"@C:\Windows\System32\speech\speechux\sapi.cpl,-5566"
HKO,"AppEvents\EventLabels\EmptyRecycleBin",,%REG_SZ%,"Empty Recycle Bin"
HKO,"AppEvents\EventLabels\EmptyRecycleBin","DispFileName",%REG_SZ%,"@mmres.dll,-5831"
HKO,"AppEvents\EventLabels\FaxBeep",,%REG_SZ%,"New Fax Notification"
HKO,"AppEvents\EventLabels\FaxBeep","DispFileName",%REG_SZ%,"@mmres.dll,-5858"
HKO,"AppEvents\EventLabels\FeedDiscovered",,%REG_SZ%,"Feed Discovered"
HKO,"AppEvents\EventLabels\FeedDiscovered","DispFileName",%REG_SZ%,"@ieframe.dll,-17315"
HKO,"AppEvents\EventLabels\HubOffSound",,%REG_SZ%,"Off"
HKO,"AppEvents\EventLabels\HubOffSound","DispFileName",%REG_SZ%,"@C:\Windows\System32\speech\speechux\sapi.cpl,-5563"
HKO,"AppEvents\EventLabels\HubOnSound",,%REG_SZ%,"On"
HKO,"AppEvents\EventLabels\HubOnSound","DispFileName",%REG_SZ%,"@C:\Windows\System32\speech\speechux\sapi.cpl,-5562"
HKO,"AppEvents\EventLabels\HubSleepSound",,%REG_SZ%,"Sleep"
HKO,"AppEvents\EventLabels\HubSleepSound","DispFileName",%REG_SZ%,"@C:\Windows\System32\speech\speechux\sapi.cpl,-5564"
HKO,"AppEvents\EventLabels\LowBatteryAlarm",,%REG_SZ%,"Low Battery Alarm"
HKO,"AppEvents\EventLabels\LowBatteryAlarm","DispFileName",%REG_SZ%,"@mmres.dll,-5832"
HKO,"AppEvents\EventLabels\MailBeep",,%REG_SZ%,"Desktop Mail Notification"
HKO,"AppEvents\EventLabels\MailBeep","DispFileName",%REG_SZ%,"@mmres.dll,-5837"
HKO,"AppEvents\EventLabels\Maximize",,%REG_SZ%,"Maximize"
HKO,"AppEvents\EventLabels\Maximize","DispFileName",%REG_SZ%,"@mmres.dll,-5833"
HKO,"AppEvents\EventLabels\MenuCommand",,%REG_SZ%,"Menu Command"
HKO,"AppEvents\EventLabels\MenuCommand","DispFileName",%REG_SZ%,"@mmres.dll,-5834"
HKO,"AppEvents\EventLabels\MenuPopup",,%REG_SZ%,"Menu Pop-up"
HKO,"AppEvents\EventLabels\MenuPopup","DispFileName",%REG_SZ%,"@mmres.dll,-5835"
HKO,"AppEvents\EventLabels\MessageNudge",,%REG_SZ%,"Message Nudge"
HKO,"AppEvents\EventLabels\MessageNudge","DispFileName",%REG_SZ%,"@mmres.dll,-5866"
HKO,"AppEvents\EventLabels\Minimize",,%REG_SZ%,"Minimize"
HKO,"AppEvents\EventLabels\Minimize","DispFileName",%REG_SZ%,"@mmres.dll,-5836"
HKO,"AppEvents\EventLabels\MisrecoSound",,%REG_SZ%,"Misrecognition"
HKO,"AppEvents\EventLabels\MisrecoSound","DispFileName",%REG_SZ%,"@C:\Windows\System32\speech\speechux\sapi.cpl,-5561"
HKO,"AppEvents\EventLabels\MoveMenuItem",,%REG_SZ%,"Move Menu Item"
HKO,"AppEvents\EventLabels\MoveMenuItem","DispFileName",%REG_SZ%,"@ieframe.dll,-10322"
HKO,"AppEvents\EventLabels\Navigating",,%REG_SZ%,"Start Navigation"
HKO,"AppEvents\EventLabels\Navigating","DispFileName",%REG_SZ%,"@ieframe.dll,-10320"
HKO,"AppEvents\EventLabels\Notification.Default",,%REG_SZ%,"Notification"
HKO,"AppEvents\EventLabels\Notification.Default","DispFileName",%REG_SZ%,"@mmres.dll,-5865"
HKO,"AppEvents\EventLabels\Notification.IM",,%REG_SZ%,"Instant Message Notification"
HKO,"AppEvents\EventLabels\Notification.IM","DispFileName",%REG_SZ%,"@mmres.dll,-5863"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm",,%REG_SZ%,"Alarm 1"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm","DispFileName",%REG_SZ%,"@mmres.dll,-5888"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm10",,%REG_SZ%,"Alarm 10"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm10","DispFileName",%REG_SZ%,"@mmres.dll,-5897"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm10","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm2",,%REG_SZ%,"Alarm 2"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm2","DispFileName",%REG_SZ%,"@mmres.dll,-5889"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm2","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm3",,%REG_SZ%,"Alarm 3"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm3","DispFileName",%REG_SZ%,"@mmres.dll,-5890"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm3","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm4",,%REG_SZ%,"Alarm 4"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm4","DispFileName",%REG_SZ%,"@mmres.dll,-5891"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm4","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm5",,%REG_SZ%,"Alarm 5"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm5","DispFileName",%REG_SZ%,"@mmres.dll,-5892"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm5","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm6",,%REG_SZ%,"Alarm 6"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm6","DispFileName",%REG_SZ%,"@mmres.dll,-5893"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm6","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm7",,%REG_SZ%,"Alarm 7"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm7","DispFileName",%REG_SZ%,"@mmres.dll,-5894"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm7","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm8",,%REG_SZ%,"Alarm 8"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm8","DispFileName",%REG_SZ%,"@mmres.dll,-5895"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm8","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm9",,%REG_SZ%,"Alarm 9"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm9","DispFileName",%REG_SZ%,"@mmres.dll,-5896"
HKO,"AppEvents\EventLabels\Notification.Looping.Alarm9","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call",,%REG_SZ%,"Incoming Call Notification 1"
HKO,"AppEvents\EventLabels\Notification.Looping.Call","DispFileName",%REG_SZ%,"@mmres.dll,-5872"
HKO,"AppEvents\EventLabels\Notification.Looping.Call","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call10",,%REG_SZ%,"Incoming Call Notification 10"
HKO,"AppEvents\EventLabels\Notification.Looping.Call10","DispFileName",%REG_SZ%,"@mmres.dll,-5881"
HKO,"AppEvents\EventLabels\Notification.Looping.Call10","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call2",,%REG_SZ%,"Incoming Call Notification 2"
HKO,"AppEvents\EventLabels\Notification.Looping.Call2","DispFileName",%REG_SZ%,"@mmres.dll,-5873"
HKO,"AppEvents\EventLabels\Notification.Looping.Call2","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call3",,%REG_SZ%,"Incoming Call Notification 3"
HKO,"AppEvents\EventLabels\Notification.Looping.Call3","DispFileName",%REG_SZ%,"@mmres.dll,-5874"
HKO,"AppEvents\EventLabels\Notification.Looping.Call3","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call4",,%REG_SZ%,"Incoming Call Notification 4"
HKO,"AppEvents\EventLabels\Notification.Looping.Call4","DispFileName",%REG_SZ%,"@mmres.dll,-5875"
HKO,"AppEvents\EventLabels\Notification.Looping.Call4","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call5",,%REG_SZ%,"Incoming Call Notification 5"
HKO,"AppEvents\EventLabels\Notification.Looping.Call5","DispFileName",%REG_SZ%,"@mmres.dll,-5876"
HKO,"AppEvents\EventLabels\Notification.Looping.Call5","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call6",,%REG_SZ%,"Incoming Call Notification 6"
HKO,"AppEvents\EventLabels\Notification.Looping.Call6","DispFileName",%REG_SZ%,"@mmres.dll,-5877"
HKO,"AppEvents\EventLabels\Notification.Looping.Call6","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call7",,%REG_SZ%,"Incoming Call Notification 7"
HKO,"AppEvents\EventLabels\Notification.Looping.Call7","DispFileName",%REG_SZ%,"@mmres.dll,-5878"
HKO,"AppEvents\EventLabels\Notification.Looping.Call7","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call8",,%REG_SZ%,"Incoming Call Notification 8"
HKO,"AppEvents\EventLabels\Notification.Looping.Call8","DispFileName",%REG_SZ%,"@mmres.dll,-5879"
HKO,"AppEvents\EventLabels\Notification.Looping.Call8","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Looping.Call9",,%REG_SZ%,"Incoming Call Notification 9"
HKO,"AppEvents\EventLabels\Notification.Looping.Call9","DispFileName",%REG_SZ%,"@mmres.dll,-5880"
HKO,"AppEvents\EventLabels\Notification.Looping.Call9","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\Notification.Mail",,%REG_SZ%,"New Mail Notification"
HKO,"AppEvents\EventLabels\Notification.Mail","DispFileName",%REG_SZ%,"@mmres.dll,-5861"
HKO,"AppEvents\EventLabels\Notification.Proximity",,%REG_SZ%,"NFP Completion"
HKO,"AppEvents\EventLabels\Notification.Proximity","DispFileName",%REG_SZ%,"@mmres.dll,-5868"
HKO,"AppEvents\EventLabels\Notification.Reminder",,%REG_SZ%,"Calendar Reminder"
HKO,"AppEvents\EventLabels\Notification.Reminder","DispFileName",%REG_SZ%,"@mmres.dll,-5864"
HKO,"AppEvents\EventLabels\Notification.SMS",,%REG_SZ%,"New Text Message Notification"
HKO,"AppEvents\EventLabels\Notification.SMS","DispFileName",%REG_SZ%,"@mmres.dll,-5862"
HKO,"AppEvents\EventLabels\Open",,%REG_SZ%,"Open Program"
HKO,"AppEvents\EventLabels\Open","DispFileName",%REG_SZ%,"@mmres.dll,-5839"
HKO,"AppEvents\EventLabels\PanelSound",,%REG_SZ%,"Disambiguation Panel"
HKO,"AppEvents\EventLabels\PanelSound","DispFileName",%REG_SZ%,"@C:\Windows\System32\speech\speechux\sapi.cpl,-5565"
HKO,"AppEvents\EventLabels\PrintComplete",,%REG_SZ%,"Print Complete"
HKO,"AppEvents\EventLabels\PrintComplete","DispFileName",%REG_SZ%,"@mmres.dll,-5840"
HKO,"AppEvents\EventLabels\ProximityConnection",,%REG_SZ%,"NFP Connection"
HKO,"AppEvents\EventLabels\ProximityConnection","DispFileName",%REG_SZ%,"@mmres.dll,-5867"
HKO,"AppEvents\EventLabels\RestoreDown",,%REG_SZ%,"Restore Down"
HKO,"AppEvents\EventLabels\RestoreDown","DispFileName",%REG_SZ%,"@mmres.dll,-5841"
HKO,"AppEvents\EventLabels\RestoreUp",,%REG_SZ%,"Restore Up"
HKO,"AppEvents\EventLabels\RestoreUp","DispFileName",%REG_SZ%,"@mmres.dll,-5842"
HKO,"AppEvents\EventLabels\SecurityBand",,%REG_SZ%,"Information Bar"
HKO,"AppEvents\EventLabels\SecurityBand","DispFileName",%REG_SZ%,"@ieframe.dll,-10326"
HKO,"AppEvents\EventLabels\ShowBand",,%REG_SZ%,"Show Toolbar Band"
HKO,"AppEvents\EventLabels\ShowBand","DispFileName",%REG_SZ%,"@ieframe.dll,-10324"
HKO,"AppEvents\EventLabels\SystemAsterisk",,%REG_SZ%,"Asterisk"
HKO,"AppEvents\EventLabels\SystemAsterisk","DispFileName",%REG_SZ%,"@mmres.dll,-5843"
HKO,"AppEvents\EventLabels\SystemExclamation",,%REG_SZ%,"Exclamation"
HKO,"AppEvents\EventLabels\SystemExclamation","DispFileName",%REG_SZ%,"@mmres.dll,-5845"
HKO,"AppEvents\EventLabels\SystemExit",,%REG_SZ%,"Exit Windows"
HKO,"AppEvents\EventLabels\SystemExit","DispFileName",%REG_SZ%,"@mmres.dll,-5846"
HKO,"AppEvents\EventLabels\SystemExit","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\SystemHand",,%REG_SZ%,"Critical Stop"
HKO,"AppEvents\EventLabels\SystemHand","DispFileName",%REG_SZ%,"@mmres.dll,-5847"
HKO,"AppEvents\EventLabels\SystemNotification",,%REG_SZ%,"System Notification"
HKO,"AppEvents\EventLabels\SystemNotification","DispFileName",%REG_SZ%,"@mmres.dll,-5848"
HKO,"AppEvents\EventLabels\SystemQuestion",,%REG_SZ%,"Question"
HKO,"AppEvents\EventLabels\SystemQuestion","DispFileName",%REG_SZ%,"@mmres.dll,-5849"
HKO,"AppEvents\EventLabels\WindowsLogoff",,%REG_SZ%,"Windows Logoff"
HKO,"AppEvents\EventLabels\WindowsLogoff","DispFileName",%REG_SZ%,"@mmres.dll,-5852"
HKO,"AppEvents\EventLabels\WindowsLogoff","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\WindowsLogon",,%REG_SZ%,"Windows Logon"
HKO,"AppEvents\EventLabels\WindowsLogon","DispFileName",%REG_SZ%,"@mmres.dll,-5853"
HKO,"AppEvents\EventLabels\WindowsLogon","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\EventLabels\WindowsUAC",,%REG_SZ%,"Windows User Account Control"
HKO,"AppEvents\EventLabels\WindowsUAC","DispFileName",%REG_SZ%,"@mmres.dll,-5859"
HKO,"AppEvents\EventLabels\WindowsUnlock",,%REG_SZ%,"Windows Unlock"
HKO,"AppEvents\EventLabels\WindowsUnlock","DispFileName",%REG_SZ%,"@mmres.dll,-5869"
HKO,"AppEvents\EventLabels\WindowsUnlock","ExcludeFromCPL",%REG_DWORD%,1 ; 0x00000001
HKO,"AppEvents\Schemes",,%REG_SZ%,".Default"
HKO,"AppEvents\Schemes\Apps\.Default",,%REG_SZ%,"Windows"
HKO,"AppEvents\Schemes\Apps\.Default","DispFileName",%REG_SZ%,"@mmres.dll,-5856"
HKO,"AppEvents\Schemes\Apps\.Default\.Default\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\.Default\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\AppGPFault\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\AppGPFault\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\CCSelect",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\ChangeTheme\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\ChangeTheme\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\Close\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\Close\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\CriticalBatteryAlarm\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Foreground.wav"
HKO,"AppEvents\Schemes\Apps\.Default\CriticalBatteryAlarm\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Foreground.wav"
HKO,"AppEvents\Schemes\Apps\.Default\DeviceConnect\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Hardware Insert.wav"
HKO,"AppEvents\Schemes\Apps\.Default\DeviceConnect\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Hardware Insert.wav"
HKO,"AppEvents\Schemes\Apps\.Default\DeviceDisconnect\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Hardware Remove.wav"
HKO,"AppEvents\Schemes\Apps\.Default\DeviceDisconnect\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Hardware Remove.wav"
HKO,"AppEvents\Schemes\Apps\.Default\DeviceFail\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Hardware Fail.wav"
HKO,"AppEvents\Schemes\Apps\.Default\DeviceFail\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Hardware Fail.wav"
HKO,"AppEvents\Schemes\Apps\.Default\FaxBeep\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Email.wav"
HKO,"AppEvents\Schemes\Apps\.Default\FaxBeep\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Email.wav"
HKO,"AppEvents\Schemes\Apps\.Default\LowBatteryAlarm\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\LowBatteryAlarm\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\MailBeep\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Email.wav"
HKO,"AppEvents\Schemes\Apps\.Default\MailBeep\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Email.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Maximize\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\Maximize\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\MenuCommand\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\MenuCommand\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\MenuPopup\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\MenuPopup\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\MessageNudge\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Message Nudge.wav"
HKO,"AppEvents\Schemes\Apps\.Default\MessageNudge\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Message Nudge.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Minimize\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\Minimize\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Default\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify System Generic.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Default\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify System Generic.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.IM\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Messaging.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.IM\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Messaging.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm01.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm01.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm10\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm10.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm10\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm10.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm2\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm02.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm2\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm02.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm3\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm03.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm3\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm03.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm4\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm04.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm4\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm04.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm5\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm05.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm5\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm05.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm6\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm06.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm6\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm06.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm7\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm07.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm7\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm07.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm8\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm08.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm8\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm08.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm9\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm09.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Alarm9\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Alarm09.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring01.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring01.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call10\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring10.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call10\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring10.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call2\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring02.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call2\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring02.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call3\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring03.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call3\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring03.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call4\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring04.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call4\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring04.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call5\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring05.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call5\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring05.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call6\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring06.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call6\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring06.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call7\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring07.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call7\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring07.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call8\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring08.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call8\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring08.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call9\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring09.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Looping.Call9\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Ring09.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Mail\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Email.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Mail\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Email.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Proximity\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Proximity Notification.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Proximity\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Proximity Notification.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Reminder\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Calendar.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.Reminder\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Calendar.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.SMS\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Messaging.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Notification.SMS\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Notify Messaging.wav"
HKO,"AppEvents\Schemes\Apps\.Default\Open\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\Open\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\PrintComplete\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\PrintComplete\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\ProximityConnection\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Proximity Connection.wav"
HKO,"AppEvents\Schemes\Apps\.Default\ProximityConnection\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Proximity Connection.wav"
HKO,"AppEvents\Schemes\Apps\.Default\RestoreDown\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\RestoreDown\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\RestoreUp\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\RestoreUp\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\ShowBand",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\SystemAsterisk\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemAsterisk\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemExclamation\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemExclamation\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemExit\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\SystemExit\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\SystemHand\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Foreground.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemHand\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Foreground.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemNotification\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemNotification\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Background.wav"
HKO,"AppEvents\Schemes\Apps\.Default\SystemQuestion\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\SystemQuestion\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\WindowsLogoff\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\WindowsLogoff\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\.Default\WindowsLogon\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Logon.wav"
HKO,"AppEvents\Schemes\Apps\.Default\WindowsLogon\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Logon.wav"
HKO,"AppEvents\Schemes\Apps\.Default\WindowsUAC\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows User Account Control.wav"
HKO,"AppEvents\Schemes\Apps\.Default\WindowsUAC\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows User Account Control.wav"
HKO,"AppEvents\Schemes\Apps\.Default\WindowsUnlock\.Current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Unlock.wav"
HKO,"AppEvents\Schemes\Apps\.Default\WindowsUnlock\.Default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Windows Unlock.wav"
HKO,"AppEvents\Schemes\Apps\Explorer",,%REG_SZ%,"File Explorer"
HKO,"AppEvents\Schemes\Apps\Explorer","DispFileName",%REG_SZ%,"@mmres.dll,-5854"
HKO,"AppEvents\Schemes\Apps\Explorer\ActivatingDocument",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\BlockedPopup\.current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\BlockedPopup\.default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\EmptyRecycleBin\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\EmptyRecycleBin\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\FeedDiscovered\.current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\FeedDiscovered\.default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\MoveMenuItem",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\Navigating\.Current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\Navigating\.Default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\SecurityBand\.current",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\Explorer\SecurityBand\.default",,%REG_KEYONLY%
HKO,"AppEvents\Schemes\Apps\sapisvr",,%REG_SZ%,"Speech Recognition"
HKO,"AppEvents\Schemes\Apps\sapisvr","DispFileName",%REG_SZ%,"@C:\Windows\System32\speech\speechux\sapi.cpl,-5555"
HKO,"AppEvents\Schemes\Apps\sapisvr\DisNumbersSound\.current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Disambiguation.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\DisNumbersSound\.default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Disambiguation.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\HubOffSound\.current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Off.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\HubOffSound\.default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Off.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\HubOnSound\.current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech On.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\HubOnSound\.default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech On.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\HubSleepSound\.current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Sleep.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\HubSleepSound\.default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Sleep.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\MisrecoSound\.current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Misrecognition.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\MisrecoSound\.default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Misrecognition.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\PanelSound\.current",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Disambiguation.wav"
HKO,"AppEvents\Schemes\Apps\sapisvr\PanelSound\.default",,%REG_EXPAND_SZ%,"%%SystemRoot%%\media\Speech Disambiguation.wav"
HKO,"AppEvents\Schemes\Names\.Default",,%REG_SZ%,"@mmres.dll,-800"
HKO,"AppEvents\Schemes\Names\.None",,%REG_SZ%,"@mmres.dll,-801"
HKO,"Console","ColorTable00",%REG_DWORD%,789516 ; 0x000c0c0c
HKO,"Console","ColorTable01",%REG_DWORD%,14300928 ; 0x00da3700
HKO,"Console","ColorTable02",%REG_DWORD%,958739 ; 0x000ea113
HKO,"Console","ColorTable03",%REG_DWORD%,14521914 ; 0x00dd963a
HKO,"Console","ColorTable04",%REG_DWORD%,2035653 ; 0x001f0fc5
HKO,"Console","ColorTable05",%REG_DWORD%,9967496 ; 0x00981788
HKO,"Console","ColorTable06",%REG_DWORD%,40129 ; 0x00009cc1
HKO,"Console","ColorTable07",%REG_DWORD%,13421772 ; 0x00cccccc
HKO,"Console","ColorTable08",%REG_DWORD%,7763574 ; 0x00767676
HKO,"Console","ColorTable09",%REG_DWORD%,16742459 ; 0x00ff783b
HKO,"Console","ColorTable10",%REG_DWORD%,837142 ; 0x000cc616
HKO,"Console","ColorTable11",%REG_DWORD%,14079585 ; 0x00d6d661
HKO,"Console","ColorTable12",%REG_DWORD%,5654759 ; 0x005648e7
HKO,"Console","ColorTable13",%REG_DWORD%,10354868 ; 0x009e00b4
HKO,"Console","ColorTable14",%REG_DWORD%,10875385 ; 0x00a5f1f9
HKO,"Console","ColorTable15",%REG_DWORD%,15921906 ; 0x00f2f2f2
HKO,"Console","CtrlKeyShortcutsDisabled",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","CursorColor",%REG_DWORD%,4294967295 ; 0xffffffff
HKO,"Console","CursorSize",%REG_DWORD%,25 ; 0x00000019
HKO,"Console","DefaultBackground",%REG_DWORD%,4294967295 ; 0xffffffff
HKO,"Console","DefaultForeground",%REG_DWORD%,4294967295 ; 0xffffffff
HKO,"Console","EnableColorSelection",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","ExtendedEditKey",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","ExtendedEditKeyCustom",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","FaceName",%REG_SZ%,"__DefaultTTFont__"
HKO,"Console","FilterOnPaste",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","FontFamily",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","FontSize",%REG_DWORD%,1048576 ; 0x00100000
HKO,"Console","FontWeight",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","ForceV2",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","FullScreen",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","HistoryBufferSize",%REG_DWORD%,50 ; 0x00000032
HKO,"Console","HistoryNoDup",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","InsertMode",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","LineSelection",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","LineWrap",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","LoadConIme",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","NumberOfHistoryBuffers",%REG_DWORD%,4 ; 0x00000004
HKO,"Console","PopupColors",%REG_DWORD%,245 ; 0x000000f5
HKO,"Console","QuickEdit",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","ScreenBufferSize",%REG_DWORD%,589889656 ; 0x23290078
HKO,"Console","ScreenColors",%REG_DWORD%,7 ; 0x00000007
HKO,"Console","ScrollScale",%REG_DWORD%,1 ; 0x00000001
HKO,"Console","TerminalScrolling",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","TrimLeadingZeros",%REG_DWORD%,0 ; 0x00000000
HKO,"Console","WindowAlpha",%REG_DWORD%,255 ; 0x000000ff
HKO,"Console","WindowSize",%REG_DWORD%,1966200 ; 0x001e0078
HKO,"Console","WordDelimiters",%REG_DWORD%,0 ; 0x00000000
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","ColorTable05",%REG_DWORD%,5645313 ; 0x00562401
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","ColorTable06",%REG_DWORD%,15789550 ; 0x00f0edee
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","FaceName",%REG_SZ%,"Lucida Console"
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","FontFamily",%REG_DWORD%,54 ; 0x00000036
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","FontWeight",%REG_DWORD%,400 ; 0x00000190
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","PopupColors",%REG_DWORD%,243 ; 0x000000f3
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","QuickEdit",%REG_DWORD%,1 ; 0x00000001
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","ScreenBufferSize",%REG_DWORD%,196608120 ; 0x0bb80078
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","ScreenColors",%REG_DWORD%,86 ; 0x00000056
HKO,"Console\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe","WindowSize",%REG_DWORD%,3276920 ; 0x00320078
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","ColorTable05",%REG_DWORD%,5645313 ; 0x00562401
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","ColorTable06",%REG_DWORD%,15789550 ; 0x00f0edee
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","FaceName",%REG_SZ%,"Lucida Console"
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","FontFamily",%REG_DWORD%,54 ; 0x00000036
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","FontWeight",%REG_DWORD%,400 ; 0x00000190
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","PopupColors",%REG_DWORD%,243 ; 0x000000f3
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","QuickEdit",%REG_DWORD%,1 ; 0x00000001
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","ScreenBufferSize",%REG_DWORD%,196608120 ; 0x0bb80078
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","ScreenColors",%REG_DWORD%,86 ; 0x00000056
HKO,"Console\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe","WindowSize",%REG_DWORD%,3276920 ; 0x00320078
HKO,"Control Panel\Accessibility","MessageDuration",%REG_DWORD%,5 ; 0x00000005
HKO,"Control Panel\Accessibility","MinimumHitRadius",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Accessibility\AudioDescription","Locale",%REG_SZ%,""
HKO,"Control Panel\Accessibility\AudioDescription","On",%REG_SZ%,"0"
HKO,"Control Panel\Accessibility\Blind Access","On",%REG_SZ%,"0"
HKO,"Control Panel\Accessibility\HighContrast","Flags",%REG_SZ%,"126"
HKO,"Control Panel\Accessibility\HighContrast","High Contrast Scheme",%REG_SZ%,""
HKO,"Control Panel\Accessibility\Keyboard Preference","On",%REG_SZ%,"0"
HKO,"Control Panel\Accessibility\Keyboard Response","AutoRepeatDelay",%REG_SZ%,"1000"
HKO,"Control Panel\Accessibility\Keyboard Response","AutoRepeatRate",%REG_SZ%,"500"
HKO,"Control Panel\Accessibility\Keyboard Response","BounceTime",%REG_SZ%,"0"
HKO,"Control Panel\Accessibility\Keyboard Response","DelayBeforeAcceptance",%REG_SZ%,"1000"
HKO,"Control Panel\Accessibility\Keyboard Response","Flags",%REG_SZ%,"126"
HKO,"Control Panel\Accessibility\Keyboard Response","Last BounceKey Setting",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Accessibility\Keyboard Response","Last Valid Delay",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Accessibility\Keyboard Response","Last Valid Repeat",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Accessibility\Keyboard Response","Last Valid Wait",%REG_DWORD%,1000 ; 0x000003e8
HKO,"Control Panel\Accessibility\MouseKeys","Flags",%REG_SZ%,"62"
HKO,"Control Panel\Accessibility\MouseKeys","MaximumSpeed",%REG_SZ%,"80"
HKO,"Control Panel\Accessibility\MouseKeys","TimeToMaximumSpeed",%REG_SZ%,"3000"
HKO,"Control Panel\Accessibility\On","Locale",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Accessibility\On","On",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Accessibility\ShowSounds","On",%REG_SZ%,"0"
HKO,"Control Panel\Accessibility\SlateLaunch","ATapp",%REG_SZ%,"narrator"
HKO,"Control Panel\Accessibility\SlateLaunch","LaunchAT",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\Accessibility\SoundSentry","Flags",%REG_SZ%,"2"
HKO,"Control Panel\Accessibility\SoundSentry","FSTextEffect",%REG_SZ%,"0"
HKO,"Control Panel\Accessibility\SoundSentry","TextEffect",%REG_SZ%,"0"
HKO,"Control Panel\Accessibility\SoundSentry","WindowsEffect",%REG_SZ%,"1"
HKO,"Control Panel\Accessibility\StickyKeys","Flags",%REG_SZ%,"510"
HKO,"Control Panel\Accessibility\TimeOut","Flags",%REG_SZ%,"2"
HKO,"Control Panel\Accessibility\TimeOut","TimeToWait",%REG_SZ%,"300000"
HKO,"Control Panel\Accessibility\ToggleKeys","Flags",%REG_SZ%,"62"
HKO,"Control Panel\Appearance\New Schemes",,%REG_KEYONLY%
HKO,"Control Panel\Appearance\Schemes","@themeui.dll,-850",%REG_BINARY%,02,00,00,00,46,00,00,00,01,00,00,00,11,00,00,00,11,00,00,00,14,00,00,00,14,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,fc,7f,22,14,fc,7f,b0,fe,12,00,00,00,00,00,00,00,00,00,98,23,eb,77,0f,00,00,00,0f,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,f0,77,00,20,14,00,00,00,00,10,80,05,14,00,f0,1f,14,00,00,00,14,00,12,00,00,00,12,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,88,fb,e8,77,02,02,00,00,ac,b9,f0,77,00,00,00,00,20,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,7c,6b,e8,77,00,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,06,00,00,00,18,00,00,00,ff,ff,ff,ff,f0,4b,21,fc,00,c4,f0,77,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,0b,00,00,00,00,ff,12,00,50,00,00,00,c0,fe,12,00,0c,10,00,01,00,00,00,00,00,00,00,00,00,00,ff,00,00,ff,ff,00,00,00,00,00,00,00,00,00,ff,ff,ff,00,ff,ff,ff,00,ff,ff,00,00,ff,ff,ff,00,00,00,ff,00,00,ff,ff,00,00,00,00,00,00,80,00,00,ff,ff,ff,00,00,00,00,00,80,80,80,00,00,ff,00,00,ff,ff,ff,00,00,00,00,00,c0,c0,c0,00,ff,ff,ff,00,ff,ff,ff,00,ff,ff,00,00,00,00,00,00,c0,c0,c0,00,80,80,ff,00,00,00,ff,00,00,ff,ff,00
HKO,"Control Panel\Appearance\Schemes","@themeui.dll,-851",%REG_BINARY%,02,00,00,00,46,00,00,00,01,00,00,00,11,00,00,00,11,00,00,00,14,00,00,00,14,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,fc,7f,22,14,fc,7f,b0,fe,12,00,00,00,00,00,00,00,00,00,98,23,eb,77,0f,00,00,00,0f,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,f0,77,00,20,14,00,00,00,00,10,80,05,14,00,f0,1f,14,00,00,00,14,00,12,00,00,00,12,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,88,fb,e8,77,02,02,00,00,ac,b9,f0,77,00,00,00,00,20,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,7c,6b,e8,77,00,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,06,00,00,00,18,00,00,00,ff,ff,ff,ff,f0,4b,21,fc,00,c4,f0,77,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,0b,00,00,00,00,ff,12,00,50,00,00,00,c0,fe,12,00,0c,10,00,01,00,00,00,00,00,00,00,00,00,ff,ff,00,00,00,ff,00,00,00,00,00,00,00,00,00,ff,ff,ff,00,00,ff,00,00,00,ff,00,00,00,00,00,00,00,ff,ff,00,00,00,ff,00,ff,ff,ff,00,00,00,ff,00,ff,ff,ff,00,00,00,00,00,80,80,80,00,c0,c0,c0,00,00,ff,00,00,ff,ff,ff,00,c0,c0,c0,00,ff,ff,ff,00,ff,ff,ff,00,00,00,00,00,ff,ff,00,00,c0,c0,c0,00,80,80,ff,00,00,ff,ff,00,00,00,ff,00
HKO,"Control Panel\Appearance\Schemes","@themeui.dll,-852",%REG_BINARY%,02,00,00,00,46,00,00,00,01,00,00,00,11,00,00,00,11,00,00,00,14,00,00,00,14,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,fc,7f,22,14,fc,7f,b0,fe,12,00,00,00,00,00,00,00,00,00,98,23,eb,77,0f,00,00,00,0f,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,f0,77,00,20,14,00,00,00,00,10,80,05,14,00,f0,1f,14,00,00,00,14,00,12,00,00,00,12,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,88,fb,e8,77,02,02,00,00,ac,b9,f0,77,00,00,00,00,20,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,7c,6b,e8,77,00,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,06,00,00,00,18,00,00,00,ff,ff,ff,ff,f0,4b,21,fc,00,c4,f0,77,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,0b,00,00,00,00,ff,12,00,50,00,00,00,c0,fe,12,00,0c,10,00,01,00,00,00,00,00,00,00,00,80,00,80,00,00,80,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,00,ff,ff,ff,00,ff,ff,ff,00,ff,ff,ff,00,ff,ff,00,00,00,80,00,00,00,00,00,00,80,00,80,00,ff,ff,ff,00,00,00,00,00,80,80,80,00,00,ff,00,00,ff,ff,ff,00,ff,ff,ff,00,c0,c0,c0,00,ff,ff,ff,00,ff,ff,ff,00,ff,ff,ff,00,00,00,00,00,c0,c0,c0,00,80,80,ff,00,80,00,80,00,00,80,00,00
HKO,"Control Panel\Appearance\Schemes","@themeui.dll,-853",%REG_BINARY%,02,00,00,00,46,00,00,00,01,00,00,00,11,00,00,00,11,00,00,00,14,00,00,00,14,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,fc,7f,22,14,fc,7f,b0,fe,12,00,00,00,00,00,00,00,00,00,98,23,eb,77,0f,00,00,00,0f,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,f0,77,00,20,14,00,00,00,00,10,80,05,14,00,f0,1f,14,00,00,00,14,00,12,00,00,00,12,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,88,fb,e8,77,02,02,00,00,ac,b9,f0,77,00,00,00,00,20,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,7c,6b,e8,77,00,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,00,00,06,00,00,00,18,00,00,00,ff,ff,ff,ff,f0,4b,21,fc,00,c4,f0,77,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,14,00,0b,00,00,00,00,ff,12,00,50,00,00,00,c0,fe,12,00,0c,10,00,01,ff,ff,ff,00,ff,ff,ff,00,00,00,00,00,ff,ff,ff,00,ff,ff,ff,00,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,00,80,80,80,00,c0,c0,c0,00,80,80,80,00,00,00,00,00,ff,ff,ff,00,ff,ff,ff,00,80,80,80,00,00,80,00,00,00,00,00,00,00,00,00,00,c0,c0,c0,00,00,00,00,00,c0,c0,c0,00,00,00,00,00,ff,ff,ff,00,c0,c0,c0,00,00,00,00,00,00,00,00,00,ff,ff,ff,00
HKO,"Control Panel\Appearance\Schemes","@themeui.dll,-854",%REG_BINARY%,02,00,00,00,f4,01,00,00,01,00,00,00,10,00,00,00,10,00,00,00,12,00,00,00,12,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0c,00,00,00,0f,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,12,00,00,00,12,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,d4,d0,c8,00,3a,6e,a5,00,0a,24,6a,00,80,80,80,00,d4,d0,c8,00,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,00,d4,d0,c8,00,d4,d0,c8,00,80,80,80,00,0a,24,6a,00,ff,ff,ff,00,d4,d0,c8,00,80,80,80,00,80,80,80,00,00,00,00,00,d4,d0,c8,00,ff,ff,ff,00,40,40,40,00,d4,d0,c8,00,00,00,00,00,ff,ff,e1,00,b5,b5,b5,00,00,00,80,00,a6,ca,f0,00,c0,c0,c0,00
HKO,"Control Panel\Colors","ActiveBorder",%REG_SZ%,"180 180 180"
HKO,"Control Panel\Colors","ActiveTitle",%REG_SZ%,"153 180 209"
HKO,"Control Panel\Colors","AppWorkspace",%REG_SZ%,"171 171 171"
HKO,"Control Panel\Colors","Background",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Colors","ButtonAlternateFace",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Colors","ButtonDkShadow",%REG_SZ%,"105 105 105"
HKO,"Control Panel\Colors","ButtonFace",%REG_SZ%,"240 240 240"
HKO,"Control Panel\Colors","ButtonHilight",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Colors","ButtonLight",%REG_SZ%,"227 227 227"
HKO,"Control Panel\Colors","ButtonShadow",%REG_SZ%,"160 160 160"
HKO,"Control Panel\Colors","ButtonText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Colors","GradientActiveTitle",%REG_SZ%,"185 209 234"
HKO,"Control Panel\Colors","GradientInactiveTitle",%REG_SZ%,"215 228 242"
HKO,"Control Panel\Colors","GrayText",%REG_SZ%,"109 109 109"
HKO,"Control Panel\Colors","Hilight",%REG_SZ%,"51 153 255"
HKO,"Control Panel\Colors","HilightText",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Colors","HotTrackingColor",%REG_SZ%,"0 102 204"
HKO,"Control Panel\Colors","InactiveBorder",%REG_SZ%,"244 247 252"
HKO,"Control Panel\Colors","InactiveTitle",%REG_SZ%,"191 205 219"
HKO,"Control Panel\Colors","InactiveTitleText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Colors","InfoText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Colors","InfoWindow",%REG_SZ%,"255 255 225"
HKO,"Control Panel\Colors","Menu",%REG_SZ%,"240 240 240"
HKO,"Control Panel\Colors","MenuBar",%REG_SZ%,"240 240 240"
HKO,"Control Panel\Colors","MenuHilight",%REG_SZ%,"51 153 255"
HKO,"Control Panel\Colors","MenuText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Colors","Scrollbar",%REG_SZ%,"200 200 200"
HKO,"Control Panel\Colors","TitleText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Colors","Window",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Colors","WindowFrame",%REG_SZ%,"100 100 100"
HKO,"Control Panel\Colors","WindowText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Cursors","AppStarting",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_working.ani"
HKO,"Control Panel\Cursors","Arrow",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_arrow.cur"
HKO,"Control Panel\Cursors","ContactVisualization",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\Cursors","Crosshair",%REG_EXPAND_SZ%,""
HKO,"Control Panel\Cursors","CursorBaseSize",%REG_DWORD%,32 ; 0x00000020
HKO,"Control Panel\Cursors","GestureVisualization",%REG_DWORD%,31 ; 0x0000001f
HKO,"Control Panel\Cursors","Hand",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_link.cur"
HKO,"Control Panel\Cursors","Help",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_helpsel.cur"
HKO,"Control Panel\Cursors","IBeam",%REG_EXPAND_SZ%,""
HKO,"Control Panel\Cursors","No",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_unavail.cur"
HKO,"Control Panel\Cursors","NWPen",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_pen.cur"
HKO,"Control Panel\Cursors","Scheme Source",%REG_DWORD%,2 ; 0x00000002
HKO,"Control Panel\Cursors","SizeAll",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_move.cur"
HKO,"Control Panel\Cursors","SizeNESW",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_nesw.cur"
HKO,"Control Panel\Cursors","SizeNS",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_ns.cur"
HKO,"Control Panel\Cursors","SizeNWSE",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_nwse.cur"
HKO,"Control Panel\Cursors","SizeWE",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_ew.cur"
HKO,"Control Panel\Cursors","UpArrow",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_up.cur"
HKO,"Control Panel\Cursors","Wait",%REG_EXPAND_SZ%,"%%SystemRoot%%\cursors\aero_busy.ani"
HKO,"Control Panel\Desktop","ActiveWndTrackTimeout",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Desktop","BlockSendInputResets",%REG_SZ%,"0"
HKO,"Control Panel\Desktop","CaretTimeout",%REG_DWORD%,5000 ; 0x00001388
HKO,"Control Panel\Desktop","CaretWidth",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\Desktop","ClickLockTime",%REG_DWORD%,1200 ; 0x000004b0
HKO,"Control Panel\Desktop","CoolSwitchColumns",%REG_SZ%,"7"
HKO,"Control Panel\Desktop","CoolSwitchRows",%REG_SZ%,"3"
HKO,"Control Panel\Desktop","CursorBlinkRate",%REG_SZ%,"530"
HKO,"Control Panel\Desktop","DockMoving",%REG_SZ%,"1"
HKO,"Control Panel\Desktop","DragFromMaximize",%REG_SZ%,"1"
HKO,"Control Panel\Desktop","DragFullWindows",%REG_SZ%,"1"
HKO,"Control Panel\Desktop","DragHeight",%REG_SZ%,"4"
HKO,"Control Panel\Desktop","DragWidth",%REG_SZ%,"4"
HKO,"Control Panel\Desktop","FocusBorderHeight",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\Desktop","FocusBorderWidth",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\Desktop","FontSmoothing",%REG_SZ%,"2"
HKO,"Control Panel\Desktop","FontSmoothingGamma",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Desktop","FontSmoothingOrientation",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\Desktop","FontSmoothingType",%REG_DWORD%,2 ; 0x00000002
HKO,"Control Panel\Desktop","ForegroundFlashCount",%REG_DWORD%,7 ; 0x00000007
HKO,"Control Panel\Desktop","ForegroundLockTimeout",%REG_DWORD%,200000 ; 0x00030d40
HKO,"Control Panel\Desktop","LeftOverlapChars",%REG_SZ%,"3"
HKO,"Control Panel\Desktop","MenuShowDelay",%REG_SZ%,"400"
HKO,"Control Panel\Desktop","MouseWheelRouting",%REG_DWORD%,2 ; 0x00000002
HKO,"Control Panel\Desktop","PaintDesktopVersion",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Desktop","Pattern",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Desktop","RightOverlapChars",%REG_SZ%,"3"
HKO,"Control Panel\Desktop","ScreenSaveActive",%REG_SZ%,"1"
HKO,"Control Panel\Desktop","SnapSizing",%REG_SZ%,"1"
HKO,"Control Panel\Desktop","TileWallpaper",%REG_SZ%,"0"
HKO,"Control Panel\Desktop","WallPaper",%REG_SZ%,"C:\Windows\Web\Wallpaper\Windows\img0.jpg"
HKO,"Control Panel\Desktop","WallpaperOriginX",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Desktop","WallpaperOriginY",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Desktop","WallpaperStyle",%REG_SZ%,"10"
HKO,"Control Panel\Desktop","WheelScrollChars",%REG_SZ%,"3"
HKO,"Control Panel\Desktop","WheelScrollLines",%REG_SZ%,"3"
HKO,"Control Panel\Desktop","WindowArrangementActive",%REG_SZ%,"1"
HKO,"Control Panel\Desktop\Colors","ActiveBorder",%REG_SZ%,"212 208 200"
HKO,"Control Panel\Desktop\Colors","ActiveTitle",%REG_SZ%,"10 36 106"
HKO,"Control Panel\Desktop\Colors","AppWorkSpace",%REG_SZ%,"128 128 128"
HKO,"Control Panel\Desktop\Colors","ButtonAlternateFace",%REG_SZ%,"181 181 181"
HKO,"Control Panel\Desktop\Colors","ButtonDkShadow",%REG_SZ%,"64 64 64"
HKO,"Control Panel\Desktop\Colors","ButtonFace",%REG_SZ%,"212 208 200"
HKO,"Control Panel\Desktop\Colors","ButtonHiLight",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Desktop\Colors","ButtonLight",%REG_SZ%,"212 208 200"
HKO,"Control Panel\Desktop\Colors","ButtonShadow",%REG_SZ%,"128 128 128"
HKO,"Control Panel\Desktop\Colors","ButtonText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Desktop\Colors","GradientActiveTitle",%REG_SZ%,"166 202 240"
HKO,"Control Panel\Desktop\Colors","GradientInactiveTitle",%REG_SZ%,"192 192 192"
HKO,"Control Panel\Desktop\Colors","GrayText",%REG_SZ%,"128 128 128"
HKO,"Control Panel\Desktop\Colors","Hilight",%REG_SZ%,"10 36 106"
HKO,"Control Panel\Desktop\Colors","HilightText",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Desktop\Colors","HotTrackingColor",%REG_SZ%,"0 0 128"
HKO,"Control Panel\Desktop\Colors","InactiveBorder",%REG_SZ%,"212 208 200"
HKO,"Control Panel\Desktop\Colors","InactiveTitle",%REG_SZ%,"128 128 128"
HKO,"Control Panel\Desktop\Colors","InactiveTitleText",%REG_SZ%,"212 208 200"
HKO,"Control Panel\Desktop\Colors","InfoText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Desktop\Colors","InfoWindow",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Desktop\Colors","Menu",%REG_SZ%,"212 208 200"
HKO,"Control Panel\Desktop\Colors","MenuText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Desktop\Colors","Scrollbar",%REG_SZ%,"212 208 200"
HKO,"Control Panel\Desktop\Colors","TitleText",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Desktop\Colors","Window",%REG_SZ%,"255 255 255"
HKO,"Control Panel\Desktop\Colors","WindowFrame",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Desktop\Colors","WindowText",%REG_SZ%,"0 0 0"
HKO,"Control Panel\Desktop\WindowMetrics","BorderWidth",%REG_SZ%,"#USR:Control Panel\Desktop\WindowMetrics"
HKO,"Control Panel\Desktop\WindowMetrics","CaptionFont",%REG_BINARY%,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"Control Panel\Desktop\WindowMetrics","CaptionHeight",%REG_SZ%,"-270"
HKO,"Control Panel\Desktop\WindowMetrics","CaptionWidth",%REG_SZ%,"-270"
HKO,"Control Panel\Desktop\WindowMetrics","IconFont",%REG_BINARY%,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"Control Panel\Desktop\WindowMetrics","IconTitleWrap",%REG_SZ%,"1"
HKO,"Control Panel\Desktop\WindowMetrics","MenuFont",%REG_BINARY%,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"Control Panel\Desktop\WindowMetrics","MenuHeight",%REG_SZ%,"-270"
HKO,"Control Panel\Desktop\WindowMetrics","MenuWidth",%REG_SZ%,"-270"
HKO,"Control Panel\Desktop\WindowMetrics","MessageFont",%REG_BINARY%,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"Control Panel\Desktop\WindowMetrics","ScrollHeight",%REG_SZ%,"-240"
HKO,"Control Panel\Desktop\WindowMetrics","ScrollWidth",%REG_SZ%,"-240"
HKO,"Control Panel\Desktop\WindowMetrics","Shell Icon Size",%REG_SZ%,"32"
HKO,"Control Panel\Desktop\WindowMetrics","SmCaptionFont",%REG_BINARY%,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"Control Panel\Desktop\WindowMetrics","SmCaptionHeight",%REG_SZ%,"-180"
HKO,"Control Panel\Desktop\WindowMetrics","SmCaptionWidth",%REG_SZ%,"-180"
HKO,"Control Panel\Desktop\WindowMetrics","StatusFont",%REG_BINARY%,f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"Control Panel\Input Method","Show Status",%REG_SZ%,"1"
HKO,"Control Panel\Input Method\Hot Keys\00000010","Key Modifiers",%REG_BINARY%,02,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000010","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000010","Virtual Key",%REG_BINARY%,20,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000011","Key Modifiers",%REG_BINARY%,04,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000011","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000011","Virtual Key",%REG_BINARY%,20,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000012","Key Modifiers",%REG_BINARY%,02,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000012","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000012","Virtual Key",%REG_BINARY%,be,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000070","Key Modifiers",%REG_BINARY%,02,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000070","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000070","Virtual Key",%REG_BINARY%,20,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000071","Key Modifiers",%REG_BINARY%,04,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000071","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000071","Virtual Key",%REG_BINARY%,20,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000072","Key Modifiers",%REG_BINARY%,03,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000072","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000072","Virtual Key",%REG_BINARY%,bc,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000104","Key Modifiers",%REG_BINARY%,06,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000104","Target IME",%REG_BINARY%,11,04,01,e0
HKO,"Control Panel\Input Method\Hot Keys\00000104","Virtual Key",%REG_BINARY%,30,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000200","Key Modifiers",%REG_BINARY%,03,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000200","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000200","Virtual Key",%REG_BINARY%,47,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000201","Key Modifiers",%REG_BINARY%,03,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000201","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000201","Virtual Key",%REG_BINARY%,4b,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000202","Key Modifiers",%REG_BINARY%,03,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000202","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000202","Virtual Key",%REG_BINARY%,4c,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000203","Key Modifiers",%REG_BINARY%,03,c0,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000203","Target IME",%REG_BINARY%,00,00,00,00
HKO,"Control Panel\Input Method\Hot Keys\00000203","Virtual Key",%REG_BINARY%,56,00,00,00
HKO,"Control Panel\International","Locale",%REG_SZ%,"00000407"
HKO,"Control Panel\International","LocaleName",%REG_SZ%,"de-DE"
HKO,"Control Panel\International","s1159",%REG_SZ%,""
HKO,"Control Panel\International","s2359",%REG_SZ%,""
HKO,"Control Panel\International","sCurrency",%REG_SZ%,"€"
HKO,"Control Panel\International","sDate",%REG_SZ%,"."
HKO,"Control Panel\International","sDecimal",%REG_SZ%,","
HKO,"Control Panel\International","sGrouping",%REG_SZ%,"3;0"
HKO,"Control Panel\International","sLanguage",%REG_SZ%,"DEU"
HKO,"Control Panel\International","sList",%REG_SZ%,";"
HKO,"Control Panel\International","sLongDate",%REG_SZ%,"dddd, d. MMMM yyyy"
HKO,"Control Panel\International","sMonDecimalSep",%REG_SZ%,","
HKO,"Control Panel\International","sMonGrouping",%REG_SZ%,"3;0"
HKO,"Control Panel\International","sMonThousandSep",%REG_SZ%,"."
HKO,"Control Panel\International","sNativeDigits",%REG_SZ%,"0123456789"
HKO,"Control Panel\International","sNegativeSign",%REG_SZ%,"-"
HKO,"Control Panel\International","sPositiveSign",%REG_SZ%,""
HKO,"Control Panel\International","sShortDate",%REG_SZ%,"dd.MM.yyyy"
HKO,"Control Panel\International","sThousand",%REG_SZ%,"."
HKO,"Control Panel\International","sTime",%REG_SZ%,":"
HKO,"Control Panel\International","sTimeFormat",%REG_SZ%,"HH:mm:ss"
HKO,"Control Panel\International","sShortTime",%REG_SZ%,"HH:mm"
HKO,"Control Panel\International","sYearMonth",%REG_SZ%,"MMMM yyyy"
HKO,"Control Panel\International","iCalendarType",%REG_SZ%,"1"
HKO,"Control Panel\International","iCountry",%REG_SZ%,"49"
HKO,"Control Panel\International","iCurrDigits",%REG_SZ%,"2"
HKO,"Control Panel\International","iCurrency",%REG_SZ%,"3"
HKO,"Control Panel\International","iDate",%REG_SZ%,"1"
HKO,"Control Panel\International","iDigits",%REG_SZ%,"2"
HKO,"Control Panel\International","NumShape",%REG_SZ%,"1"
HKO,"Control Panel\International","iFirstDayOfWeek",%REG_SZ%,"0"
HKO,"Control Panel\International","iFirstWeekOfYear",%REG_SZ%,"2"
HKO,"Control Panel\International","iLZero",%REG_SZ%,"1"
HKO,"Control Panel\International","iMeasure",%REG_SZ%,"0"
HKO,"Control Panel\International","iNegCurr",%REG_SZ%,"8"
HKO,"Control Panel\International","iNegNumber",%REG_SZ%,"1"
HKO,"Control Panel\International","iPaperSize",%REG_SZ%,"9"
HKO,"Control Panel\International","iTime",%REG_SZ%,"1"
HKO,"Control Panel\International","iTimePrefix",%REG_SZ%,"0"
HKO,"Control Panel\International","iTLZero",%REG_SZ%,"1"
HKO,"Control Panel\International\Geo","Nation",%REG_SZ%,"94"
HKO,"Control Panel\International\Geo","Name",%REG_SZ%,"DE"
HKO,"Control Panel\International\User Profile","Languages",%REG_MULTI_SZ%,"de-DE"
HKO,"Control Panel\International\User Profile","ShowAutoCorrection",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile","ShowTextPrediction",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile","ShowCasing",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile","ShowShiftLock",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile\de-DE","0407:00000407",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile System Backup","Languages",%REG_MULTI_SZ%,"de-DE"
HKO,"Control Panel\International\User Profile System Backup","ShowAutoCorrection",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile System Backup","ShowTextPrediction",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile System Backup","ShowCasing",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile System Backup","ShowShiftLock",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\International\User Profile System Backup\de-DE","0407:00000407",%REG_DWORD%,1 ; 0x00000001
HKO,"Control Panel\Keyboard","InitialKeyboardIndicators",%REG_SZ%,"2147483648"
HKO,"Control Panel\Keyboard","KeyboardDelay",%REG_SZ%,"1"
HKO,"Control Panel\Keyboard","KeyboardSpeed",%REG_SZ%,"31"
HKO,"Control Panel\Mouse","ActiveWindowTracking",%REG_DWORD%,0 ; 0x00000000
HKO,"Control Panel\Mouse","Beep",%REG_SZ%,"No"
HKO,"Control Panel\Mouse","DoubleClickHeight",%REG_SZ%,"4"
HKO,"Control Panel\Mouse","DoubleClickSpeed",%REG_SZ%,"500"
HKO,"Control Panel\Mouse","DoubleClickWidth",%REG_SZ%,"4"
HKO,"Control Panel\Mouse","ExtendedSounds",%REG_SZ%,"No"
HKO,"Control Panel\Mouse","MouseHoverHeight",%REG_SZ%,"4"
HKO,"Control Panel\Mouse","MouseHoverTime",%REG_SZ%,"400"
HKO,"Control Panel\Mouse","MouseHoverWidth",%REG_SZ%,"4"
HKO,"Control Panel\Mouse","MouseSensitivity",%REG_SZ%,"10"
HKO,"Control Panel\Mouse","MouseSpeed",%REG_SZ%,"1"
HKO,"Control Panel\Mouse","MouseThreshold1",%REG_SZ%,"6"
HKO,"Control Panel\Mouse","MouseThreshold2",%REG_SZ%,"10"
HKO,"Control Panel\Mouse","MouseTrails",%REG_SZ%,"0"
HKO,"Control Panel\Mouse","SmoothMouseXCurve",%REG_BINARY%,00,00,00,00,00,00,00,00,15,6e,00,00,00,00,00,00,00,40,01,00,00,00,00,00,29,dc,03,00,00,00,00,00,00,00,28,00,00,00,00,00
HKO,"Control Panel\Mouse","SmoothMouseYCurve",%REG_BINARY%,00,00,00,00,00,00,00,00,fd,11,01,00,00,00,00,00,00,24,04,00,00,00,00,00,00,fc,12,00,00,00,00,00,00,c0,bb,01,00,00,00,00
HKO,"Control Panel\Mouse","SnapToDefaultButton",%REG_SZ%,"0"
HKO,"Control Panel\Mouse","SwapMouseButtons",%REG_SZ%,"0"
HKO,"Control Panel\PowerCfg","CurrentPowerPolicy",%REG_SZ%,"0"
HKO,"Control Panel\PowerCfg\GlobalPowerPolicy","Policies",%REG_BINARY%,01,00,00,00,00,00,00,00,03,00,00,00,10,00,00,00,00,00,00,00,03,00,00,00,10,00,00,00,02,00,00,00,03,00,00,00,00,00,00,00,02,00,00,00,03,00,00,00,00,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,01,00,00,00,03,00,00,00,03,00,00,00,00,00,00,c0,01,00,00,00,05,00,00,00,01,00,00,00,0a,00,00,00,00,00,00,00,03,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,16,00,00,00
HKO,"Control Panel\PowerCfg\PowerPolicies\0","Description",%REG_SZ%,"This scheme is suited to most home or desktop computers that are left plugged in all the time."
HKO,"Control Panel\PowerCfg\PowerPolicies\0","Name",%REG_SZ%,"Home/Office Desk"
HKO,"Control Panel\PowerCfg\PowerPolicies\0","Policies",%REG_BINARY%,01,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,02,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,2c,01,00,00,32,32,00,03,04,00,00,00,04,00,00,00,00,00,00,00,00,00,00,00,b0,04,00,00,2c,01,00,00,00,00,00,00,58,02,00,00,01,01,64,50,64,64,00,00
HKO,"Control Panel\PowerCfg\PowerPolicies\1","Description",%REG_SZ%,"This scheme is designed for extended battery life for portable computers on the road."
HKO,"Control Panel\PowerCfg\PowerPolicies\1","Name",%REG_SZ%,"Portable/Laptop"
HKO,"Control Panel\PowerCfg\PowerPolicies\1","Policies",%REG_BINARY%,01,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,b0,04,00,00,2c,01,00,00,32,32,03,03,04,00,00,00,04,00,00,00,00,00,00,00,00,00,00,00,84,03,00,00,2c,01,00,00,08,07,00,00,2c,01,00,00,01,01,64,50,64,64,00,00
HKO,"Control Panel\PowerCfg\PowerPolicies\2","Description",%REG_SZ%,"This scheme keeps the monitor on for doing presentations."
HKO,"Control Panel\PowerCfg\PowerPolicies\2","Name",%REG_SZ%,"Presentation"
HKO,"Control Panel\PowerCfg\PowerPolicies\2","Policies",%REG_BINARY%,01,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,00,00,00,00,84,03,00,00,32,32,03,02,04,00,00,00,04,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,2c,01,00,00,01,01,50,50,64,64,00,00
HKO,"Control Panel\PowerCfg\PowerPolicies\3","Description",%REG_SZ%,"This scheme keeps the computer running so that it can be accessed from the network.  Use this scheme if you do not have network wakeup hardware."
HKO,"Control Panel\PowerCfg\PowerPolicies\3","Name",%REG_SZ%,"Always On"
HKO,"Control Panel\PowerCfg\PowerPolicies\3","Policies",%REG_BINARY%,01,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,02,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,32,32,00,00,04,00,00,00,04,00,00,00,00,00,00,00,00,00,00,00,b0,04,00,00,84,03,00,00,00,00,00,00,08,07,00,00,00,01,64,64,64,64,00,00
HKO,"Control Panel\PowerCfg\PowerPolicies\4","Description",%REG_SZ%,"This scheme keeps the computer on and optimizes it for high performance."
HKO,"Control Panel\PowerCfg\PowerPolicies\4","Name",%REG_SZ%,"Minimal Power Management"
HKO,"Control Panel\PowerCfg\PowerPolicies\4","Policies",%REG_BINARY%,01,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,02,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,2c,01,00,00,32,32,03,03,04,00,00,00,04,00,00,00,00,00,00,00,00,00,00,00,84,03,00,00,2c,01,00,00,00,00,00,00,84,03,00,00,00,01,64,64,64,64,00,00
HKO,"Control Panel\PowerCfg\PowerPolicies\5","Description",%REG_SZ%,"This scheme is extremely aggressive for saving power."
HKO,"Control Panel\PowerCfg\PowerPolicies\5","Name",%REG_SZ%,"Max Battery"
HKO,"Control Panel\PowerCfg\PowerPolicies\5","Policies",%REG_BINARY%,01,00,00,00,02,00,00,00,01,00,00,00,00,00,00,00,02,00,00,00,05,00,00,00,00,00,00,00,b0,04,00,00,78,00,00,00,32,32,03,02,04,00,00,00,04,00,00,00,00,00,00,00,00,00,00,00,84,03,00,00,3c,00,00,00,00,00,00,00,b4,00,00,00,01,01,64,32,64,64,00,00
HKO,"Control Panel\Quick Actions\Pinned",,%REG_KEYONLY%
HKO,"Control Panel\Sound","Beep",%REG_SZ%,"yes"
HKO,"Control Panel\Sound","ExtendedSounds",%REG_SZ%,"yes"
HKO,"Environment","Path",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Local\Microsoft\WindowsApps;"
HKO,"Environment","TEMP",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Local\Temp"
HKO,"Environment","TMP",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Local\Temp"
HKO,"EUDC\932","SystemDefaultEUDCFont",%REG_SZ%,"EUDC.TTE"
HKO,"EUDC\936","SystemDefaultEUDCFont",%REG_SZ%,"EUDC.TTE"
HKO,"EUDC\949","SystemDefaultEUDCFont",%REG_SZ%,"EUDC.TTE"
HKO,"EUDC\950","SystemDefaultEUDCFont",%REG_SZ%,"EUDC.TTE"
HKO,"Keyboard Layout\Preload","1",%REG_SZ%,"00000407"
HKO,"Keyboard Layout\Substitutes",,%REG_KEYONLY%
HKO,"Keyboard Layout\Toggle",,%REG_KEYONLY%
HKO,"Network",,%REG_KEYONLY%
HKO,"SOFTWARE\Google\Chrome\NativeMessagingHosts\com.microsoft.browsercore",,%REG_SZ%,"C:\Program Files\Windows Security\BrowserCore\manifest.json"
HKO,"SOFTWARE\Microsoft\Accessibility",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","FirstTimeHelppaneStartup",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","Height",%REG_DWORD%,340 ; 0x00000154
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","ImplicitFeedback",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","OnlineAssist",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","PositionX",%REG_DWORD%,4294967295 ; 0xffffffff
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","PositionY",%REG_DWORD%,4294967295 ; 0xffffffff
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","UserID",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Assistance\Client\1.0\Settings","Width",%REG_DWORD%,510 ; 0x000001fe
HKO,"SOFTWARE\Microsoft\Avalon.Graphics",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\CommsAPHost\Test",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\CTF\Assemblies\0x00000407\{34745C63-B2F0-4784-8B67-5E12C8701A31}","Default",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\CTF\Assemblies\0x00000407\{34745C63-B2F0-4784-8B67-5E12C8701A31}","Profile",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\CTF\Assemblies\0x00000407\{34745C63-B2F0-4784-8B67-5E12C8701A31}","KeyboardLayout",%REG_DWORD%,67568647 ; 0x04070407
HKO,"SOFTWARE\Microsoft\CTF\DirectSwitchHotkeys",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\CTF\HiddenDummyLayouts",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\CTF\SortOrder\AssemblyItem\0x00000407\{34745C63-B2F0-4784-8B67-5E12C8701A31}\00000000","CLSID",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\CTF\SortOrder\AssemblyItem\0x00000407\{34745C63-B2F0-4784-8B67-5E12C8701A31}\00000000","KeyboardLayout",%REG_DWORD%,67568647 ; 0x04070407
HKO,"SOFTWARE\Microsoft\CTF\SortOrder\AssemblyItem\0x00000407\{34745C63-B2F0-4784-8B67-5E12C8701A31}\00000000","Profile",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\CTF\SortOrder\Language","00000000",%REG_SZ%,"00000407"
HKO,"SOFTWARE\Microsoft\CTF\TIP",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Fax\FaxOptions",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Fax\fxsclnt\Archive",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Fax\fxsclnt\Confirm",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Fax\Setup",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Fax\UserInfo",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\GameBarApi",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\IME",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Input\TIPC",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Input\TSF\Tsf3Override",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\InputMethod",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\InputPersonalization","RestrictImplicitInkCollection",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\InputPersonalization","RestrictImplicitTextCollection",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\InputPersonalization\TrainedDataStore","HarvestContacts",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Internet Connection Wizard","Completed",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Internet Explorer\Document Windows","height",%REG_BINARY%,00,00,00,00
HKO,"SOFTWARE\Microsoft\Internet Explorer\Document Windows","Maximized",%REG_SZ%,"no"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Document Windows","width",%REG_BINARY%,00,00,00,80
HKO,"SOFTWARE\Microsoft\Internet Explorer\Document Windows","x",%REG_BINARY%,00,00,00,80
HKO,"SOFTWARE\Microsoft\Internet Explorer\Document Windows","y",%REG_BINARY%,00,00,00,00
HKO,"SOFTWARE\Microsoft\Internet Explorer\International","AcceptLanguage",%REG_SZ%,"de-DE,de;q=0.5"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Anchor Underline",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Cache_Update_Frequency",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Disable Script Debugger",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","DisableScriptDebuggerIE",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Display Inline Images",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Do404Search",%REG_BINARY%,01,00,00,00
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Local Page",%REG_SZ%,"%%11%%\blank.htm"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Save_Session_History_On_Exit",%REG_SZ%,"no"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Search Page",%REG_SZ%,"http://go.microsoft.com/fwlink/?LinkId=54896"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Show_FullURL",%REG_SZ%,"no"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Show_StatusBar",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Show_ToolBar",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Show_URLinStatusBar",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Show_URLToolBar",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","Use_DlgBox_Colors",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","UseClearType",%REG_SZ%,"no"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Main","XMLHTTP",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Internet Explorer\New Windows","PopupMgr",%REG_SZ%,"yes"
HKO,"SOFTWARE\Microsoft\Internet Explorer\New Windows","Use Anchor Hover Color",%REG_SZ%,"1"
HKO,"SOFTWARE\Microsoft\Internet Explorer\New Windows","UseSecBand",%REG_SZ%,"1"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Security","Safety Warning Level",%REG_SZ%,"Query"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Security","Sending_Security",%REG_SZ%,"Medium"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Security","Viewing_Security",%REG_SZ%,"Low"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Services",,%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Internet Explorer\Settings","Anchor Color",%REG_SZ%,"0,0,255"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Settings","Anchor Color Visited",%REG_SZ%,"128,0,128"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Settings","Background Color",%REG_SZ%,"192,192,192"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Settings","Text Color",%REG_SZ%,"0,0,0"
HKO,"SOFTWARE\Microsoft\Internet Explorer\Settings","Use Anchor Hover Color",%REG_SZ%,"No"
HKO,"SOFTWARE\Microsoft\Internet Explorer\TypedURLs","url1",%REG_SZ%,"http://go.microsoft.com/fwlink/p/?LinkId=255141"
HKO,"SOFTWARE\Microsoft\Internet Explorer\URLSearchHooks","{CFBFAE00-17A6-11D0-99CB-00C04FD64497}",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\MobilePC\AdaptableSettings",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Multimedia\Audio\DefaultEndpoint",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Narrator\NoRoam","RunningState",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\OneDrive","EnableDownlevelInstallOnBluePlus",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\OneDrive","EnableTHDFFeatures",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Osk","RunningState",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\PeerNet\Event_Config",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Personalization\Settings","AcceptedPrivacyPolicy",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Phone\ShellUI",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Remote Assistance",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\ScreenMagnifier","RunningState",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Sensors",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Speech\Preferences\AppCompatDisableDictation","dwm.exe",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Speech\Preferences\AppCompatDisableDictation","tabtip.exe",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Speech\Preferences\AppCompatDisableMSAA","devenv.exe",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Speech\Preferences\AppCompatDisableMSAA","taskmgr.exe",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\TabletTip\1.7",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\UEV\Agent","UserConsoleVersion",%REG_SZ%,"10.0.19041.1387"
HKO,"SOFTWARE\Microsoft\WAB\WAB4\Wab File Name",,%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\WcmSvc\Tethering\Roaming",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\wfs\DraftsView",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\wfs\InboxView",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\wfs\IncomingView",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\wfs\OutboxView",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\wfs\SentItemsView",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\AssignedAccessConfiguration",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ClickNote\UserCustomization\DoubleClickBelowLock","Override",%REG_DWORD%,5 ; 0x00000005
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ClickNote\UserCustomization\DoubleClickBelowLock","PenWorkspaceVerb",%REG_DWORD%,3 ; 0x00000003
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ClickNote\UserCustomization\LongPressBelowLock","Override",%REG_DWORD%,5 ; 0x00000005
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ClickNote\UserCustomization\LongPressBelowLock","PenWorkspaceVerb",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ClickNote\UserCustomization\SingleClickBelowLock","Override",%REG_DWORD%,8 ; 0x00000008
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ClickNote\UserCustomization\SingleClickBelowLock","PenWorkspaceVerb",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\CloudStore",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","FeatureManagementEnabled",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","OemPreInstalledAppsEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","PreInstalledAppsEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","RotatingLockScreenEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","RotatingLockScreenOverlayEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","SilentInstalledAppsEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","SoftLandingEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","SystemPaneSuggestionsEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager","SlideshowEnabled",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Renderers\SubscribedContent-310091","Version",%REG_SZ%,"2"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Renderers\SubscribedContent-310092","Version",%REG_SZ%,"2"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Renderers\SubscribedContent-338380","Version",%REG_SZ%,"2"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Renderers\SubscribedContent-338381","Version",%REG_SZ%,"2"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Renderers\SubscribedContent-338387","Version",%REG_SZ%,"2"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Renderers\SubscribedContent-338388","Version",%REG_SZ%,"2"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Subscriptions",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced","Start_SearchFiles",%REG_DWORD%,2 ; 0x00000002
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers","DisableAutoplay",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers\EventHandlersDefaultSelection",,%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers\UserChosenExecuteHandlers",,%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\DefaultIcon","empty",%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\imageres.dll,-55"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\DefaultIcon","full",%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\imageres.dll,-54"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SearchPlatform\Preferences","BreadCrumbBarSearchDefault",%REG_SZ%,"MSNSearch"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SearchPlatform\Preferences","DisableAutoNavigateURL",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SearchPlatform\Preferences","DisableAutoResolveEmailAddrs",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SearchPlatform\Preferences","DisableResultsInNewWindow",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SearchPlatform\Preferences","DisableTabbedBrowsing",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SearchPlatform\Preferences","EditSavedSearch",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SearchPlatform\Preferences","IEAddressBarSearchDefault",%REG_SZ%,"MSNSearch"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","!Do not use this registry key",%REG_SZ%,"Use the SHGetFolderPath or SHGetKnownFolderPath function instead"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","AppData",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Cache",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Local\Microsoft\Windows\INetCache"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Cookies",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Local\Microsoft\Windows\INetCookies"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Desktop",%REG_EXPAND_SZ%,"%%USERPROFILE%%\Desktop"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Favorites",%REG_EXPAND_SZ%,"%%USERPROFILE%%\Favorites"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","History",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Local\Microsoft\Windows\History"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Local AppData",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Local"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","My Music",%REG_EXPAND_SZ%,"%%USERPROFILE%%\Music"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","My Pictures",%REG_EXPAND_SZ%,"%%USERPROFILE%%\Pictures"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","My Video",%REG_EXPAND_SZ%,"%%USERPROFILE%%\Videos"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","NetHood",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\Network Shortcuts"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Personal",%REG_EXPAND_SZ%,"%%USERPROFILE%%\Documents"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","PrintHood",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\Printer Shortcuts"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Programs",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Recent",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\Recent"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","SendTo",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\SendTo"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Start Menu",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\Start Menu"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Startup",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","Templates",%REG_EXPAND_SZ%,"%%USERPROFILE%%\AppData\Roaming\Microsoft\Windows\Templates"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders","{374DE290-123F-4565-9164-39C4925E467B}",%REG_EXPAND_SZ%,"%%USERPROFILE%%\Downloads"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\FileHistory\RestoreUI","FolderViewType",%REG_SZ%,"MediumIcons"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\FileHistory\RestoreUI","SearchResultsViewType",%REG_SZ%,"Content"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\FileHistory\RestoreUI","WindowLocation",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Holographic","FirstRunSucceeded",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Holographic\StageManagement","DisableQuickRoomSetup",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Holographic\StageManagement","DisableStageNearbyRequirement",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ActiveLearning",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","AnsiChar",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","AutoCandState",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","BallonUI",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","BeepEnable",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Big5CharOnly",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","CandidateLargeFont",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","CandidateSortType",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ChangJie.All.ActiveAlphaNum",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ChangJie.All.ZkeyAsWildCard",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ChangJie.AssociatedWord",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ChangJie.IsOfflineReading",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ChangJie.ReadLayout",%REG_SZ%,"0x00010030"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","CharMode",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","CustomLayout",%REG_BINARY%,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","DefaultLanguage",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Delemiter",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Domain",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","EnableCNSReading",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","EnableExtensionA_Char",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","EnableExtensionB_Char",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","EudpSCK",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Fuzzy",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","HFTLearning",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Intellegnt.Eudp",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Intelligent.AssociatedWord",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Intelligent.AutoFinalize",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Intelligent.AutoInputSwitch",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Intelligent.EnableFinal",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Intelligent.EscapeFunc",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","LeadingIndicator",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Legacy.AutoFinalize",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Legacy.AutoInputSwitch",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Legacy.EnableFinal",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Legacy.EscapeFunc",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Legacy.Eudp",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Legacy.Modeless",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","MaxCharPerSentence",%REG_SZ%,"0x00000020"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","NewChangJie.Modeless",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","NewPhonetic.IntCharMode",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","NewPhonetic.Modeless",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","NewQuick.Modeless",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Phonetic.All.ActiveAlphaNum",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Phonetic.All.ZkeyAsWildCard",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Phonetic.AssociatedWord",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Phonetic.IntCharMode",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Phonetic.IsOfflineReading",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Phonetic.ReadLayout",%REG_SZ%,"0x00020010"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","PhrManEudpSortType",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","PhrManSelfLearnSortType",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","PluginLexiconInfo",%REG_BINARY%,00,00,00,00,00,00,00,00
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","PuncEnable",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Quick.AssociatedWord",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Quick.ZkeyAsWildCard",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ReconvertLength",%REG_SZ%,"0x00000020"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ReservedWord",%REG_BINARY%,08,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,2f,00,2f,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,66,00,69,00,6c,00,65,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,66,00,74,00,70,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,68,00,74,00,74,00,70,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,6d,00,61,00,69,00,6c,00,74,00,6f,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,6e,00,65,00,77,00,73,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,77,00,69,00,6e,00,64,00,6f,00,77,00,73,00,00,00,00,00,00,00,00,00,00,00,00,00,77,00,77,00,77,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ReversedReadingType",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","SelfLearning",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","SharedEudp",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ShiftLeft",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","ShiftRight",%REG_SZ%,"0x00000001"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Surrogate",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","Trigram",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","UserSymbolMapping",%REG_BINARY%,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,20,00,31,00,32,00,33,00,34,00,35,00,36,00,37,00,38,00,39,00,30,00,61,00,62,00,63,00,64,00,65,00,66,00,67,00,68,00,69,00,6a,00,6b,00,6c,00,6d,00,6e,00,6f,00,70,00,71,00,72,00,73,00,74,00,75,00,76,00,77,00,78,00,79,00,7a,00,2d,00,3d,00,5c,00,5b,00,5d,00,3b,00,27,00,2c,00,2e,00,2f,00,60,00,00,30,11,ff,12,ff,13,ff,14,ff,15,ff,16,ff,17,ff,18,ff,19,ff,10,ff,41,ff,42,ff,43,ff,44,ff,45,ff,46,ff,47,ff,48,ff,49,ff,4a,ff,4b,ff,4c,ff,4d,ff,4e,ff,4f,ff,50,ff,51,ff,52,ff,53,ff,54,ff,55,ff,56,ff,57,ff,58,ff,59,ff,5a,ff,00,25,1d,ff,3c,ff,14,30,15,30,54,fe,19,20,0c,ff,02,30,0f,ff,35,20,20,00,21,00,40,00,23,00,24,00,25,00,5e,00,26,00,2a,00,28,00,29,00,41,00,42,00,43,00,44,00,45,00,46,00,47,00,48,00,49,00,4a,00,4b,00,4c,00,4d,00,4e,00,4f,00,50,00,51,00,52,00,53,00,54,00,55,00,56,00,57,00,58,00,59,00,5a,00,5f,00,2b,00,7c,00,7b,00,7d,00,3a,00,22,00,3c,00,3e,00,3f,00,7e,00,00,30,01,ff,20,ff,03,ff,04,ff,05,ff,3f,fe,06,ff,0a,ff,08,ff,09,ff,21,ff,22,ff,23,ff,24,ff,25,ff,26,ff,27,ff,28,ff,29,ff,2a,ff,2b,ff,2c,ff,2d,ff,2e,ff,2f,ff,30,ff,31,ff,32,ff,33,ff,34,ff,35,ff,36,ff,37,ff,38,ff,39,ff,3a,ff,3f,ff,0b,ff,5c,ff,5b,ff,5d,ff,1a,ff,1d,20,1c,ff,1e,ff,1f,ff,5e,ff,20,00,31,00,32,00,33,00,34,00,35,00,36,00,37,00,38,00,39,00,30,00,61,00,62,00,63,00,64,00,65,00,66,00,67,00,68,00,69,00,6a,00,6b,00,6c,00,6d,00,6e,00,6f,00,70,00,71,00,72,00,73,00,74,00,75,00,76,00,77,00,78,00,79,00,7a,00,2d,00,3d,00,5c,00,5b,00,5d,00,3b,00,27,00,2c,00,2e,00,2f,00,60,00,00,30,11,ff,12,ff,13,ff,14,ff,15,ff,16,ff,17,ff,18,ff,19,ff,10,ff,41,ff,42,ff,43,ff,44,ff,45,ff,46,ff,47,ff,48,ff,49,ff,4a,ff,4b,ff,4c,ff,4d,ff,4e,ff,4f,ff,50,ff,51,ff,52,ff,53,ff,54,ff,55,ff,56,ff,57,ff,58,ff,59,ff,5a,ff,00,25,1d,ff,3c,ff,14,30,15,30,54,fe,19,20,0c,ff,02,30,0f,ff,35,20,20,00,21,00,40,00,23,00,24,00,25,00,5e,00,26,00,2a,00,28,00,29,00,41,00,42,00,43,00,44,00,45,00,46,00,47,00,48,00,49,00,4a,00,4b,00,4c,00,4d,00,4e,00,4f,00,50,00,51,00,52,00,53,00,54,00,55,00,56,00,57,00,58,00,59,00,5a,00,5f,00,2b,00,7c,00,7b,00,7d,00,3a,00,22,00,3c,00,3e,00,3f,00,7e,00,00,30,01,ff,20,ff,03,ff,04,ff,05,ff,3f,fe,06,ff,0a,ff,08,ff,09,ff,21,ff,22,ff,23,ff,24,ff,25,ff,26,ff,27,ff,28,ff,29,ff,2a,ff,2b,ff,2c,ff,2d,ff,2e,ff,2f,ff,30,ff,31,ff,32,ff,33,ff,34,ff,35,ff,36,ff,37,ff,38,ff,39,ff,3a,ff,3f,ff,0b,ff,5c,ff,5b,ff,5d,ff,1a,ff,1d,20,1c,ff,1e,ff,1f,ff,5e,ff,20,00,31,00,32,00,33,00,34,00,35,00,36,00,37,00,38,00,39,00,30,00,61,00,62,00,63,00,64,00,65,00,66,00,67,00,68,00,69,00,6a,00,6b,00,6c,00,6d,00,6e,00,6f,00,70,00,71,00,72,00,73,00,74,00,75,00,76,00,77,00,78,00,79,00,7a,00,2d,00,3d,00,5c,00,5b,00,5d,00,3b,00,27,00,2c,00,2e,00,2f,00,60,00,00,30,11,ff,12,ff,13,ff,14,ff,15,ff,16,ff,17,ff,18,ff,19,ff,10,ff,41,ff,42,ff,43,ff,44,ff,45,ff,46,ff,47,ff,48,ff,49,ff,4a,ff,4b,ff,4c,ff,4d,ff,4e,ff,4f,ff,50,ff,51,ff,52,ff,53,ff,54,ff,55,ff,56,ff,57,ff,58,ff,59,ff,5a,ff,00,25,1d,ff,3c,ff,14,30,15,30,54,fe,19,20,0c,ff,02,30,0f,ff,35,20,20,00,21,00,40,00,23,00,24,00,25,00,5e,00,26,00,2a,00,28,00,29,00,41,00,42,00,43,00,44,00,45,00,46,00,47,00,48,00,49,00,4a,00,4b,00,4c,00,4d,00,4e,00,4f,00,50,00,51,00,52,00,53,00,54,00,55,00,56,00,57,00,58,00,59,00,5a,00,5f,00,2b,00,7c,00,7b,00,7d,00,3a,00,22,00,3c,00,3e,00,3f,00,7e,00,00,30,01,ff,20,ff,03,ff,04,ff,05,ff,3f,fe,06,ff,0a,ff,08,ff,09,ff,21,ff,22,ff,23,ff,24,ff,25,ff,26,ff,27,ff,28,ff,29,ff,2a,ff,2b,ff,2c,ff,2d,ff,2e,ff,2f,ff,30,ff,31,ff,32,ff,33,ff,34,ff,35,ff,36,ff,37,ff,38,ff,39,ff,3a,ff,3f,ff,0b,ff,5c,ff,5b,ff,5d,ff,1a,ff,1d,20,1c,ff,1e,ff,1f,ff,5e,ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70","VirtualInputMode",%REG_SZ%,"0x00000000"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70\FuzzyScheme","Data",%REG_BINARY%,87,3f,00,00
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ime\IMTC70\FuzzyScheme","Name",%REG_SZ%,"{EF8C6C27-997A-4af2-BC0E-A15C84790F8C}"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings","CertificateRevocation",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings","DisableCachingOfSSLPages",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings","IE5_UA_Backup_Flag",%REG_SZ%,"5.0"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings","PrivacyAdvanced",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings","SecureProtocols",%REG_DWORD%,2688 ; 0x00000a80
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings","User Agent",%REG_SZ%,"Mozilla/5.0 (compatible; MSIE 9.0; Win32)"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\Cache",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Cache","Persistent",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Http Filters\RPA",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\P3P\History",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Passport",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Lock Screen","LockAppAumId",%REG_SZ%,"Microsoft.LockApp_cw5n1h2txyewy!WindowsDefaultLockScreen"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Mobility",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PenWorkspace\Notes","NotesApp",%REG_SZ%,"Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe!App"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","AAPThreshold",%REG_DWORD%,2 ; 0x00000002
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","CursorSpeed",%REG_DWORD%,10 ; 0x0000000a
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","EnableEdgy",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","LeaveOnWithMouse",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","PanEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","RightClickZoneEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","ScrollDirection",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","TapAndDrag",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","TapsEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","TwoFingerTapEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad","ZoomEnabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PrecisionTouchPad\Status","Enabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Privacy","TailoredExperiencesWithDiagnosticDataEnabled",%REG_DWORD%,2 ; 0x00000002
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.CloudExperienceHostLauncher","ApplicationType",%REG_DWORD%,1073741824 ; 0x40000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.CloudExperienceHostLauncher","Capabilities",%REG_DWORD%,9471 ; 0x000024ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.CloudExperienceHostLauncher","PackageMoniker",%REG_SZ%,"System"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.CloudExperienceHostLauncherCustom","ApplicationType",%REG_DWORD%,1073741824 ; 0x40000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.CloudExperienceHostLauncherCustom","Capabilities",%REG_DWORD%,9471 ; 0x000024ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.CloudExperienceHostLauncherCustom","PackageMoniker",%REG_SZ%,"System"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.DisplaySettings","ApplicationType",%REG_DWORD%,1073741824 ; 0x40000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.DisplaySettings","Capabilities",%REG_DWORD%,9471 ; 0x000024ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.DisplaySettings","PackageMoniker",%REG_SZ%,"System"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.FodHelper","ApplicationType",%REG_DWORD%,1073741824 ; 0x40000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.FodHelper","Capabilities",%REG_DWORD%,9471 ; 0x000024ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.FodHelper","PackageMoniker",%REG_SZ%,"System"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.MobilityExperience","ApplicationType",%REG_DWORD%,1073741824 ; 0x40000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.MobilityExperience","Capabilities",%REG_DWORD%,9471 ; 0x000024ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.MobilityExperience","PackageMoniker",%REG_SZ%,"System"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.Suggested","ApplicationType",%REG_DWORD%,1073741824 ; 0x40000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.Suggested","Capabilities",%REG_DWORD%,9471 ; 0x000024ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.Suggested","PackageMoniker",%REG_SZ%,"System"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.WindowsTip","ApplicationType",%REG_DWORD%,1073741824 ; 0x40000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.WindowsTip","Capabilities",%REG_DWORD%,9471 ; 0x000024ff
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\Applications\Windows.SystemToast.WindowsTip","PackageMoniker",%REG_SZ%,"System"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\RADAR","CLResolutionInterval",%REG_DWORD%,5 ; 0x00000005
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\RADAR","DisplayInterval",%REG_DWORD%,1440 ; 0x000005a0
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Run","OneDriveSetup",%REG_SZ%,"C:\Windows\SysWOW64\OneDriveSetup.exe /thfirstsetup"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\Bubbles\Screen 1",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\Bubbles\Screen 2",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\Mystify\Screen 1",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\Mystify\Screen 2",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\Ribbons\Screen 1",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\Ribbons\Screen 2",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\ssText3d\Screen 1",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Screensavers\ssText3d\Screen 2",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\Groups\AppSync","Enabled",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\SmartGlass","UserAuthPolicy",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\HandoffPriorities","RequestMakeCall",%REG_SZ%,"DIALER.EXE"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\HandoffPriorities\MediaModes",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ThemeManager","DllName",%REG_EXPAND_SZ%,"%%SystemRoot%%\resources\themes\Aero\Aero.msstyles"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\ThemeManager","PrePolicy-DllName",%REG_SZ%,"C:\Windows\resources\themes\Aero\Aero.msstyles"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes","InstallVisualStyleColor",%REG_SZ%,"NormalColor"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes","InstallVisualStyleSize",%REG_SZ%,"NormalSize"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes","LastHighContrastTheme",%REG_EXPAND_SZ%,"%%SystemRoot%%\resources\Ease of Access Themes\hcblack.theme"
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes","ThemeChangesDesktopIcons",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes","ThemeChangesMousePointers",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize","ColorPrevalence",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize","EnableTransparency",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing","State",%REG_DWORD%,146432 ; 0x00023c00
HKO,"SOFTWARE\Microsoft\Windows\DWM","Composition",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows\TabletPC\Snipping Tool",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\TabletPC\TabSetup",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Devices","Microsoft XPS Document Writer",%REG_SZ%,"winspool,Ne00:"
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Devices","Microsoft Print to PDF",%REG_SZ%,"winspool,Ne01:"
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Devices","Fax",%REG_SZ%,"winspool,Ne02:"
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ICM",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MsiCorruptedFileRecovery\RepairedProducts","AnyIdMax",%REG_DWORD%,5 ; 0x00000005
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MsiCorruptedFileRecovery\RepairedProducts","SameIdMax",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MsiCorruptedFileRecovery\RepairedProducts","TimeWindowMinutes",%REG_DWORD%,1440 ; 0x000005a0
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\PrinterPorts","Microsoft XPS Document Writer",%REG_SZ%,"winspool,Ne00:,15,45"
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\PrinterPorts","Microsoft Print to PDF",%REG_SZ%,"winspool,Ne01:,15,45"
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\PrinterPorts","Fax",%REG_SZ%,"winspool,Ne02:,15,45"
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\TileDataModel\Migration",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","Device",%REG_SZ%,""
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","IsMRUEstablished",%REG_DWORD%,4294967295 ; 0xffffffff
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows","LegacyDefaultPrinterMode",%REG_DWORD%,4294967295 ; 0xffffffff
HKO,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\Pen","PenArbitrationType",%REG_DWORD%,3 ; 0x00000003
HKO,"SOFTWARE\Microsoft\Wisp\MultiTouch",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","DblDist",%REG_DWORD%,20 ; 0x00000014
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","DblTime",%REG_DWORD%,300 ; 0x0000012c
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","EraseEnable",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","FlickMode",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","FlickTolerance",%REG_DWORD%,50 ; 0x00000032
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","HoldMode",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","HoldTime",%REG_DWORD%,2300 ; 0x000008fc
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","RightMaskEnable",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","Splash",%REG_DWORD%,50 ; 0x00000032
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","TapTime",%REG_DWORD%,100 ; 0x00000064
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters","WaitTime",%REG_DWORD%,300 ; 0x0000012c
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\CustomFlickCommands",,%REG_KEYONLY%
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","down",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","downLeft",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","downRight",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","left",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","right",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","up",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","upLeft",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Pen\SysEventParameters\FlickCommands","upRight",%REG_SZ%,"{00000000-0000-0000-0000-000000000000}"
HKO,"SOFTWARE\Microsoft\Wisp\Touch","Bouncing",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Wisp\Touch","Friction",%REG_DWORD%,50 ; 0x00000032
HKO,"SOFTWARE\Microsoft\Wisp\Touch","Inertia",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Wisp\Touch","TouchMode_hold",%REG_DWORD%,1 ; 0x00000001
HKO,"SOFTWARE\Microsoft\Wisp\Touch","TouchModeN_DtapDist",%REG_DWORD%,50 ; 0x00000032
HKO,"SOFTWARE\Microsoft\Wisp\Touch","TouchModeN_DtapTime",%REG_DWORD%,50 ; 0x00000032
HKO,"SOFTWARE\Microsoft\Wisp\Touch","TouchModeN_HoldTime_Animation",%REG_DWORD%,50 ; 0x00000032
HKO,"SOFTWARE\Microsoft\Wisp\Touch","TouchModeN_HoldTime_BeforeAnimation",%REG_DWORD%,50 ; 0x00000032
HKO,"SOFTWARE\Microsoft\Wisp\Touch","TouchUI",%REG_DWORD%,0 ; 0x00000000
HKO,"SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\Cache",,%REG_KEYONLY%
HKO,"SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Cache",,%REG_KEYONLY%
HKO,"SOFTWARE\Policies\Power\PowerSettings",,%REG_KEYONLY%
HKO,"System\CurrentControlSet\Control\Network\NetworkLocationWizard","ShowCount",%REG_DWORD%,0 ; 0x00000000

; EOF

Downloads

The console application is available in two functional identical forms: OFFREG.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and OFFREG.COM, a small form without these extras.

Implementation and Build Details

Offline Registry Reader is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Offline Registry Reader from the source presented hereafter.
  1. Create the text file OFFREG.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    #include <sddl.h>
    #include <offreg.h>
    
    #define memcpy	__movsb
    #define wmemcpy	__movsw
    
    #define MAX_DEPTH		512UL
    #define MAX_KEY_LENGTH		255UL
    #define MAX_VALUE_NAME		16383UL
    #define MAX_VALUE_DATA		1048576UL
    
    typedef	unsigned long long	QWORD, *LPQWORD;
    
    BYTE	cbData[MAX_VALUE_DATA];
    WCHAR	szKey[(MAX_KEY_LENGTH + 1) * MAX_DEPTH];
    WCHAR	szValue[MAX_VALUE_NAME + 1];
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	LPBYTE	lpOutput;
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	dwOutput *= sizeof(*szOutput);
    	lpOutput = (LPBYTE) szOutput;
    
    	do
    	{
    		if (!WriteFile(hFile, lpOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpOutput += dwFile;
    		dwOutput -= dwFile;
    	} while (dwOutput != 0);
    
    	return TRUE;
    }
    
    #define PrintString(HANDLE, LITERAL)	PrintDirect(HANDLE, LITERAL, sizeof(LITERAL) / sizeof(*LITERAL) - 1)
    
    __inline
    BOOL	WINAPI	PrintDirect(HANDLE hFile, LPCWSTR lpString, DWORD dwString)
    {
    	DWORD	dwFile;
    
    	dwString *= sizeof(*lpString);
    
    	do
    	{
    		if (!WriteFile(hFile, lpString, dwString, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpString = (LPCWSTR) ((LPBYTE) lpString + dwFile);
    		dwString -= dwFile;
    	} while (dwString != 0);
    
    	return TRUE;
    }
    
    __inline
    LPCWSTR	WINAPI	InfEscape(LPCWSTR lpString)
    {
    	do
    		if ((*lpString == L'"')
    		 || (*lpString == L'%'))
    			return lpString;
    	while (*lpString++ != L'\0');
    
    	return NULL;
    }
    
    #ifndef TINY
    const	WCHAR	szBytes[256][4] = {L",00", L",01", L",02", L",03", L",04", L",05", L",06", L",07", L",08", L",09", L",0a", L",0b", L",0c", L",0d", L",0e", L",0f",
    		                   L",10", L",11", L",12", L",13", L",14", L",15", L",16", L",17", L",18", L",19", L",1a", L",1b", L",1c", L",1d", L",1e", L",1f",
    		                   L",20", L",21", L",22", L",23", L",24", L",25", L",26", L",27", L",28", L",29", L",2a", L",2b", L",2c", L",2d", L",2e", L",2f",
    		                   L",30", L",31", L",32", L",33", L",34", L",35", L",36", L",37", L",38", L",39", L",3a", L",3b", L",3c", L",3d", L",3e", L",3f",
    		                   L",40", L",41", L",42", L",43", L",44", L",45", L",46", L",47", L",48", L",49", L",4a", L",4b", L",4c", L",4d", L",4e", L",4f",
    		                   L",50", L",51", L",52", L",53", L",54", L",55", L",56", L",57", L",58", L",59", L",5a", L",5b", L",5c", L",5d", L",5e", L",5f",
    		                   L",60", L",61", L",62", L",63", L",64", L",65", L",66", L",67", L",68", L",69", L",6a", L",6b", L",6c", L",6d", L",6e", L",6f",
    		                   L",70", L",71", L",72", L",73", L",74", L",75", L",76", L",77", L",78", L",79", L",7a", L",7b", L",7c", L",7d", L",7e", L",7f",
    		                   L",80", L",81", L",82", L",83", L",84", L",85", L",86", L",87", L",88", L",89", L",8a", L",8b", L",8c", L",8d", L",8e", L",8f",
    		                   L",90", L",91", L",92", L",93", L",94", L",95", L",96", L",97", L",98", L",99", L",9a", L",9b", L",9c", L",9d", L",9e", L",9f",
    		                   L",a0", L",a1", L",a2", L",a3", L",a4", L",a5", L",a6", L",a7", L",a8", L",a9", L",aa", L",ab", L",ac", L",ad", L",ae", L",af",
    		                   L",b0", L",b1", L",b2", L",b3", L",b4", L",b5", L",b6", L",b7", L",b8", L",b9", L",ba", L",bb", L",bc", L",bd", L",be", L",bf",
    		                   L",c0", L",c1", L",c2", L",c3", L",c4", L",c5", L",c6", L",c7", L",c8", L",c9", L",ca", L",cb", L",cc", L",cd", L",ce", L",cf",
    		                   L",d0", L",d1", L",d2", L",d3", L",d4", L",d5", L",d6", L",d7", L",d8", L",d9", L",da", L",db", L",dc", L",dd", L",de", L",df",
    		                   L",e0", L",e1", L",e2", L",e3", L",e4", L",e5", L",e6", L",e7", L",e8", L",e9", L",ea", L",eb", L",ec", L",ed", L",ee", L",ef",
    		                   L",f0", L",f1", L",f2", L",f3", L",f4", L",f5", L",f6", L",f7", L",f8", L",f9", L",fa", L",fb", L",fc", L",fd", L",fe", L",ff"};
    #endif
    
    const	LPCWSTR	szType[12] = {L"NONE",
    		              L"SZ",
    		              L"EXPAND_SZ",
    		              L"BINARY",
    		              L"DWORD",		// alias DWORD_LITTLE_ENDIAN
    		              L"DWORD_BIG_ENDIAN",
    		              L"LINK",
    		              L"MULTI_SZ",
    		              L"RESOURCE_LIST",
    		              L"FULL_RESOURCE_DESCRIPTOR",
    		              L"RESOURCE_REQUIREMENTS_LIST",
    		              L"QWORD"};	// alias QWORD_LITTLE_ENDIAN
    
    DWORD	WINAPI	Offline(HANDLE hConsole, HANDLE hOutput, ORHKEY hkKey, DWORD dwKey)
    {
    	BOOL	bOutput;
    	ORHKEY	hkSubKey;
    	LPCWSTR	lpSubKey = szKey + dwKey + 1;
    	LPCWSTR	lpData, lpEscape, lpLast, lpMulti;
    #ifdef SANITY
    	LPCWSTR	lpCount;
    	DWORD	dwCount, dwChars;
    #endif
    	DWORD	dwError;
    	DWORD	dwSubKeys, dwSubKey;
    	DWORD	dwValues, dwValue, dwType, dwData, dwBytes;
    #ifdef SECURITY
    	dwData = sizeof(cbData);
    
    	dwError = ORGetKeySecurity(hkKey,
    	                           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
    	                           cbData,
    	                           &dwData);
    
    	if (dwError != ERROR_SUCCESS)
    		PrintConsole(hConsole,
    		             L"ORGetKeySecurity() returned error %lu for registry key \'%ls\'\n",
    		             dwError, szKey);
    	else
    		if (!ConvertSecurityDescriptorToStringSecurityDescriptor(cbData,
    		                                                         SDDL_REVISION_1,
    		                                                         OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
    		                                                         &lpData,
    		                                                         (LPDWORD) NULL))
    			PrintConsole(hConsole,
    			             L"ConvertSecurityDescriptorToStringSecurityDescriptor() returned error %lu for registry key \'%ls\'\n",
    			             dwError = GetLastError(), szKey);
    		else
    		{
    			if (dwKey < sizeof("HKEY_OFFLINE"))
    				bOutput = PrintString(hOutput,
    				                      L"HKO,,,%REG_KEYONLY%\r\n");
    			else
    				bOutput = PrintFormat(hOutput,
    				                      L"HKO,\"%ls\",,%%REG_KEYONLY%%\r\n",
    				                      szKey + sizeof("HKEY_OFFLINE"));
    
    			bOutput &= PrintString(hOutput, L"; ");
    			bOutput &= PrintDirect(hOutput, lpData, wcslen(lpData));
    			bOutput &= PrintString(hOutput, L"\r\n");
    
    			if (!bOutput)
    				PrintConsole(hConsole,
    				             L"WriteFile() returned error %lu for registry key \'%ls\'\n",
    				             dwError = GetLastError(), szKey);
    
    			if (LocalFree(lpData) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    #endif
    	for (dwValues = 0;; dwValues++)
    	{
    	//	*szValue = L'\0';
    		dwValue = sizeof(szValue) / sizeof(*szValue);
    		dwData = sizeof(cbData);
    
    		dwError = OREnumValue(hkKey,
    		                      dwValues,
    		                      szValue,
    		                      &dwValue,
    		                      &dwType,
    		                      cbData,
    		                      &dwData);
    
    		if (dwError == ERROR_NO_MORE_ITEMS)
    			break;
    
    		if (dwError != ERROR_SUCCESS)
    			PrintConsole(hConsole,
    			             L"OREnumValue() returned error %lu for registry key \'%ls\'\n",
    			             dwError, szKey);
    		else
    		{
    #ifdef SANITY
    			dwChars = wcslen(szValue);
    
    			if (dwValue < dwChars)
    				PrintConsole(hConsole,
    				             L"ERROR: size (%lu characters) of value name \'%ls\' in registry key \'%ls\' smaller than actual string length (%lu characters)!\n",
    				             dwValue, szValue, dwChars, szKey);
    			else if (dwValue > dwChars)
    				PrintConsole(hConsole,
    				             L"WARNING: size (%lu characters) of value name \'%ls\' in registry key \'%ls\' greater than actual string length (%lu characters)\n",
    				             dwValue, szValue, dwChars, szKey);
    
    			if (dwData == 0)
    				PrintConsole(hConsole,
    				             L"WARNING: no value data for value name \'%ls\' in registry key \'%ls\'\n",
    				             szValue, szKey);
    			else
    				switch (dwType)
    				{
    				case REG_LINK:
    
    					if (dwData % sizeof(L'\0') != 0)
    						PrintConsole(hConsole,
    						             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' not a multiple of WCHAR size!\n",
    						             dwData, szValue, szKey);
    					break;
    
    				case REG_DWORD_BIG_ENDIAN:
    				case REG_DWORD_LITTLE_ENDIAN:
    			//	case REG_DWORD:
    
    					if (dwData < sizeof(DWORD))
    						PrintConsole(hConsole,
    						             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than DWORD size!\n",
    						             dwData, szValue, szKey);
    					else if (dwData > sizeof(DWORD))
    						PrintConsole(hConsole,
    						             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than DWORD size\n",
    						             dwData, szValue, szKey);
    					break;
    
    				case REG_QWORD_LITTLE_ENDIAN:
    			//	case REG_QWORD:
    
    					if (dwData < sizeof(QWORD))
    						PrintConsole(hConsole,
    						             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than QWORD size!\n",
    						             dwData, szValue, szKey);
    					else if (dwData > sizeof(QWORD))
    						PrintConsole(hConsole,
    						             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than QWORD size\n",
    						             dwData, szValue, szKey);
    					break;
    
    				case REG_SZ:
    				case REG_EXPAND_SZ:
    
    					dwChars = wcslen((LPCWSTR) cbData);
    					dwBytes = (dwChars + 1) * sizeof(L'\0');
    
    					if (dwData < dwBytes)
    						PrintConsole(hConsole,
    						             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than actual string length (%lu + 1 characters = %lu bytes)\n",
    						             dwData, szValue, szKey, dwChars, dwBytes);
    					else if (dwData > dwBytes)
    						PrintConsole(hConsole,
    						             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than actual string length (%lu + 1 characters = %lu bytes)\n",
    						             dwData, szValue, szKey, dwChars, dwBytes);
    					break;
    
    				case REG_MULTI_SZ:
    
    					dwChars = 0;
    					dwCount = 1;
    					lpCount = (LPCWSTR) cbData;
    
    					while (*lpCount != L'\0')
    					{
    						dwChars += wcslen(lpCount);
    						dwCount++;
    						lpCount += wcslen(lpCount) + 1;
    					}
    
    					dwBytes = (dwChars + dwCount) * sizeof(L'\0');
    
    					if (dwData < dwBytes)
    						PrintConsole(hConsole,
    						             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than sum of actual string lengths (%lu + %lu characters = %lu bytes)\n",
    						             dwData, szValue, szKey, dwChars, dwCount, dwBytes);
    					else if (dwData > dwBytes)
    						PrintConsole(hConsole,
    						             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than sum of actual string lengths (%lu + %lu characters = %lu bytes)\n",
    						             dwData, szValue, szKey, dwChars, dwCount, dwBytes);
    					break;
    
    			//	case REG_NONE:
    			//	case REG_BINARY:
    			//	case REG_RESOURCE_LIST:
    			//	case REG_FULL_RESOURCE_DESCRIPTOR:
    			//	case REG_RESOURCE_REQUIREMENTS_LIST:
    				}
    #ifdef UNKNOWN
    			if (dwType > REG_QWORD)
    				PrintConsole(hConsole,
    				             L"WARNING: unknown data type (0x%08lx) for value name \'%ls\' in registry key \'%ls\'\n",
    				             dwType, szValue, szKey);
    #endif
    #endif // SANITY
    			if (dwKey < sizeof("HKEY_OFFLINE"))
    				bOutput = PrintFormat(hOutput,
    				                      L"HKO,,");
    			else
    				bOutput = PrintFormat(hOutput,
    				                      L"HKO,\"%ls\",",
    				                      szKey + sizeof("HKEY_OFFLINE"));
    
    			if (dwType < sizeof(szType) / sizeof(*szType))
    				if (dwValue == 0)
    					bOutput &= PrintFormat(hOutput, L",%%REG_%ls%%", szType[dwType]);
    				else
    					bOutput &= PrintFormat(hOutput, L"\"%ls\",%%REG_%ls%%", szValue, szType[dwType]);
    			else
    				if (dwValue == 0)
    					bOutput &= PrintFormat(hOutput, L",0x%08lx", dwType);
    				else
    					bOutput &= PrintFormat(hOutput, L"\"%ls\",0x%08lx", szValue, dwType);
    
    			if (dwData == 0)
    				bOutput &= PrintString(hOutput, L"\r\n");
    			else
    				switch (dwType)
    				{
    				case REG_LINK:
    
    					if (dwData % sizeof(L'\0') != 0)
    						goto DEFAULT;
    
    					bOutput &= PrintString(hOutput, L",\"");
    					bOutput &= PrintDirect(hOutput, (LPCWSTR) cbData, dwData / sizeof(L'\0'));
    					bOutput &= PrintString(hOutput, L"\"\r\n");
    
    					break;
    
    				case REG_SZ:
    				case REG_EXPAND_SZ:
    
    					if (dwData % sizeof(L'\0') != 0)
    						goto DEFAULT;
    
    					if (*(LPCWSTR) cbData == L'\0')
    						bOutput &= PrintString(hOutput, L",\"\"\r\n");
    					else
    					{
    						lpData = (LPCWSTR) cbData;
    						((LPWSTR) lpData)[dwData / sizeof(L'\0')] = L'\0';
    
    						dwData = wcslen(lpData);
    
    						bOutput &= PrintString(hOutput, L",\"");
    
    						for (lpEscape = InfEscape(lpData); lpEscape != NULL; lpData = lpEscape, lpEscape = InfEscape(lpEscape + 1))
    							bOutput &= PrintDirect(hOutput, lpData, lpEscape + 1 - lpData);
    
    						bOutput &= PrintDirect(hOutput, lpData, (LPCWSTR) cbData + dwData - lpData);
    						bOutput &= PrintString(hOutput, L"\"\r\n");
    					}
    
    					break;
    
    				case REG_MULTI_SZ:
    
    					if (dwData % sizeof(L'\0') != 0)
    						goto DEFAULT;
    
    					if ((dwData == sizeof(L'\0'))
    					 && (*(LPCWSTR) cbData == L'\0'))
    						bOutput &= PrintString(hOutput, L";\r\n");
    					else
    					{
    						lpData = (LPCWSTR) cbData;
    						dwData /= sizeof(L'\0');
    						lpLast = lpData + dwData;
    
    						if ((dwData > 1)
    						 && (lpData[dwData - 1] == L'\0')
    						 && (lpData[dwData - 2] == L'\0'))
    							lpLast--;
    						else
    							*(LPWSTR) lpLast = L'\0';
    
    						do
    							if (*lpData == L'\0')
    								bOutput &= PrintString(hOutput, L";\"\"");
    							else
    							{
    								dwData = wcslen(lpData);
    
    								bOutput &= PrintString(hOutput, L",\"");
    
    								for (lpEscape = InfEscape(lpMulti = lpData), lpData += dwData;
    								     lpEscape != NULL; lpMulti = lpEscape,
    								     lpEscape = InfEscape(lpEscape + 1))
    									bOutput &= PrintDirect(hOutput, lpMulti, lpEscape + 1 - lpMulti);
    
    								bOutput &= PrintDirect(hOutput, lpMulti, lpData - lpMulti);
    								bOutput &= PrintString(hOutput, L"\"");
    							}
    						while (++lpData < lpLast);
    
    						bOutput &= PrintString(hOutput, L"\r\n");
    					}
    
    					break;
    
    				case REG_DWORD_BIG_ENDIAN:
    
    					if (dwData != sizeof(DWORD))
    						goto DEFAULT;
    #if 0
    					bOutput &= PrintFormat(hOutput, L",%lu\r\n", _byteswap_ulong(*(LPDWORD) cbData));
    #else
    					bOutput &= PrintFormat(hOutput, L",%lu ; 0x%08lx\r\n", _byteswap_ulong(*(LPDWORD) cbData), *(LPDWORD) cbData);
    #endif
    					break;
    
    				case REG_DWORD_LITTLE_ENDIAN:
    			//	case REG_DWORD:
    
    					if (dwData != sizeof(DWORD))
    						goto DEFAULT;
    #if 0
    					bOutput &= PrintFormat(hOutput, L",%lu\r\n", *(LPDWORD) cbData);
    #else
    					bOutput &= PrintFormat(hOutput, L",%lu ; 0x%08lx\r\n", *(LPDWORD) cbData, *(LPDWORD) cbData);
    #endif
    					break;
    
    				case REG_QWORD_LITTLE_ENDIAN:
    			//	case REG_QWORD:
    
    					if (dwData != sizeof(QWORD))
    						goto DEFAULT;
    #if 0
    					bOutput &= PrintFormat(hOutput, L",%I64u\r\n", *(LPQWORD) cbData);
    #else
    					bOutput &= PrintFormat(hOutput, L",%I64u ; 0x%016I64x\r\n", *(LPQWORD) cbData, *(LPQWORD) cbData);
    #endif
    					break;
    
    			//	case REG_NONE:
    			//	case REG_BINARY:
    			//	case REG_RESOURCE_LIST:
    			//	case REG_FULL_RESOURCE_DESCRIPTOR:
    			//	case REG_RESOURCE_REQUIREMENTS_LIST:
    				default:
    				DEFAULT:
    					for (dwBytes = 0; dwBytes < dwData; dwBytes++)
    #ifdef TINY
    						bOutput &= PrintFormat(hOutput, L",%02x", cbData[dwBytes]);
    #else
    						bOutput &= PrintDirect(hOutput, szBytes[cbData[dwBytes]], 3);
    #endif
    					bOutput &= PrintString(hOutput, L"\r\n");
    				}
    
    			if (!bOutput)
    				PrintConsole(hConsole,
    				             L"WriteFile() returned error %lu for value \'%ls\' of registry key \'%ls\'\n",
    				             dwError = GetLastError(), szValue, szKey);
    		}
    	}
    
    	for (dwSubKeys = 0;; dwSubKeys++)
    	{
    		dwSubKey = sizeof(szKey) / sizeof(*szKey) - dwKey - 1;
    
    		dwError = OREnumKey(hkKey,
    		                    dwSubKeys,
    		                    lpSubKey,
    		                    &dwSubKey,
    		                    (LPWSTR) NULL,
    		                    (LPDWORD) NULL,
    		                    (LPFILETIME) NULL);
    
    		if (dwError == ERROR_NO_MORE_ITEMS)
    			break;
    
    		if (dwError != ERROR_SUCCESS)
    			PrintConsole(hConsole,
    			             L"OREnumKey() returned error %lu for registry key \'%ls\'\n",
    			             dwError, szKey);
    		else
    		{
    #ifdef SANITY
    			dwChars = wcslen(lpSubKey);
    
    			if (dwChars > dwSubKey)
    				PrintConsole(hConsole,
    				             L"ERROR: size (%lu characters) of subkey name \'%ls\' in registry key \'%ls\' smaller than actual string length (%lu characters)\n",
    				             dwSubKey, lpSubKey, szKey, dwChars);
    			else if (dwChars < dwSubKey)
    				PrintConsole(hConsole,
    				             L"WARNING: size (%lu characters) of subkey name \'%ls\' in registry key \'%ls\' greater than actual string length (%lu characters)\n",
    				             dwSubKey, lpSubKey, szKey, dwChars);
    #endif // SANITY
    			szKey[dwKey] = L'\\';
    
    			dwError = OROpenKey(hkKey,
    			                    lpSubKey,
    			                    &hkSubKey);
    
    			if (dwError != ERROR_SUCCESS)
    				PrintConsole(hConsole,
    				             L"OROpenKey() returned error %lu for registry key \'%ls\'\n",
    				             dwError, szKey);
    			else
    			{
    				dwError = Offline(hConsole, hOutput, hkSubKey, dwKey + 1 + dwSubKey);
    
    				dwValue = ORCloseKey(hkSubKey);
    
    				if (dwValue != ERROR_SUCCESS)
    					PrintConsole(hConsole,
    					             L"ORCloseKey() returned error %lu for registry key \'%ls\'\n",
    					             dwValue, szKey);
    			}
    
    			szKey[dwKey] = L'\0';
    		}
    	}
    #ifndef SECURITY
    	if ((dwValues == 0) && (dwSubKeys == 0))
    	{
    		if (dwKey < sizeof("HKEY_OFFLINE"))
    			bOutput = PrintString(hOutput,
    			                      L"HKO,,,%REG_KEYONLY%\r\n");
    		else
    			bOutput = PrintFormat(hOutput,
    			                      L"HKO,\"%ls\",,%%REG_KEYONLY%%\r\n",
    			                      szKey + sizeof("HKEY_OFFLINE"));
    
    		if (!bOutput)
    			PrintConsole(hConsole,
    			             L"WriteFile() returned error %lu for empty registry key \'%ls\'\n",
    			             dwError = GetLastError(), szKey);
    	}
    #endif
    	return dwError;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	SYSTEMTIME	st;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwMajor, dwMinor;
    	HKEY	hkRoot;
    	HANDLE	hOutput;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments != 2)
    				PrintConsole(hConsole,
    				             L"Bad arguments: a single file or path name of a registry hive must be given!\n");
    			else
    			{
    				hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    				if (hOutput == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"GetStdHandle() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!FlushFileBuffers(hOutput))
    						PrintConsole(hConsole,
    						             L"FlushFileBuffers() returned error %lu: standard output is not redirected to a file!\n",
    						             dwError = GetLastError());
    					else
    					{
    						ORGetVersion(&dwMajor, &dwMinor);
    
    						PrintConsole(hConsole,
    						             L"OFFREG.DLL version %lu.%lu\n",
    						             dwMajor, dwMinor);
    
    						dwError = OROpenHive(lpArguments[1], &hkRoot);
    
    						if (dwError != ERROR_SUCCESS)
    							PrintConsole(hConsole,
    							             L"OROpenHive() returned error %lu\n",
    							             dwError);
    						else
    						{
    							GetSystemTime(&st);
    
    							if (!PrintFormat(hOutput,
    							                 L"\xFEFF"	// UTF-16LE BOM
    							                 L"[Version]\r\n"
    							                 L"DriverVer = %02hu/%02hu/%04hu,%02hu.%02hu.%02hu.%03hu ; UTC\r\n"
    							                 L"Provider  = \"Stefan Kanthak\"\r\n"
    							                 L"Signature = \"$Windows NT$\"\r\n"
    							                 L"\r\n"
    							                 L"[Strings]\r\n"
    							                 L"REG_SZ                         = 0x00000000\r\n"
    							                 L"REG_BINARY                     = 0x00000001\r\n"
    							                 L"REG_KEYONLY                    = 0x00000010\r\n"
    							                 L"REG_MULTI_SZ                   = 0x00010000\r\n"
    							                 L"REG_DWORD                      = 0x00010001\r\n"
    							                 L"REG_EXPAND_SZ                  = 0x00020000\r\n"
    							                 L"REG_NONE                       = 0x00020001\r\n"
    							                 L"REG_COMPATIBLE                 = 0x00030001 ; same as REG_BINARY\r\n"
    							                 L"REG_DWORD_LITTLE_ENDIAN        = 0x00040001 ; same as REG_DWORD\r\n"
    							                 L"REG_DWORD_BIG_ENDIAN           = 0x00050001\r\n"
    							                 L"REG_LINK                       = 0x00060000\r\n"
    							                 L"REG_RESOURCE_LIST              = 0x00080001\r\n"
    							                 L"REG_FULL_RESOURCE_DESCRIPTOR   = 0x00090001\r\n"
    							                 L"REG_RESOURCE_REQUIREMENTS_LIST = 0x000a0001\r\n"
    							                 L"REG_QWORD                      = 0x000b0001\r\n"
    							                 L"REG_QWORD_LITTLE_ENDIAN        = 0x000b0001 ; same as REG_QWORD\r\n"
    							                 L"\r\n"
    							                 L"[DefaultInstall.NT]\r\n"
    							                 L";AddReg = AddReg.HKO\r\n"
    							                 L"\r\n"
    							                 L"[AddReg.HKO]\r\n",
    							                 st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds))
    								PrintConsole(hConsole,
    								             L"WriteFile() returned error %lu\n",
    								             dwError = GetLastError());
    #if 0
    							wmemcpy(szKey, L"HKEY_OFFLINE", sizeof("HKEY_OFFLINE"));
    #else
    							memcpy(szKey, L"HKEY_OFFLINE", sizeof(L"HKEY_OFFLINE"));
    #endif
    							dwError = Offline(hConsole, hOutput, hkRoot, sizeof("HKEY_OFFLINE") - 1);
    
    							if (!PrintString(hOutput,
    							                 L"\r\n"
    							                 L"; EOF\r\n"))
    								PrintConsole(hConsole,
    								             L"WriteFile() returned error %lu\n",
    								             dwError = GetLastError());
    
    							dwError = ORCloseHive(hkRoot);
    
    							if (dwError != ERROR_SUCCESS)
    								PrintConsole(hConsole,
    								             L"ORCloseHive() returned error %lu\n",
    								             dwError);
    						}
    					}
    
    					if (!CloseHandle(hOutput))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
    Note: with the preprocessor macro SANITY defined, several consistency and sanity checks regarding the size of key and value names as well as value data and value data types are performed.

    Note: with the preprocessor macro SECURITY defined, the security descriptors of enumerated keys are printed in Security Descriptor Definition Language notation.

    Note: with the preprocessor macro TINY defined, the application gets 2036 bytes smaller, but also a little slower!

  2. Run the following four command lines to compile the source file OFFREG.C created in step 1., link the compiled object file OFFREG.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:mainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeOFFREG.COM OFFREG.C ADVAPI32.LIB KERNEL32.LIB OFFREG.LIB SHELL32.LIB USER32.LIB
    ERASE OFFREG.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    OFFREG.C
    OFFREG.C(523) : warning C4090: 'function' : different 'const' qualifiers
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Registry INF Dumper

Purpose
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source, Build Instructions and Demonstration

Purpose

Enumerate all keys and values of one or more predefined Registry branches (HKCC, HKCR, HKCU, HKLM, HKLS, HKPD, HKU) and print them as an .inf file in UTF-16LE encoding on standard output (which must be redirected to a file or piped into an application that reads from standard input, like Clip, Find or More).

Note: to dump the entire Registry specify the branches HKLM and HKU.

Synopsis

REGISTRY.COM { HKCC | HKEY_CURRENT_CONFIG | HKCR | HKEY_CLASSES_ROOT | HKCU | HKEY_CURRENT_USER | HKDD | HKEY_DYN_DATA | HKLM | HKEY_LOCAL_MACHINE | HKLS | HKEY_CURRENT_USER_LOCAL_SETTINGS | HKPD | HKEY_PERFORMANCE_DATA | HKU | HKEY_USERS } … >‹output file name›
REGISTRY.COM { HKCC | HKEY_CURRENT_CONFIG | HKCR | HKEY_CLASSES_ROOT | HKCU | HKEY_CURRENT_USER | HKDD | HKEY_DYN_DATA | HKLM | HKEY_LOCAL_MACHINE | HKLS | HKEY_CURRENT_USER_LOCAL_SETTINGS | HKPD | HKEY_PERFORMANCE_DATA | HKU | HKEY_USERS } … | CLIP.COM
REGISTRY.COM { HKCC | HKEY_CURRENT_CONFIG | HKCR | HKEY_CLASSES_ROOT | HKCU | HKEY_CURRENT_USER | HKDD | HKEY_DYN_DATA | HKLM | HKEY_LOCAL_MACHINE | HKLS | HKEY_CURRENT_USER_LOCAL_SETTINGS | HKPD | HKEY_PERFORMANCE_DATA | HKU | HKEY_USERS } … | MORE.COM
Note: when run under a user account which has the privilege SeBackupPrivilege assigned, the Registry INF Dumper enables it to enumerate all registry keys below the specified branch(es).

Note: when run under a user account which has the privilege SeSecurityPrivilege assigned, the Registry INF Dumper enables it to include the system access control list in the optionally printed security descriptors.

Demonstration

Dump the HKCC branch of the registry to the file HKCC.inf and display it afterwards:
VER
.\REGISTRY.COM HKCC 1>HKCC.inf
NET.EXE HelpMsg %ERRORLEVEL%
TYPE HKCC.inf
Microsoft Windows [Version 6.1.7601]

The operation completed successfully.

; Registry of 'AMNESIAC'

[Version]
DriverVer = 08/15/2021,12.34.56.789 ; UTC
Provider  = "Stefan Kanthak"
Signature = "$Windows NT$"

[Strings]
REG_SZ                         = 0x00000000
REG_BINARY                     = 0x00000001
REG_KEYONLY                    = 0x00000010
REG_MULTI_SZ                   = 0x00010000
REG_DWORD                      = 0x00010001
REG_EXPAND_SZ                  = 0x00020000
REG_NONE                       = 0x00020001
REG_COMPATIBLE                 = 0x00030001 ; same as REG_BINARY
REG_DWORD_LITTLE_ENDIAN        = 0x00040001 ; same as REG_DWORD
REG_DWORD_BIG_ENDIAN           = 0x00050001
REG_LINK                       = 0x00060000
REG_RESOURCE_LIST              = 0x00080001
REG_FULL_RESOURCE_DESCRIPTOR   = 0x00090001
REG_RESOURCE_REQUIREMENTS_LIST = 0x000a0001
REG_QWORD                      = 0x000b0001
REG_QWORD_LITTLE_ENDIAN        = 0x000b0001 ; same as REG_QWORD

[DefaultInstall.NT]
;AddReg = AddReg.HKU,AddReg.HKLM;AddReg.HKCU,AddReg.HKCR

[AddReg.HKCC]
HKCC,"Software\Fonts","LogPixels",%REG_DWORD%,96 ; 0x00000060
HKCC,"System\CurrentControlSet\Control\Print\Printers",,%REG_KEYONLY%;
HKCC,"System\CurrentControlSet\Control\VIDEO",,%REG_KEYONLY%;
HKCC,"System\CurrentControlSet\Enum\IDE\DISKFUJITSU_MHZ2320BJ_G2____________________0000001E\5&2223391E&0&0.0.0","CSConfigFlags",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\Enum\USBSTOR\DISK&VEN_GENERIC&PROD_FLASH_DISK&REV_8.07\4E0B595B&0","CSConfigFlags",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\SERVICES\TSDDD\DEVICE0","Attach.ToDesktop",%REG_DWORD%,1 ; 0x00000001
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","Attach.ToDesktop",%REG_DWORD%,1 ; 0x00000001
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.BitsPerPel",%REG_DWORD%,32 ; 0x00000020
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.XResolution",%REG_DWORD%,1920 ; 0x00000780
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.YResolution",%REG_DWORD%,1200 ; 0x000004b0
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.VRefresh",%REG_DWORD%,1 ; 0x00000001
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.Flags",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.XPanning",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.YPanning",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.Orientation",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","DefaultSettings.FixedOutput",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","Attach.RelativeX",%REG_DWORD%,0 ; 0x00000000
HKCC,"System\CurrentControlSet\SERVICES\VGASAVE\DEVICE0","Attach.RelativeY",%REG_DWORD%,0 ; 0x00000000

; EOF

Downloads

The console application is available in two functional identical forms: REGISTRY.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and REGISTRY.COM, a small form without these extras.

Implementation and Build Details

Registry INF Dumper is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error is not supported!

The MSDN article Console Handles provides background information.

Source, Build Instructions and Demonstration

Perform the following two (plus two optional) simple steps to build the console application Registry INF Dumper from the source presented hereafter.
  1. Create the text file REGISTRY.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define _CRT_SECURE_NO_WARNINGS
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    #include <sddl.h>
    
    #define memcpy	__movsb
    #define wmemcpy	__movsw
    
    #define MAX_DEPTH		512UL
    #define MAX_KEY_LENGTH		255UL
    #define MAX_VALUE_NAME		16383UL
    #define MAX_VALUE_DATA		1048576UL
    
    #define SE_SECURITY_PRIVILEGE	8UL	// "SeSecurityPrivilege"
    #define SE_BACKUP_PRIVILEGE	17UL	// "SeBackupPrivilege"
    
    const	TOKEN_PRIVILEGES	tpBackup = {1, {SE_BACKUP_PRIVILEGE, 0, SE_PRIVILEGE_ENABLED}};
    
    #ifdef SECURITY
    const	TOKEN_PRIVILEGES	tpSecurity = {1, {SE_SECURITY_PRIVILEGE, 0, SE_PRIVILEGE_ENABLED}};
    #endif
    
    typedef	unsigned long long	QWORD, *LPQWORD;
    
    BYTE	cbData[MAX_VALUE_DATA];
    WCHAR	szKey[(MAX_KEY_LENGTH + 1) * MAX_DEPTH];
    WCHAR	szValue[MAX_VALUE_NAME + 1];
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	LPBYTE	lpOutput;
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	dwOutput *= sizeof(*szOutput);
    	lpOutput = (LPBYTE) szOutput;
    
    	do
    	{
    		if (!WriteFile(hFile, lpOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpOutput += dwFile;
    		dwOutput -= dwFile;
    	} while (dwOutput != 0);
    
    	return TRUE;
    }
    
    #define PrintString(HANDLE, LITERAL)	PrintDirect(HANDLE, LITERAL, sizeof(LITERAL) / sizeof(*LITERAL) - 1)
    
    __inline
    BOOL	WINAPI	PrintDirect(HANDLE hFile, LPCWSTR lpString, DWORD dwString)
    {
    	DWORD	dwFile;
    
    	dwString *= sizeof(*lpString);
    
    	do
    	{
    		if (!WriteFile(hFile, lpString, dwString, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpString = (LPCWSTR) ((LPBYTE) lpString + dwFile);
    		dwString -= dwFile;
    	} while (dwString != 0);
    
    	return TRUE;
    }
    
    __inline
    LPCWSTR	WINAPI	InfEscape(LPCWSTR lpString)
    {
    	do
    		if ((*lpString == L'"')
    		 || (*lpString == L'%'))
    			return lpString;
    	while (*lpString++ != L'\0');
    
    	return NULL;
    }
    
    #ifndef TINY
    const	WCHAR	szBytes[256][4] = {L",00", L",01", L",02", L",03", L",04", L",05", L",06", L",07", L",08", L",09", L",0a", L",0b", L",0c", L",0d", L",0e", L",0f",
    		                   L",10", L",11", L",12", L",13", L",14", L",15", L",16", L",17", L",18", L",19", L",1a", L",1b", L",1c", L",1d", L",1e", L",1f",
    		                   L",20", L",21", L",22", L",23", L",24", L",25", L",26", L",27", L",28", L",29", L",2a", L",2b", L",2c", L",2d", L",2e", L",2f",
    		                   L",30", L",31", L",32", L",33", L",34", L",35", L",36", L",37", L",38", L",39", L",3a", L",3b", L",3c", L",3d", L",3e", L",3f",
    		                   L",40", L",41", L",42", L",43", L",44", L",45", L",46", L",47", L",48", L",49", L",4a", L",4b", L",4c", L",4d", L",4e", L",4f",
    		                   L",50", L",51", L",52", L",53", L",54", L",55", L",56", L",57", L",58", L",59", L",5a", L",5b", L",5c", L",5d", L",5e", L",5f",
    		                   L",60", L",61", L",62", L",63", L",64", L",65", L",66", L",67", L",68", L",69", L",6a", L",6b", L",6c", L",6d", L",6e", L",6f",
    		                   L",70", L",71", L",72", L",73", L",74", L",75", L",76", L",77", L",78", L",79", L",7a", L",7b", L",7c", L",7d", L",7e", L",7f",
    		                   L",80", L",81", L",82", L",83", L",84", L",85", L",86", L",87", L",88", L",89", L",8a", L",8b", L",8c", L",8d", L",8e", L",8f",
    		                   L",90", L",91", L",92", L",93", L",94", L",95", L",96", L",97", L",98", L",99", L",9a", L",9b", L",9c", L",9d", L",9e", L",9f",
    		                   L",a0", L",a1", L",a2", L",a3", L",a4", L",a5", L",a6", L",a7", L",a8", L",a9", L",aa", L",ab", L",ac", L",ad", L",ae", L",af",
    		                   L",b0", L",b1", L",b2", L",b3", L",b4", L",b5", L",b6", L",b7", L",b8", L",b9", L",ba", L",bb", L",bc", L",bd", L",be", L",bf",
    		                   L",c0", L",c1", L",c2", L",c3", L",c4", L",c5", L",c6", L",c7", L",c8", L",c9", L",ca", L",cb", L",cc", L",cd", L",ce", L",cf",
    		                   L",d0", L",d1", L",d2", L",d3", L",d4", L",d5", L",d6", L",d7", L",d8", L",d9", L",da", L",db", L",dc", L",dd", L",de", L",df",
    		                   L",e0", L",e1", L",e2", L",e3", L",e4", L",e5", L",e6", L",e7", L",e8", L",e9", L",ea", L",eb", L",ec", L",ed", L",ee", L",ef",
    		                   L",f0", L",f1", L",f2", L",f3", L",f4", L",f5", L",f6", L",f7", L",f8", L",f9", L",fa", L",fb", L",fc", L",fd", L",fe", L",ff"};
    #endif
    
    const	LPCWSTR	szHKey[8] = {L"HKCR",
    		             L"HKCU",
    		             L"HKLM",
    		             L"HKU",
    		             L"HKPD",
    		             L"HKCC",
    		             L"HKDD",
    		             L"HKLS"};
    
    const	LPCWSTR	szHKEY[8] = {L"HKEY_CLASSES_ROOT",
    		             L"HKEY_CURRENT_USER",
    		             L"HKEY_LOCAL_MACHINE",
    		             L"HKEY_USERS",
    		             L"HKEY_PERFORMANCE_DATA",
    		             L"HKEY_CURRENT_CONFIG",
    		             L"HKEY_DYN_DATA",
    		             L"HKEY_CURRENT_USER_LOCAL_SETTINGS"};
    
    const	DWORD	dwHKEY[8] = {sizeof("HKEY_CLASSES_ROOT"),
    		             sizeof("HKEY_CURRENT_USER"),
    		             sizeof("HKEY_LOCAL_MACHINE"),
    		             sizeof("HKEY_USERS"),
    		             sizeof("HKEY_PERFORMANCE_DATA"),
    		             sizeof("HKEY_CURRENT_CONFIG"),
    		             sizeof("HKEY_DYN_DATA"),
    		             sizeof("HKEY_CURRENT_USER_LOCAL_SETTINGS")};
    
    const	LPCWSTR	szType[12] = {L"NONE",
    		              L"SZ",
    		              L"EXPAND_SZ",
    		              L"BINARY",
    		              L"DWORD",		// alias DWORD_LITTLE_ENDIAN
    		              L"DWORD_BIG_ENDIAN",
    		              L"LINK",
    		              L"MULTI_SZ",
    		              L"RESOURCE_LIST",
    		              L"FULL_RESOURCE_DESCRIPTOR",
    		              L"RESOURCE_REQUIREMENTS_LIST",
    		              L"QWORD"};	// alias QWORD_LITTLE_ENDIAN
    
    DWORD	WINAPI	Registry(HANDLE hConsole, HANDLE hOutput, QWORD qwPrivileges, HKEY hkHKEY, DWORD dwKey)
    {
    	HKEY	hkKey;
    	BOOL	bOutput;
    	DWORD	dwError;
    	DWORD	dwIndex = (DWORD) hkHKEY ^ (DWORD) HKEY_CLASSES_ROOT;
    	DWORD	dwSubKeys, dwSubKey;
    	DWORD	dwValues, dwValue, dwType, dwData, dwBytes;
    #ifdef SANITY
    	DWORD	dwCount, dwChars;
    	LPCWSTR	lpCount;
    #endif
    	LPCWSTR	lpHKey = szHKey[dwIndex];
    	LPCWSTR	lpKey = dwKey < dwHKEY[dwIndex] ? NULL : szKey + dwHKEY[dwIndex];
    	LPCWSTR	lpSubKey = szKey + dwKey + 1;
    	LPCWSTR	lpData, lpEscape, lpLast, lpMulti;
    
    	dwError = RegOpenKeyEx(hkHKEY,
    	                       lpKey,
    	                       qwPrivileges & (1 << SE_BACKUP_PRIVILEGE) ? REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK : REG_OPTION_OPEN_LINK,
    #ifdef SECURITY
    	                       qwPrivileges & (1 << SE_SECURITY_PRIVILEGE) ? ACCESS_SYSTEM_SECURITY | KEY_READ | KEY_WOW64_64KEY : KEY_READ | KEY_WOW64_64KEY,
    #else
    	                       KEY_READ | KEY_WOW64_64KEY,
    #endif
    	                       &hkKey);
    
    	if (dwError != ERROR_SUCCESS)
    		PrintConsole(hConsole,
    		             L"RegOpenKeyEx() returned error %lu for registry key \'%ls\'\n",
    		             dwError, szKey);
    	else
    	{
    #ifdef SECURITY
    		dwData = sizeof(cbData);
    
    		dwError = RegGetKeySecurity(hkHKEY,
    		                            qwPrivileges & (1 << SE_SECURITY_PRIVILEGE) ? OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
    		                            cbData,
    		                            &dwData);
    
    		if (dwError != ERROR_SUCCESS)
    			PrintConsole(hConsole,
    			             L"RegGetKeySecurity() returned error %lu for registry key \'%ls\'\n",
    			             dwError, szKey);
    		else
    			if (!ConvertSecurityDescriptorToStringSecurityDescriptor(cbData,
    			                                                         SDDL_REVISION_1,
    			                                                         OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
    			                                                         &lpData,
    			                                                         (LPDWORD) NULL))
    				PrintConsole(hConsole,
    				             L"ConvertSecurityDescriptorToStringSecurityDescriptor() returned error %lu for registry key \'%ls\'\n",
    				             dwError = GetLastError(), szKey);
    			else
    			{
    				if (lpKey == NULL)
    					bOutput = PrintFormat(hOutput,
    					                      L"%ls,,,%%REG_KEYONLY%%\r\n",
    					                      lpHKey);
    				else
    					bOutput = PrintFormat(hOutput,
    					                      L"%ls,\"%ls\",,%%REG_KEYONLY%%\r\n",
    					                      lpHKey, lpKey);
    
    				bOutput &= PrintString(hOutput, L"; ");
    				bOutput &= PrintDirect(hOutput, lpData, wcslen(lpData));
    				bOutput &= PrintString(hOutput, L"\r\n");
    
    				if (!bOutput)
    					PrintConsole(hConsole,
    					             L"WriteFile() returned error %lu for registry key \'%ls\'\n",
    					             dwError = GetLastError(), szKey);
    
    				if (LocalFree(lpData) != NULL)
    					PrintConsole(hConsole,
    					             L"LocalFree() returned error %lu\n",
    					             GetLastError());
    			}
    #endif
    		for (dwValues = 0;; dwValues++)
    		{
    		//	*szValue = L'\0';
    			dwValue = sizeof(szValue) / sizeof(*szValue);
    			dwData = sizeof(cbData);
    
    			dwError = RegEnumValue(hkKey,
    			                       dwValues,
    			                       szValue,
    			                       &dwValue,
    			                       (LPDWORD) NULL,
    			                       &dwType,
    			                       cbData,
    			                       &dwData);
    
    			if (dwError != ERROR_SUCCESS)
    			{
    				if (dwError == ERROR_NO_MORE_ITEMS)
    					break;
    
    				PrintConsole(hConsole,
    				             L"RegEnumValue() returned error %lu for registry key \'%ls\'\n",
    				             dwError, szKey);
    
    				if (dwError == ERROR_ACCESS_DENIED)
    					break;
    			}
    			else
    			{
    #ifdef SANITY
    				dwChars = wcslen(szValue);
    
    				if (dwValue < dwChars)
    					PrintConsole(hConsole,
    					             L"ERROR: size (%lu characters) of value name \'%ls\' in registry key \'%ls\' smaller than actual string length (%lu characters)!\n",
    					             dwValue, szValue, dwChars, szKey);
    				else if (dwValue > dwChars)
    					PrintConsole(hConsole,
    					             L"WARNING: size (%lu characters) of value name \'%ls\' in registry key \'%ls\' greater than actual string length (%lu characters)\n",
    					             dwValue, szValue, dwChars, szKey);
    
    				if (dwData == 0)
    					PrintConsole(hConsole,
    					             L"WARNING: no value data for value name \'%ls\' in registry key \'%ls\'\n",
    					             szValue, szKey);
    				else
    					switch (dwType)
    					{
    					case REG_LINK:
    
    						if (dwData % sizeof(L'\0') != 0)
    							PrintConsole(hConsole,
    							             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' not a multiple of WCHAR size!\n",
    							             dwData, szValue, szKey);
    						break;
    
    					case REG_DWORD_BIG_ENDIAN:
    					case REG_DWORD_LITTLE_ENDIAN:
    				//	case REG_DWORD:
    
    						if (dwData < sizeof(DWORD))
    							PrintConsole(hConsole,
    							             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than DWORD size!\n",
    							             dwData, szValue, szKey);
    						else if (dwData > sizeof(DWORD))
    							PrintConsole(hConsole,
    							             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than DWORD size\n",
    							             dwData, szValue, szKey);
    						break;
    
    					case REG_QWORD_LITTLE_ENDIAN:
    				//	case REG_QWORD:
    
    						if (dwData < sizeof(QWORD))
    							PrintConsole(hConsole,
    							             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than QWORD size!\n",
    							             dwData, szValue, szKey);
    						else if (dwData > sizeof(QWORD))
    							PrintConsole(hConsole,
    							             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than QWORD size\n",
    							             dwData, szValue, szKey);
    						break;
    
    					case REG_SZ:
    					case REG_EXPAND_SZ:
    
    						dwChars = wcslen((LPCWSTR) cbData);
    						dwBytes = (dwChars + 1) * sizeof(L'\0');
    
    						if (dwData < dwBytes)
    							PrintConsole(hConsole,
    							             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than actual string length (%lu + 1 characters = %lu bytes)\n",
    							             dwData, szValue, szKey, dwChars, dwBytes);
    						else if (dwData > dwBytes)
    							PrintConsole(hConsole,
    							             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than actual string length (%lu + 1 characters = %lu bytes)\n",
    							             dwData, szValue, szKey, dwChars, dwBytes);
    						break;
    
    					case REG_MULTI_SZ:
    
    						dwChars = 0;
    						dwCount = 1;
    						lpCount = (LPCWSTR) cbData;
    
    						while (*lpCount != L'\0')
    						{
    							dwChars += wcslen(lpCount);
    							dwCount++;
    							lpCount += wcslen(lpCount) + 1;
    						}
    
    						dwBytes = (dwChars + dwCount) * sizeof(L'\0');
    
    						if (dwData < dwBytes)
    							PrintConsole(hConsole,
    							             L"ERROR: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' smaller than sum of actual string lengths (%lu + %lu characters = %lu bytes)\n",
    							             dwData, szValue, szKey, dwChars, dwCount, dwBytes);
    						else if (dwData > dwBytes)
    							PrintConsole(hConsole,
    							             L"WARNING: size (%lu bytes) of value data for value name \'%ls\' in registry key \'%ls\' greater than sum of actual string lengths (%lu + %lu characters = %lu bytes)\n",
    							             dwData, szValue, szKey, dwChars, dwCount, dwBytes);
    						break;
    
    				//	case REG_NONE:
    				//	case REG_BINARY:
    				//	case REG_RESOURCE_LIST:
    				//	case REG_FULL_RESOURCE_DESCRIPTOR:
    				//	case REG_RESOURCE_REQUIREMENTS_LIST:
    					}
    #ifdef UNKNOWN
    				if (dwType > REG_QWORD)
    					PrintConsole(hConsole,
    					             L"WARNING: unknown data type (0x%08lx) for value name \'%ls\' in registry key \'%ls\'\n",
    					             dwType, szValue, szKey);
    #endif
    #endif // SANITY
    				if (lpKey == NULL)
    					bOutput = PrintFormat(hOutput, L"%ls,,", lpHKey);
    				else
    					bOutput = PrintFormat(hOutput, L"%ls,\"%ls\",", lpHKey, lpKey);
    
    				if (dwType < sizeof(szType) / sizeof(*szType))
    					if (dwValue == 0)
    						bOutput &= PrintFormat(hOutput, L",%%REG_%ls%%", szType[dwType]);
    					else
    						bOutput &= PrintFormat(hOutput, L"\"%ls\",%%REG_%ls%%", szValue, szType[dwType]);
    				else
    					if (dwValue == 0)
    						bOutput &= PrintFormat(hOutput, L",0x%08lx", dwType);
    					else
    						bOutput &= PrintFormat(hOutput, L"\"%ls\",0x%08lx", dwType);
    
    				if (dwData == 0)
    					bOutput &= PrintString(hOutput, L"\r\n");
    				else
    					switch (dwType)
    					{
    					case REG_LINK:
    
    						if (dwData % sizeof(L'\0') != 0)
    							goto DEFAULT;
    
    						bOutput &= PrintString(hOutput, L",\"");
    						bOutput &= PrintDirect(hOutput, (LPCWSTR) cbData, dwData / sizeof(L'\0'));
    						bOutput &= PrintString(hOutput, L"\"\r\n");
    
    						break;
    
    					case REG_SZ:
    					case REG_EXPAND_SZ:
    
    						if (dwData % sizeof(L'\0') != 0)
    							goto DEFAULT;
    
    						if (*(LPCWSTR) cbData == L'\0')
    							bOutput &= PrintString(hOutput, L",\"\"\r\n");
    						else
    						{
    							lpData = (LPCWSTR) cbData;
    							((LPWSTR) lpData)[dwData / sizeof(L'\0')] = L'\0';
    							dwData = wcslen(lpData);
    
    							bOutput &= PrintString(hOutput, L",\"");
    
    							for (lpEscape = InfEscape(lpData); lpEscape != NULL; lpData = lpEscape, lpEscape = InfEscape(lpData + 1))
    								bOutput &= PrintDirect(hOutput, lpData, lpEscape + 1 - lpData);
    
    							bOutput &= PrintDirect(hOutput, lpData, (LPCWSTR) cbData + dwData - lpData);
    							bOutput &= PrintString(hOutput, L"\"\r\n");
    						}
    
    						break;
    
    					case REG_MULTI_SZ:
    
    						if (dwData % sizeof(L'\0') != 0)
    							goto DEFAULT;
    
    						if ((dwData == sizeof(L'\0'))
    						 && (*(LPCWSTR) cbData == L'\0'))
    							bOutput &= PrintString(hOutput, L";\r\n");
    						else
    						{
    							lpData = (LPCWSTR) cbData;
    							dwData /= sizeof(L'\0');
    							lpLast = lpData + dwData;
    
    							if ((dwData > 1)
    							 && (lpData[dwData - 1] == L'\0')
    							 && (lpData[dwData - 2] == L'\0'))
    								lpLast--;
    							else
    								*(LPWSTR) lpLast = L'\0';
    
    							do
    								if (*lpData == L'\0')
    									bOutput &= PrintString(hOutput, L";\"\"");
    								else
    								{
    									dwData = wcslen(lpData);
    
    									bOutput &= PrintString(hOutput, L",\"");
    
    									for (lpEscape = InfEscape(lpMulti = lpData), lpData += dwData;
    									     lpEscape != NULL; lpMulti = lpEscape,
    									     lpEscape = InfEscape(lpEscape + 1))
    										bOutput &= PrintDirect(hOutput, lpMulti, lpEscape + 1 - lpMulti);
    
    									bOutput &= PrintDirect(hOutput, lpMulti, lpData - lpMulti);
    									bOutput &= PrintString(hOutput, L"\"");
    								}
    							while (++lpData < lpLast);
    
    							bOutput &= PrintString(hOutput, L"\r\n");
    						}
    
    						break;
    
    					case REG_DWORD_BIG_ENDIAN:
    
    						if (dwData != sizeof(DWORD))
    							goto DEFAULT;
    #if 0
    						bOutput &= PrintFormat(hOutput, L",%lu\r\n", _byteswap_ulong(*(LPDWORD) cbData));
    #else
    						bOutput &= PrintFormat(hOutput, L",%lu ; 0x%08lx\r\n", _byteswap_ulong(*(LPDWORD) cbData), *(LPDWORD) cbData);
    #endif
    						break;
    
    					case REG_DWORD_LITTLE_ENDIAN:
    				//	case REG_DWORD:
    
    						if (dwData != sizeof(DWORD))
    							goto DEFAULT;
    #if 0
    						bOutput &= PrintFormat(hOutput, L",%lu\r\n", *(LPDWORD) cbData);
    #else
    						bOutput &= PrintFormat(hOutput, L",%lu ; 0x%08lx\r\n", *(LPDWORD) cbData, *(LPDWORD) cbData);
    #endif
    						break;
    
    					case REG_QWORD_LITTLE_ENDIAN:
    				//	case REG_QWORD:
    
    						if (dwData != sizeof(QWORD))
    							goto DEFAULT;
    #if 0
    						bOutput &= PrintFormat(hOutput, L",%I64u\r\n", *(LPQWORD) cbData);
    #else
    						bOutput &= PrintFormat(hOutput, L",%I64u ; 0x%016I64x\r\n", *(LPQWORD) cbData, *(LPQWORD) cbData);
    #endif
    						break;
    
    				//	case REG_NONE:
    				//	case REG_BINARY:
    				//	case REG_RESOURCE_LIST:
    				//	case REG_FULL_RESOURCE_DESCRIPTOR:
    				//	case REG_RESOURCE_REQUIREMENTS_LIST:
    					default:
    					DEFAULT:
    						for (dwBytes = 0; dwBytes < dwData; dwBytes++)
    #ifdef TINY
    							bOutput &= PrintFormat(hOutput, L",%02x", cbData[dwBytes]);
    #else
    							bOutput &= PrintDirect(hOutput, szBytes[cbData[dwBytes]], 3);
    #endif
    						bOutput &= PrintString(hOutput, L"\r\n");
    					}
    
    				if (!bOutput)
    					PrintConsole(hConsole,
    					             L"WriteFile() returned error %lu for value \'%ls\' of registry key \'%ls\'\n",
    					             dwError = GetLastError(), szValue, szKey);
    			}
    		}
    
    		for (dwSubKeys = 0;; dwSubKeys++)
    		{
    			dwSubKey = sizeof(szKey) / sizeof(*szKey) - dwKey - 1;
    #if 0
    			dwError = RegEnumKey(hkKey,
    			                     dwSubKeys,
    			                     lpSubKey,
    			                     dwSubKey);
    #else
    			dwError = RegEnumKeyEx(hkKey,
    			                       dwSubKeys,
    			                       lpSubKey,
    			                       &dwSubKey,
    			                       (LPDWORD) NULL,
    			                       (LPWSTR) NULL,
    			                       (LPDWORD) NULL,
    			                       (LPFILETIME) NULL);
    #endif
    			if (dwError != ERROR_SUCCESS)
    			{
    				if (dwError == ERROR_NO_MORE_ITEMS)
    					break;
    
    				PrintConsole(hConsole,
    #if 0
    				             L"RegEnumKey() returned error %lu for registry key \'%ls\'\n",
    #else
    				             L"RegEnumKeyEx() returned error %lu for registry key \'%ls\'\n",
    #endif
    				             dwError, szKey);
    
    				if (dwError == ERROR_ACCESS_DENIED)
    					break;
    			}
    			else
    			{
    #ifdef SANITY
    				dwChars = wcslen(lpSubKey);
    
    				if (dwChars > dwSubKey)
    					PrintConsole(hConsole,
    					             L"ERROR: size (%lu characters) of subkey name \'%ls\' in registry key \'%ls\' smaller than actual string length (%lu characters)\n",
    					             dwSubKey, lpSubKey, szKey, dwChars);
    				else if (dwChars < dwSubKey)
    					PrintConsole(hConsole,
    					             L"WARNING: size (%lu characters) of subkey name \'%ls\' in registry key \'%ls\' greater than actual string length (%lu characters)\n",
    					             dwSubKey, lpSubKey, szKey, dwChars);
    #endif
    				szKey[dwKey] = L'\\';
    
    				dwError = Registry(hConsole, hOutput, qwPrivileges, hkHKEY, dwKey + 1 + dwSubKey);
    
    				szKey[dwKey] = L'\0';
    			}
    		}
    #ifndef SECURITY
    		if ((dwValues == 0) && (dwSubKeys == 0))
    		{
    			if (lpKey == NULL)
    				bOutput = PrintFormat(hOutput,
    				                      L"%ls,,,%%REG_KEYONLY%%\r\n",
    				                      lpHKey);
    			else
    				bOutput = PrintFormat(hOutput,
    				                      L"%ls,\"%ls\",,%%REG_KEYONLY%%\r\n",
    				                      lpHKey, lpKey);
    
    			if (!bOutput)
    				PrintConsole(hConsole,
    				             L"WriteFile() returned error %lu for empty registry key \'%ls\'\n",
    				             dwError = GetLastError(), szKey);
    		}
    #endif
    		dwValue = RegCloseKey(hkKey);
    
    		if (dwValue != ERROR_SUCCESS)
    			PrintConsole(hConsole,
    			             L"RegCloseKey() returned error %lu for registry key \'%ls\'\n",
    			             dwValue, szKey);
    	}
    
    	return dwError;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	SYSTEMTIME	st;
    
    	INT	nArgument = 1;
    	INT	nArguments;
    	LPWSTR	*lpArguments;
    	WCHAR	szComputer[MAX_COMPUTERNAME_LENGTH + 1] = L"<unknown>";
    	DWORD	dwComputer = sizeof(szComputer) / sizeof(*szComputer);
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwIndex;
    	QWORD	qwPrivileges = 0;
    	HKEY	hkHKEY;
    	HANDLE	hToken;
    	HANDLE	hProcess = GetCurrentProcess();
    	HANDLE	hOutput;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"No arguments: at least one predefined registry key name must be given!\n");
    			else
    			{
    				hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    				if (hOutput == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"GetStdHandle() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!FlushFileBuffers(hOutput))
    						PrintConsole(hConsole,
    						             L"FlushFileBuffers() returned error %lu: standard output is not redirected to a file!\n",
    						             dwError = GetLastError());
    					else
    					{
    						dwError = ERROR_SUCCESS;
    
    						if (!GetComputerName(szComputer, &dwComputer))
    							PrintConsole(hConsole,
    							             L"GetComputerName() returned error %lu\n",
    							             dwError = GetLastError());
    
    						GetSystemTime(&st);
    
    						if (!PrintFormat(hOutput,
    						                 L"\xFEFF"	// UTF-16LE BOM
    						                 L"; Registry of \'%ls\'\r\n"
    						                 L"\r\n"
    						                 L"[Version]\r\n"
    						                 L"DriverVer = %02hu/%02hu/%04hu,%02hu.%02hu.%02hu.%03hu ; UTC\r\n"
    						                 L"Provider  = \"Stefan Kanthak\"\r\n"
    						                 L"Signature = \"$Windows NT$\"\r\n"
    						                 L"\r\n"
    						                 L"[Strings]\r\n"
    						                 L"REG_SZ                         = 0x00000000\r\n"
    						                 L"REG_BINARY                     = 0x00000001\r\n"
    						                 L"REG_KEYONLY                    = 0x00000010\r\n"
    						                 L"REG_MULTI_SZ                   = 0x00010000\r\n"
    						                 L"REG_DWORD                      = 0x00010001\r\n"
    						                 L"REG_EXPAND_SZ                  = 0x00020000\r\n"
    						                 L"REG_NONE                       = 0x00020001\r\n"
    						                 L"REG_COMPATIBLE                 = 0x00030001 ; same as REG_BINARY\r\n"
    						                 L"REG_DWORD_LITTLE_ENDIAN        = 0x00040001 ; same as REG_DWORD\r\n"
    						                 L"REG_DWORD_BIG_ENDIAN           = 0x00050001\r\n"
    						                 L"REG_LINK                       = 0x00060000\r\n"
    						                 L"REG_RESOURCE_LIST              = 0x00080001\r\n"
    						                 L"REG_FULL_RESOURCE_DESCRIPTOR   = 0x00090001\r\n"
    						                 L"REG_RESOURCE_REQUIREMENTS_LIST = 0x000a0001\r\n"
    						                 L"REG_QWORD                      = 0x000b0001\r\n"
    						                 L"REG_QWORD_LITTLE_ENDIAN        = 0x000b0001 ; same as REG_QWORD\r\n"
    						                 L"\r\n"
    						                 L"[DefaultInstall.NT]\r\n"
    						                 L";AddReg = AddReg.HKU,AddReg.HKLM;AddReg.HKCU,AddReg.HKCR\r\n",
    						                 szComputer,
    						                 st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds))
    							PrintConsole(hConsole,
    							             L"WriteFile() returned error %lu\n",
    							             dwError = GetLastError());
    
    						if (!OpenProcessToken(hProcess,
    						                      TOKEN_ADJUST_PRIVILEGES,
    						                      &hToken))
    							PrintConsole(hConsole,
    							             L"OpenProcessToken() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							if (!AdjustTokenPrivileges(hToken,
    							                           FALSE,
    							                           &tpBackup,
    							                           sizeof(TOKEN_PRIVILEGES),
    							                           (TOKEN_PRIVILEGES *) NULL,
    							                           (LPDWORD) NULL))
    								PrintConsole(hConsole,
    								             L"AdjustTokenPrivileges() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    								if (GetLastError() == ERROR_SUCCESS)
    									qwPrivileges |= 1 << SE_BACKUP_PRIVILEGE;
    #ifdef SECURITY
    							if (!AdjustTokenPrivileges(hToken,
    							                           FALSE,
    							                           &tpSecurity,
    							                           sizeof(TOKEN_PRIVILEGES),
    							                           (TOKEN_PRIVILEGES *) NULL,
    							                           (LPDWORD) NULL))
    								PrintConsole(hConsole,
    								             L"AdjustTokenPrivileges() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    								if (GetLastError() == ERROR_SUCCESS)
    									qwPrivileges |= 1 << SE_SECURITY_PRIVILEGE;
    #endif
    							if (!CloseHandle(hToken))
    								PrintConsole(hConsole,
    								             L"CloseHandle() returned error %lu\n",
    								             GetLastError());
    						}
    
    						do
    						{
    							hkHKEY = HKEY_CLASSES_ROOT;
    
    							do
    							{
    								dwIndex = (DWORD) hkHKEY ^ (DWORD) HKEY_CLASSES_ROOT;
    
    								if ((wcscmp(szHKey[dwIndex], lpArguments[nArgument]) != 0)
    								 && (wcscmp(szHKEY[dwIndex], lpArguments[nArgument]) != 0))
    									continue;
    
    								memcpy(szKey, szHKEY[dwIndex], dwHKEY[dwIndex] * sizeof(*szKey));
    
    								if (!PrintFormat(hOutput,
    								                 L"\r\n"
    								                 L"[AddReg.%ls]\r\n",
    								                 szHKey[dwIndex]))
    									PrintConsole(hConsole,
    									             L"WriteFile() returned error %lu\n",
    									             dwError = GetLastError());
    
    								dwError = Registry(hConsole, hOutput, qwPrivileges, hkHKEY, dwHKEY[dwIndex] - 1);
    
    								break;
    							}
    							while (++(DWORD) hkHKEY <= (DWORD) HKEY_CURRENT_USER_LOCAL_SETTINGS);
    
    							if ((DWORD) hkHKEY > (DWORD) HKEY_CURRENT_USER_LOCAL_SETTINGS)
    								PrintConsole(hConsole,
    								             L"Argument \'%ls\' is not a predefined registry key name!\n",
    								             lpArguments[nArgument]);
    						}
    						while (++nArgument < nArguments);
    
    						if (!PrintString(hOutput,
    						                 L"\r\n"
    						                 L"; EOF\r\n"))
    							PrintConsole(hConsole,
    							             L"WriteFile() returned error %lu\n",
    							             dwError = GetLastError());
    					}
    
    					if (!CloseHandle(hOutput))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
    Note: the output format allows to detect Registry values without data, REG_SZ, REG_EXPAND_SZ and REG_MULTI_SZ values with empty strings, REG_LINK, REG_SZ, REG_EXPAND_SZ and REG_MULTI_SZ values with (invalid) odd size, and REG_DWORD_BIG_ENDIAN, REG_DWORD_LITTLE_ENDIAN alias REG_DWORD as well as REG_QWORD_LITTLE_ENDIAN alias REG_QWORD values with sizes not matching their data type.

    Note: with the preprocessor macro SANITY defined, several consistency and sanity checks regarding the size of key and value names as well as value data and value data types are performed.

    Note: with the preprocessor macro SECURITY defined, the security descriptors of enumerated keys are printed in Security Descriptor Definition Language notation.

    Note: with the preprocessor macro TINY defined, the application gets 2036 bytes smaller, but also a little slower!

  2. Run the following four command lines to compile the source file REGISTRY.C created in step 1., link the compiled object file REGISTRY.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeREGISTRY.COM REGISTRY.C ADVAPI32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE REGISTRY.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    REGISTRY.C
    REGISTRY.C(587) : warning C4090: 'function' : different 'const' qualifiers
    REGISTRY.C(764) : warning C4090: 'function' : different 'const' qualifiers
    REGISTRY.C(819) : warning C4213: nonstandard extension used : cast on l-value
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …
  3. (Optional) Create the text file REGISTRY.XML with the following content next to the console application REGISTRY.COM built in step 2.:

    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
    <!-- Copyright (C) 2004-2024, Stefan Kanthak -->
    <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
        <assemblyIdentity name="eSKamation.Tidbits.Registry INF Dumper" processorArchitecture="*" type="win32" version="0.8.1.5" />
        <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
            <application>
                <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
                <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
                <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
                <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
                <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
            </application>
        </compatibility>
        <description>Registry INF Dumper</description>
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
            <security>
                <requestedPrivileges>
                    <requestedExecutionLevel level="highestAvailable" uiAccess="false" />
                </requestedPrivileges>
            </security>
        </trustInfo>
    </assembly>
  4. (Optional) Embed the application manifest REGISTRY.XML created in step 3. in the console application REGISTRY.COM built in step 2.:

    MT.EXE /CANONICALIZE /MANIFEST REGISTRY.XML /OUTPUTRESOURCE:REGISTRY.COM
    Note: the Manifest Tool MT.exe is shipped with the Windows Software Development Kit.
    Microsoft (R) Manifest Tool version 6.1.7716.0
    Copyright (c) Microsoft Corporation 2009.
    All rights reserved.

Portable Executable Resource Enumerator

Purpose
Synopsis
Downloads
Implementation and Build Details
Variant 1
Variant 2
Source and Build Instructions – Variant 1
Source and Build Instructions – Variant 2

Purpose

Enumerate resources embedded in portable executable image files, i.e. applications, (resource) DLLs, drivers etc., print their metadata and information representable as text in UTF-16LE encoding on standard output (which must be redirected to a file or piped into an application that reads from standard input, like Clip, Find or More).

Synopsis

RESOURCE.COM ‹image file name› >‹output file name›
RESOURCE.COM ‹image file name› | CLIP.COM
RESOURCE.COM ‹image file name› | MORE.COM

Downloads

The console application is available in two functional identical forms: RESOURCE.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and RESOURCE.COM, a small form without these extras.

Implementation and Build Details

Portable Executable Resource Enumerator is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows Vista and newer versions of Windows NT as well as Windows PE 2.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error is not supported!

The MSDN article Console Handles provides background information.

Variant 1

The first, canonical variant uses the Win32 function LoadLibraryEx() to load an arbitrary portable executable image file into memory, then either the functions EnumResourceTypes(), EnumResourceNames() and EnumResourceLanguages() or the functions EnumResourceTypesEx(), EnumResourceNamesEx() and EnumResourceLanguagesEx() to enumerate all resources, followed by FindResourceEx(), SizeofResource(), LoadResource() and LockResource() to provide access to them, and finally FreeLibrary() to unload the module.

Note: the portable executable image file is located via DLL search order!

Caveat: on Windows Vista and later versions of Windows NT, these Win32 functions load and enumerate the MUI resource DLLs of a (language-neutral) portable executable image file.

Variant 2

The second, custom variant uses the Win32 functions CreateFile(), CreateFileMapping() and MapViewOfFile() to open an arbitrary file for reading and mapping it into memory, accesses the structures IMAGE_DOS_HEADER, IMAGE_FILE_HEADER, IMAGE_NT_HEADERS, IMAGE_OPTIONAL_HEADER plus IMAGE_SECTION_HEADER which describe portable executable image files to locate the .rsrc section, then calls its custom (recursive) function Resource() to enumerate and access all resources; finally it uses the Win32 functions UnmapViewOfFile() and CloseHandle() to unmap the file from memory and close it.

The MSDN articles PE Format, Peering Inside the PE: A Tour of the Win32 Portable Executable File Format, An In-Depth Look into the Win32 Portable Executable File Format and An In-Depth Look into the Win32 Portable Executable File Format, Part 2 document and explain the layout and the structures of portable executable image files.

Source and Build Instructions – Variant 1

Perform the following two simple steps to build the first variant of the console application Portable Executable Resource Enumerator from the source presented hereafter.
  1. Create the text file RESOURCE.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #define memcpy	__movsb
    #define wmemcpy	__movsw
    
    #ifndef MESSAGE_RESOURCE_ANSI
    #define MESSAGE_RESOURCE_ANSI	0
    #endif
    
    #ifndef RT_MENUEX
    #define RT_MENUEX	MAKEINTRESOURCE(13)
    #endif
    
    #ifndef RT_NAMETABLE
    #define RT_NAMETABLE	MAKEINTRESOURCE(15)
    #endif
    
    #ifndef RT_DIALOGEX
    #define RT_DIALOGEX	MAKEINTRESOURCE(18)
    #endif
    
    #ifndef RT_DLGINIT
    #define RT_DLGINIT	MAKEINTRESOURCE(240)
    #endif
    
    #ifndef RT_TOOLBAR
    #define RT_TOOLBAR	MAKEINTRESOURCE(241)
    #endif
    
    #ifndef RT_LOCALE
    #define RT_LOCALE	MAKEINTRESOURCE(255)
    #endif
    
    #define VS_BINARY	0U
    #define VS_TEXT		1U
    
    typedef	struct	_VS_VERSIONINFO
    {
    	WORD	wSize;			// size of 'VERSION' resource
    	WORD	wCount;			// = sizeof(VS_FIXEDFILEINFO)
    					//   (number of bytes in binary value)
    	WORD	wType;			// = VS_BINARY
    	WCHAR	szKey[16];		// = L"VS_VERSION_INFO"
    	WORD	wPadding;		// = 0 (alignment to DWORD)
    #if 0
    	DWORD	dwValue[13];
    #else
    	VS_FIXEDFILEINFO	vsFFI;
    #endif
    } VS_VERSIONINFO;
    
    typedef	struct	_VS_STRINGFILEINFO
    {
    	WORD	wSize;			// size of VS_STRINGFILEINFO, including all
    					//  subordinate VS_STRINGTABLEs and their VS_STRINGs
    	WORD	wCount;			// = 0 (number of characters in string value,
    					//      including the terminating NUL character)
    	WORD	wType;			// = VS_TEXT
    	WCHAR	szKey[15];		// = L"StringFileInfo"
    					// (alignment to DWORD not necessary here)
    //	WCHAR	szValue[0];		// NO value!
    } VS_STRINGFILEINFO;
    
    typedef	struct	_VS_STRINGTABLE
    {
    	WORD	wSize;			// size of VS_STRINGTABLE and all subordinate VS_STRINGs
    	WORD	wCount;			// = 0 (number of characters in string value,
    					//      including the terminating NUL character)
    	WORD	wType;			// = VS_TEXT
    	WCHAR	szKey[9];		// = L"040904B0"
    					// (alignment to DWORD not necessary here)
    //	WCHAR	szValue[0];		// NO value!
    } VS_STRINGTABLE;
    
    typedef	struct	_VS_STRING
    {
    	WORD	wSize;			// size of VS_STRING
    	WORD	wCount;			// = sizeof(szValue) / sizeof(*szValue)
    					//   (number of characters in string value,
    					//    including the terminating NUL character)
    	WORD	wType;			// = VS_TEXT
    	WCHAR	szKey[9];		// = L"Comments"
    					//   (mandatory key names are L"CompanyName",
    					//    L"FileDescription", L"FileVersion",
    					//    L"InternalName", L"OriginalFilename",
    					//    L"ProductName", L"ProductVersion";
    					//    optional key names are L"Comments",
    					//    L"LegalCopyright", L"LegalTrademarks",
    					//    L"OleSelfRegister", L"PrivateBuild",
    					//    L"SpecialBuild")
    					// (alignment to DWORD not necessary here)
    	WCHAR	szValue[ANYSIZE_ARRAY];	// = L"..."
    	WORD	wPadding;		// = 0 (alignment to DWORD)
    } VS_STRING;
    
    typedef	struct	_VS_VARFILEINFO
    {
    	WORD	wSize;			// size of VS_VARFILEINFO and subordinate VS_VAR
    	WORD	wCount;			// = 0 (number of characters in string value,
    					//      including the terminating NUL character)
    	WORD	wType;			// = VS_TEXT
    	WCHAR	szKey[12];		// = L"VarFileInfo"
    	WORD	wPadding;		// = 0 (alignment to DWORD)
    //	WCHAR	szValue[0];		// NO value!
    } VS_VARFILEINFO;
    
    typedef	struct	_VS_VAR
    {
    	WORD	wSize;			// = sizeof(VS_VAR)
    	WORD	wCount;			// = sizeof(dwValue)
    					//   (number of bytes in binary value)
    	WORD	wType;			// = VS_BINARY
    	WCHAR	szKey[12];		// = L"Translation"
    	WORD	wPadding;		// = 0 (alignment to DWORD)
    	DWORD	dwValue[ANYSIZE_ARRAY];	// = {0x04B00409, ...}
    					//   (pairs of codepage and language ids)
    } VS_VAR;
    
    typedef	struct	_MUI_RESOURCE
    {
    	DWORD	dwSignature;		// = 0xFECDFECD
    	DWORD	dwSize;			// size of "MUI" resource configuration data
    	DWORD	dwVersion;		// = 0x00010000
    	DWORD	dwUnknown;
    	DWORD	dwFileType;		// = 0x00000011: LN, language-neutral main file
    					// = 0x00000012: MUI, language-specific satellite file
    	DWORD	dwSystemAttributes;
    	DWORD	dwFallbackLocation;	// = 0x00000000: none
    					// = 0x00000001: internal
    					// = 0x00000002: external
    	BYTE	bServiceChecksum[16];
    	BYTE	bMainChecksum[16];
    	DWORD	dwReserved[6];
    	DWORD	dwTypeNameMainOffset;	// offset and size of named resource types
    	DWORD	dwTypeNameMainSize;	//  in main file (MULTI_SZ list)
    	DWORD	dwTypeIDMainOffset;	// offset and size of unnamed resource types
    	DWORD	dwTypeIDMainSize;	//  in main file (DWORD array)
    	DWORD	dwTypeNameMUIOffset;	// offset and size of named resource types
    	DWORD	dwTypeNameMUISize;	//  in satellite file (MULTI_SZ list)
    	DWORD	dwTypeIDMUIOffset;	// offset and size of unnamed resource types
    	DWORD	dwTypeIDMUISize;	//  in satellite file (DWORD array)
    	DWORD	dwLanguageNameOffset;	// offset and size of language string
    	DWORD	dwLanguageNameSize;
    	DWORD	dwFallbackNameOffset;	// offset and size of (ultimate) fallback
    	DWORD	dwFallbackNameSize;	//  language string
    	DWORD	dwPadding;
    //	DWORD	dwData[0];
    } MUI_RESOURCE;
    
    #define MUI_RESOURCE_SIGNATURE		0xFECDFECDUL
    #define MUI_RESOURCE_FILETYPE_MAIN	0x00000011UL
    #define MUI_RESOURCE_FILETYPE_SATELLITE	0x00000012UL
    #define MUI_RESOURCE_FALLBACK_NONE	0x00000000UL
    #define MUI_RESOURCE_FALLBACK_INTERNAL	0x00000001UL
    #define MUI_RESOURCE_FALLBACK_EXTERNAL	0x00000002UL
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	LPBYTE	lpOutput;
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	dwOutput *= sizeof(*szOutput);
    	lpOutput = (LPBYTE) szOutput;
    
    	do
    	{
    		if (!WriteFile(hFile, lpOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpOutput += dwFile;
    		dwOutput -= dwFile;
    	} while (dwOutput != 0);
    
    	return TRUE;
    }
    
    #define PrintString(HANDLE, LITERAL)	PrintDirect(HANDLE, LITERAL, sizeof(LITERAL) / sizeof(*LITERAL) - 1)
    
    __inline
    BOOL	WINAPI	PrintDirect(HANDLE hFile, LPCWSTR lpString, DWORD dwString)
    {
    	DWORD	dwFile;
    
    	dwString *= sizeof(*lpString);
    
    	do
    	{
    		if (!WriteFile(hFile, lpString, dwString, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpString = (LPCWSTR) ((LPBYTE) lpString + dwFile);
    		dwString -= dwFile;
    	} while (dwString != 0);
    
    	return TRUE;
    }
    
    const	LPCWSTR	szDayOfWeek[7] = {L"Sunday",
    		                  L"Monday",
    		                  L"Tuesday",
    		                  L"Wednesday",
    		                  L"Thursday",
    		                  L"Friday",
    		                  L"Saturday"};
    
    const	LPCWSTR	szFileOSHigh[] = {L"Unknown",				// VOS_UNKNOWN
    		                  L"MS-DOS",				// VOS_DOS
    		                  L"OS/2 (16-bit)",			// VOS_OS216
    		                  L"OS/2 (32-bit)",			// VOS_OS232
    		                  L"Windows NT",			// VOS_NT
    		                  L"Windows CE"};			// VOS_WINCE
    
    const	LPCWSTR	szFileOSLow[] = {L"Base",				// VOS__BASE
    		                 L"Windows (16-bit)",			// VOS__WINDOWS16
    		                 L"Presentation Manager (16-bit)",	// VOS__PM16
    		                 L"Presentation Manager (32-bit)",	// VOS__PM32
    		                 L"Windows (32-bit)"};			// VOS__WINDOWS32
    
    const	LPCWSTR	szFileType[] = {L"Unknown",				// VFT_UNKNOWN
    		                L"Application",				// VFT_APP
    		                L"DLL",					// VFT_DLL
    		                L"Driver",				// VFT_DRV
    		                L"Font",				// VFT_FONT
    		                L"Virtual Device",			// VFT_VXD
    		                L"Undefined",
    		                L"Static Library"};			// VFT_STATIC_LIB
    
    const	LPCWSTR	szFileDriverType[] = {L"Unknown",			// VFT2_UNKNOWN
    		                      L"Printer",			// VFT2_DRV_PRINTER
    		                      L"Keyboard",			// VFT2_DRV_KEYBOARD
    		                      L"Language",			// VFT2_DRV_LANGUAGE
    		                      L"Display",			// VFT2_DRV_DISPLAY
    		                      L"Mouse",				// VFT2_DRV_MOUSE
    		                      L"Network",			// VFT2_DRV_NETWORK
    		                      L"System",			// VFT2_DRV_SYSTEM
    		                      L"Installable",			// VFT2_DRV_INSTALLABLE
    		                      L"Sound",				// VFT2_DRV_SOUND
    		                      L"Communications",		// VFT2_DRV_COMM
    		                      L"Input Method",			// VFT2_DRV_INPUTMETHOD
    		                      L"Versioned Printer"};		// VFT2_DRV_VERSIONED_PRINTER
    
    const	LPCWSTR	szFileFontType[] = {L"Unknown",				// VFT2_UNKNOWN
    		                    L"Raster",				// VFT2_FONT_RASTER
    		                    L"Vector",				// VFT2_FONT_VECTOR
    		                    L"TrueType"};			// VFT2_FONT_TRUETYPE
    
    __inline
    LPCWSTR	WINAPI	MUIFileType(DWORD dwFileType)
    {
    	switch (dwFileType)
    	{
    	case MUI_RESOURCE_FILETYPE_MAIN:
    		return L"LN: language-neutral main file";
    
    	case MUI_RESOURCE_FILETYPE_SATELLITE:
    		return L"MUI: language-specific satellite file";
    
    	default:
    		return NULL;
    	}
    }
    
    __inline
    LPCWSTR	WINAPI	MUIFallbackLocation(DWORD dwFallbackLocation)
    {
    	switch (dwFallbackLocation)
    	{
    	case MUI_RESOURCE_FALLBACK_NONE:
    		return L"none";
    
    	case MUI_RESOURCE_FALLBACK_INTERNAL:
    		return L"internal";
    
    	case MUI_RESOURCE_FALLBACK_EXTERNAL:
    		return L"external";
    
    	default:
    		return NULL;
    	}
    }
    
    LPCWSTR	WINAPI	ResourceTypeName(WORD wResType)
    {
    	switch (wResType)
    	{
    	case RT_CURSOR:		// MAKEINTRESOURCE(1)
    		return L"RT_CURSOR";
    
    	case RT_BITMAP:		// MAKEINTRESOURCE(2)
    		return L"RT_BITMAP";
    
    	case RT_ICON:		// MAKEINTRESOURCE(3)
    		return L"RT_ICON";
    
    	case RT_MENU:		// MAKEINTRESOURCE(4)
    		return L"RT_MENU";
    
    	case RT_DIALOG:		// MAKEINTRESOURCE(5)
    		return L"RT_DIALOG";
    
    	case RT_STRING:		// MAKEINTRESOURCE(6)
    #if 1
    		return L"RT_STRING";
    #else
    		return L"RT_STRINGTABLE";
    #endif
    	case RT_FONTDIR:	// MAKEINTRESOURCE(7)
    		return L"RT_FONTDIR";
    
    	case RT_FONT:		// MAKEINTRESOURCE(8)
    		return L"RT_FONT";
    
    	case RT_ACCELERATOR:	// MAKEINTRESOURCE(9)
    		return L"RT_ACCELERATOR";
    
    	case RT_RCDATA:		// MAKEINTRESOURCE(10)
    		return L"RT_RCDATA";
    
    	case RT_MESSAGETABLE:	// MAKEINTRESOURCE(11)
    		return L"RT_MESSAGETABLE";
    
    	case RT_GROUP_CURSOR:	// MAKEINTRESOURCE(12)
    		return L"RT_GROUP_CURSOR";
    
    	case RT_MENUEX:		// MAKEINTRESOURCE(13)
    		return L"RT_MENUEX";
    
    	case RT_GROUP_ICON:	// MAKEINTRESOURCE(14)
    		return L"RT_GROUP_ICON";
    
    	case RT_NAMETABLE:	// MAKEINTRESOURCE(15)
    		return L"RT_NAMETABLE";
    
    	case RT_VERSION:	// MAKEINTRESOURCE(16)
    		return L"RT_VERSION";
    
    	case RT_DLGINCLUDE:	// MAKEINTRESOURCE(17)
    		return L"RT_DLGINCLUDE";
    
    	case RT_DIALOGEX:	// MAKEINTRESOURCE(18)
    		return L"RT_DIALOGEX";
    
    	case RT_PLUGPLAY:	// MAKEINTRESOURCE(19)
    		return L"RT_PLUGPLAY";
    
    	case RT_VXD:		// MAKEINTRESOURCE(20)
    		return L"RT_VXD";
    
    	case RT_ANICURSOR:	// MAKEINTRESOURCE(21)
    		return L"RT_ANICURSOR";
    
    	case RT_ANIICON:	// MAKEINTRESOURCE(22)
    		return L"RT_ANIICON";
    
    	case RT_HTML:		// MAKEINTRESOURCE(23)
    		return L"RT_HTML";
    
    	case RT_MANIFEST:	// MAKEINTRESOURCE(24)
    		return L"RT_MANIFEST";
    
    	case RT_DLGINIT:	// MAKEINTRESOURCE(240)
    		return L"RT_DLGINIT";
    
    	case RT_TOOLBAR:	// MAKEINTRESOURCE(241)
    		return L"RT_TOOLBAR";
    
    	case RT_LOCALE:		// MAKEINTRESOURCE(255)
    		return L"RT_LOCALE";
    
    	default:
    		return NULL;
    	}
    }
    
    __declspec(safebuffers)
    BOOL	WINAPI	EnumResLangProc(HMODULE hModule,
    		                LPCWSTR lpType,
    		                LPCWSTR lpName,
    		                WORD    wIDLanguage,
    		                LPARAM  lParam)
    {
    	BOOL	bOutput;
    	HANDLE	hOutput = ((HANDLE *) lParam)[1];
    	HANDLE	hConsole = ((HANDLE *) lParam)[2];
    	HRSRC	hResInfo;	// address of an IMAGE_RESOURCE_DATA_ENTRY structure
    	HGLOBAL	hResData;
    	DWORD	dwResource;
    	LPVOID	lpResource;
    	LPCWSTR	lpUnicode;
    	DWORD	dwUnicode;
    	DWORD	dwValue;
    	DWORD	dwBlock;
    	DWORD	dwEntry;
    	DWORD	dwKey;
    	DWORD	dw;
    	WCHAR	szLanguage[123];
    #ifdef LOCALE
    	WCHAR	szCountry[123];
    #endif
    	WCHAR	szFileFlags[sizeof(", Debug, Inferred, Patched, Pre-Release, Private Build, Special Build")];
    	LPWSTR	lpFileFlags;
    	LPCWSTR	lpFileOSLow, lpFileOSHigh;
    	LPCWSTR	lpFileType, lpFileSubtype;
    	LPCWSTR	lpValue;
    
    	FILETIME	ft;
    	SYSTEMTIME	st;
    	MUI_RESOURCE	*lpMUI;
    	VS_VERSIONINFO	*lpVersionInfo;
    	VS_STRINGTABLE	*lpStringTable;
    	VS_STRING	*lpString;
    	VS_VARFILEINFO	*lpVarFileInfo;
    	VS_VAR		*lpVar;
    
    	VS_STRINGFILEINFO	*lpStringFileInfo;
    	MESSAGE_RESOURCE_DATA	*lpTable;
    	MESSAGE_RESOURCE_BLOCK	*lpBlock;
    	MESSAGE_RESOURCE_ENTRY	*lpEntry;
    
    	hResInfo = FindResourceEx(hModule, lpType, lpName, wIDLanguage);
    
    	if (hResInfo == NULL)
    		PrintConsole(hConsole,
    		             L"FindResourceEx() returned error %lu\n",
    		             GetLastError());
    	else
    	{
    #ifdef LOCALE
    		if (wIDLanguage == 0)
    			bOutput = PrintString(hOutput,
    			                      L"\t\tLanguageID: 0 = 0x0000 ; Neutral\r\n");
    		else
    			if ((GetLocaleInfo(MAKELCID(wIDLanguage, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLanguage, sizeof(szLanguage) / sizeof(*szLanguage)) == 0)
    			 || (GetLocaleInfo(MAKELCID(wIDLanguage, SORT_DEFAULT), LOCALE_SENGCOUNTRY, szCountry, sizeof(szCountry) / sizeof(*szCountry)) == 0))
    			{
    				PrintConsole(hConsole,
    				             L"GetLocaleInfo() returned error %lu\n",
    				             GetLastError());
    
    				bOutput = PrintFormat(hOutput,
    				                      L"\t\tLanguageID: %hu = 0x%04hX\r\n",
    				                      wIDLanguage, wIDLanguage);
    			}
    			else
    				bOutput = PrintFormat(hOutput,
    				                      L"\t\tLanguageID: %hu = 0x%04hX ; %ls, %ls\r\n",
    				                      wIDLanguage, wIDLanguage, szLanguage, szCountry);
    #else
    		if (VerLanguageName(wIDLanguage, szLanguage, sizeof(szLanguage) / sizeof(*szLanguage)) == 0)
    		{
    			PrintConsole(hConsole,
    			             L"VerLanguageName() returned 0\n");
    
    			bOutput = PrintFormat(hOutput,
    			                      L"\t\tLanguageID: %hu = 0x%04hX\r\n",
    			                      wIDLanguage, wIDLanguage);
    		}
    		else
    			bOutput = PrintFormat(hOutput,
    			                      L"\t\tLanguageID: %hu = 0x%04hX ; %ls\r\n",
    			                      wIDLanguage, wIDLanguage, szLanguage);
    #endif
    		dwResource = SizeofResource(hModule, hResInfo);
    
    		if (dwResource == 0)
    			PrintConsole(hConsole,
    			             L"SizeofResource() returned error %lu\n",
    			             GetLastError());
    
    		bOutput &= PrintFormat(hOutput,
    		                       L"\t\t\tInfo Handle = 0x%p: Length = %lu\r\n",
    		                       hResInfo, dwResource);
    
    		hResData = LoadResource(hModule, hResInfo);
    
    		if (hResData == NULL)
    			PrintConsole(hConsole,
    			             L"LoadResource() returned error %lu\n",
    			             GetLastError());
    		else
    		{
    			lpResource = LockResource(hResData);
    
    			if (lpResource == NULL)
    				PrintConsole(hConsole,
    				             L"LockResource() returned NULL\n");
    			else
    			{
    				bOutput &= PrintFormat(hOutput,
    				                       L"\t\t\tData Handle = 0x%p: Offset = 0x%08lX\r\n",
    				                       hResData,
    				                       (DWORD) ((BYTE *) lpResource - (BYTE *) hModule) + ((DWORD) ((BYTE *) lpResource - (BYTE *) hModule) & 1));
    
    				if (IS_INTRESOURCE(lpType))
    					switch ((WORD) lpType)
    					{
    					case RT_STRING:
    
    						// NOTE: every RT_STRING resource, a STRINGTABLE, holds 16 UNICODE strings
    						//       IMAGE_RESOURCE_DIR_STRING_U of up to 65535 characters each, which
    						//       need not be L'\0' terminated and may contain L'\0', with their
    						//       character count (including the terminating L'\0' if present)
    						//       stored in front of them.
    
    						for (lpUnicode = lpResource,
    						     dwUnicode = 16; dwUnicode > 0; dwUnicode--,
    						     lpUnicode += 1 + lpUnicode[0])
    						{
    							dw = lpUnicode[0];
    
    							if (dw == 0)
    								continue;
    
    							bOutput &= PrintFormat(hOutput,
    							                       L"\t\t\t%6lu:\tLength = %lu\r\n"
    							                       L"\t\t\t\tString = ",
    							                       IS_INTRESOURCE(lpName) ? (WORD) lpName * 16 - dwUnicode : 16 - dwUnicode, dw);
    
    							while (lpUnicode[dw] == L'\0')
    								dw--;
    
    							bOutput &= PrintDirect(hOutput, lpUnicode + 1, dw);
    							bOutput &= PrintString(hOutput, L"\r\n");
    						}
    
    						break;
    
    					case RT_MESSAGETABLE:
    
    						for (lpTable = lpResource,
    						     lpBlock = lpTable->Blocks,
    						     dwBlock = 0; dwBlock < lpTable->NumberOfBlocks; dwBlock++)
    						{
    							if (lpBlock[dwBlock].LowId == lpBlock[dwBlock].HighId)
    								bOutput &= PrintFormat(hOutput,
    								                       L"\t\t\t%6lu:\tMessage ID 0x%08lX\r\n",
    								                       dwBlock, lpBlock[dwBlock].LowId);
    							else
    								bOutput &= PrintFormat(hOutput,
    								                       L"\t\t\t%6lu:\tMessage IDs 0x%08lX to 0x%08lX\r\n",
    								                       dwBlock, lpBlock[dwBlock].LowId, lpBlock[dwBlock].HighId);
    
    							for (lpEntry = (MESSAGE_RESOURCE_ENTRY *) ((BYTE *) lpTable + lpBlock[dwBlock].OffsetToEntries),
    							     dwEntry = lpBlock[dwBlock].LowId; dwEntry <= lpBlock[dwBlock].HighId; dwEntry++,
    							     lpEntry = (MESSAGE_RESOURCE_ENTRY *) ((BYTE *) lpEntry + lpEntry->Length))
    								if (lpEntry->Flags == MESSAGE_RESOURCE_UNICODE)
    									bOutput &= PrintFormat(hOutput,
    									                       L"\t\t\t\t0x%08lX:\tSize = %hu\r\n"
    									                       L"\t\t\t\t\t\tText = %.999ls\r\n",
    									                       dwEntry, lpEntry->Length, lpEntry->Text);
    								else if (lpEntry->Flags == MESSAGE_RESOURCE_ANSI)
    									bOutput &= PrintFormat(hOutput,
    									                       L"\t\t\t\t0x%08lX:\tSize = %hu\r\n"
    									                       L"\t\t\t\t\t\tText = %.999hs\r\n",
    									                       dwEntry, lpEntry->Length, lpEntry->Text);
    								else
    									PrintConsole(hConsole,
    									             L"Text type %hu of message 0x%08lX neither UNICODE nor ANSI!\n",
    									             lpEntry->Flags, dwEntry);
    						}
    
    						break;
    
    					case RT_VERSION:
    
    						lpVersionInfo = lpResource;
    
    						if (lpVersionInfo->wSize != dwResource)
    							PrintConsole(hConsole,
    							             L"Size %hu in \'VERSIONINFO\' differs from size of \'VERSION\' resource!\n",
    							             lpVersionInfo->wSize);
    
    						if (lpVersionInfo->wCount != sizeof(VS_FIXEDFILEINFO))
    							PrintConsole(hConsole,
    							             L"Count %hu in \'VERSIONINFO\' differs from size %lu of \'VS_FIXEDFILEINFO\' structure!\n",
    							             lpVersionInfo->wCount, sizeof(VS_FIXEDFILEINFO));
    
    						if (lpVersionInfo->wType != VS_BINARY)
    							PrintConsole(hConsole,
    							             L"Type %hu in \'VERSIONINFO\' not \'VS_BINARY\'!\n",
    							             lpVersionInfo->wType);
    #if 0
    						if (wcscmp(lpVersionInfo->szKey, L"VS_VERSION_INFO") != 0)
    #elif 0
    						if (wmemcmp(lpVersionInfo->szKey, L"VS_VERSION_INFO", sizeof("VS_VERSION_INFO")) != 0)
    #else
    						if (memcmp(lpVersionInfo->szKey, L"VS_VERSION_INFO", sizeof(L"VS_VERSION_INFO")) != 0)
    #endif
    							PrintConsole(hConsole,
    							             L"Key string \"%ls\" in \'VERSIONINFO\' not \"VS_VERSION_INFO\"!\n",
    							             lpVersionInfo->szKey);
    
    						if (lpVersionInfo->wPadding != 0)
    							PrintConsole(hConsole,
    							             L"Padding %hu in \'VERSIONINFO\' not 0!\n",
    							             lpVersionInfo->wPadding);
    
    						if (lpVersionInfo->vsFFI.dwSignature != VS_FFI_SIGNATURE)
    							PrintConsole(hConsole,
    							             L"Signature 0x%08lX in \'FIXEDFILEINFO\' not 0x%08lX!\n",
    							             lpVersionInfo->vsFFI.dwSignature, VS_FFI_SIGNATURE);
    
    						if (lpVersionInfo->vsFFI.dwStrucVersion != VS_FFI_STRUCVERSION)
    							PrintConsole(hConsole,
    							             L"Structure version 0x%08lX in \'FIXEDFILEINFO\' not 0x%08lX!\n",
    							             lpVersionInfo->vsFFI.dwStrucVersion, VS_FFI_STRUCVERSION);
    
    						if ((lpVersionInfo->vsFFI.dwFileFlags & lpVersionInfo->vsFFI.dwFileFlagsMask) == 0)
    #ifdef _CRT_SECURE_NO_WARNINGS
    							wcscpy(szFileFlags, L", None");
    #elif 0
    							wmemcpy(szFileFlags, L", None", sizeof(", None"));
    #else
    							memcpy(szFileFlags, L", None", sizeof(L", None"));
    #endif
    						else
    						{
    #ifdef _CRT_SECURE_NO_WARNINGS
    							*szFileFlags = L'\0';
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_DEBUG) == VS_FF_DEBUG)
    								wcscat(szFileFlags, L", Debug");
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_INFOINFERRED) == VS_FF_INFOINFERRED)
    								wcscat(szFileFlags, L", Inferred");
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_PATCHED) == VS_FF_PATCHED)
    								wcscat(szFileFlags, L", Patched");
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_PRERELEASE) == VS_FF_PRERELEASE)
    								wcscat(szFileFlags, L", Pre-Release");
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_PRIVATEBUILD) == VS_FF_PRIVATEBUILD)
    								wcscat(szFileFlags, L", Private Build");
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_SPECIALBUILD) == VS_FF_SPECIALBUILD)
    								wcscat(szFileFlags, L", Special Build");
    #else // _CRT_SECURE_NO_WARNINGS
    							lpFileFlags = szFileFlags;
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_DEBUG) == VS_FF_DEBUG)
    							{
    								memcpy(lpFileFlags, L", Debug", sizeof(L", Debug"));
    
    								lpFileFlags += sizeof(" Debug");
    							}
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_INFOINFERRED) == VS_FF_INFOINFERRED)
    							{
    								memcpy(lpFileFlags, L", Inferred", sizeof(L", Inferred"));
    
    								lpFileFlags += sizeof(" Inferred");
    							}
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_PATCHED) == VS_FF_PATCHED)
    							{
    								memcpy(lpFileFlags, L", Patched", sizeof(L", Patched"));
    
    								lpFileFlags += sizeof(" Patched");
    							}
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_PRERELEASE) == VS_FF_PRERELEASE)
    							{
    								memcpy(lpFileFlags, L", Pre-Release", sizeof(L", Pre-Release"));
    
    								lpFileFlags += sizeof(" Pre-Release");
    							}
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_PRIVATEBUILD) == VS_FF_PRIVATEBUILD)
    							{
    								memcpy(lpFileFlags, L", Private Build", sizeof(L", Private Build"));
    
    								lpFileFlags += sizeof(" Private Build");
    							}
    
    							if ((lpVersionInfo->vsFFI.dwFileFlags & VS_FF_SPECIALBUILD) == VS_FF_SPECIALBUILD)
    							{
    								memcpy(lpFileFlags, L", Special Build", sizeof(L", Special Build"));
    
    								lpFileFlags += sizeof(" Special Build");
    							}
    #endif // _CRT_SECURE_NO_WARNINGS
    						}
    
    						if (lpVersionInfo->vsFFI.dwFileType < sizeof(szFileType) / sizeof(*szFileType))
    							lpFileType = szFileType[lpVersionInfo->vsFFI.dwFileType];
    						else
    							lpFileType = L"Undefined";
    
    						if ((lpVersionInfo->vsFFI.dwFileType == VFT_DRV)
    						 && (lpVersionInfo->vsFFI.dwFileSubtype < sizeof(szFileDriverType) / sizeof(*szFileDriverType)))
    							lpFileSubtype = szFileDriverType[lpVersionInfo->vsFFI.dwFileSubtype];
    						else if ((lpVersionInfo->vsFFI.dwFileType == VFT_FONT)
    						      && (lpVersionInfo->vsFFI.dwFileSubtype < sizeof(szFileFontType) / sizeof(*szFileFontType)))
    							lpFileSubtype = szFileFontType[lpVersionInfo->vsFFI.dwFileSubtype];
    						else
    							lpFileSubtype = L"Undefined";
    
    						if (HIWORD(lpVersionInfo->vsFFI.dwFileOS) < sizeof(szFileOSHigh) / sizeof(*szFileOSHigh))
    							lpFileOSHigh = szFileOSHigh[HIWORD(lpVersionInfo->vsFFI.dwFileOS)];
    						else
    							lpFileOSHigh = L"Undefined";
    
    						if (LOWORD(lpVersionInfo->vsFFI.dwFileOS) < sizeof(szFileOSLow) / sizeof(*szFileOSLow))
    							lpFileOSLow = szFileOSLow[LOWORD(lpVersionInfo->vsFFI.dwFileOS)];
    						else
    							lpFileOSLow = L"Undefined";
    
    						bOutput &= PrintFormat(hOutput,
    						                       L"\t\t\tFixedFileInfo:\r\n"
    						                       L"\t\t\t\tProduct Version   = %hu.%hu:%hu.%hu\r\n"
    						                       L"\t\t\t\tModule Version    = %hu.%hu:%hu.%hu\r\n"
    						                       L"\t\t\t\tModule Flags      = %ls\r\n"
    						                       L"\t\t\t\tModule Type       = %ls\r\n"
    						                       L"\t\t\t\tModule Subtype    = %ls\r\n",
    						                       HIWORD(lpVersionInfo->vsFFI.dwProductVersionMS), LOWORD(lpVersionInfo->vsFFI.dwProductVersionMS),
    						                       HIWORD(lpVersionInfo->vsFFI.dwProductVersionLS), LOWORD(lpVersionInfo->vsFFI.dwProductVersionLS),
    						                       HIWORD(lpVersionInfo->vsFFI.dwFileVersionMS), LOWORD(lpVersionInfo->vsFFI.dwFileVersionMS),
    						                       HIWORD(lpVersionInfo->vsFFI.dwFileVersionLS), LOWORD(lpVersionInfo->vsFFI.dwFileVersionLS),
    						                       szFileFlags + 2,
    						                       lpFileType,
    						                       lpFileSubtype);
    
    						if ((lpVersionInfo->vsFFI.dwFileDateMS == 0)
    						 && (lpVersionInfo->vsFFI.dwFileDateLS == 0))
    							bOutput &= PrintString(hOutput, L"\t\t\t\tModule Time Stamp = None\r\n");
    						else
    						{
    							ft.dwHighDateTime = lpVersionInfo->vsFFI.dwFileDateMS;
    							ft.dwLowDateTime = lpVersionInfo->vsFFI.dwFileDateLS;
    
    							if (!FileTimeToSystemTime(&ft, &st))
    								PrintConsole(hConsole,
    								             L"FileTimeToSystemTime() returned error %lu\n",
    								             GetLastError());
    							else
    								bOutput &= PrintFormat(hOutput,
    								                       L"\t\t\t\tModule Time Stamp = %ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu.%03hu UTC\r\n",
    								                       szDayOfWeek[st.wDayOfWeek],
    								                       st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    						}
    
    						bOutput &= PrintFormat(hOutput,
    						                       L"\t\t\t\tTarget OS         = %ls, %ls\r\n",
    						                       lpFileOSHigh, lpFileOSLow);
    
    						for (lpResource = (BYTE *) lpVersionInfo + lpVersionInfo->wSize,
    						     lpVersionInfo += 1;
    						     lpVersionInfo < (VS_VERSIONINFO *) lpResource;
    						     lpVersionInfo = (VS_VERSIONINFO *) ((BYTE *) lpVersionInfo + lpVersionInfo->wSize + lpVersionInfo->wSize % sizeof(DWORD)))
    #if 0
    							if (wcscmp(lpVersionInfo->szKey, L"StringFileInfo") == 0)
    #elif 0
    							if (wmemcmp(lpVersionInfo->szKey, L"StringFileInfo", sizeof("StringFileInfo")) == 0)
    #else
    							if (memcmp(lpVersionInfo->szKey, L"StringFileInfo", sizeof(L"StringFileInfo")) == 0)
    #endif
    							{
    								lpStringFileInfo = (VS_STRINGFILEINFO *) lpVersionInfo;
    #if 0
    								if (lpStringFileInfo->wSize % sizeof(DWORD) != 0)
    									PrintConsole(hConsole,
    									             L"Size %hu in \'%ls\' not a multiple of 4!\n",
    									             lpStringFileInfo->wSize, lpStringFileInfo->szKey);
    #endif
    								if (lpStringFileInfo->wCount != 0)
    									PrintConsole(hConsole,
    									             L"Count %hu in \'%ls\' not 0!\n",
    									             lpStringFileInfo->wCount, lpStringFileInfo->szKey);
    
    								if (lpStringFileInfo->wType != VS_TEXT)
    									PrintConsole(hConsole,
    									             L"Type %hu in \'%ls\' not \'VS_TEXT\'!\n",
    									             lpStringFileInfo->wType, lpStringFileInfo->szKey);
    
    								bOutput &= PrintString(hOutput,
    								                       L"\t\t\tStringFileInfo:\r\n");
    
    								for (lpStringTable = (VS_STRINGTABLE *) (lpStringFileInfo + 1);
    								     lpStringTable < (VS_STRINGTABLE *) ((BYTE *) lpStringFileInfo + lpStringFileInfo->wSize);
    								     lpStringTable = (VS_STRINGTABLE *) ((BYTE *) lpStringTable + lpStringTable->wSize + lpStringTable->wSize % sizeof(DWORD)))
    								{
    #if 0
    									if (lpStringTable->wSize % sizeof(DWORD) != 0)
    										PrintConsole(hConsole,
    										             L"Size %hu in \'%ls\' not a multiple of 4!\n",
    										             lpStringTable->wSize, lpStringTable->szKey);
    #endif
    									if (lpStringTable->wCount != 0)
    										PrintConsole(hConsole,
    										             L"Count %hu in \'%ls\' not 0!\n",
    										             lpStringTable->wCount, lpStringTable->szKey);
    
    									if (lpStringTable->wType != VS_TEXT)
    										PrintConsole(hConsole,
    										             L"Type %hu in \'%ls\' not \'VS_TEXT\'!\n",
    										             lpStringTable->wType, lpStringTable->szKey);
    
    									bOutput &= PrintFormat(hOutput,
    									                       L"\t\t\t\t%ls:\r\n",
    									                       lpStringTable->szKey);
    
    									for (lpString = (VS_STRING *) (lpStringTable + 1);
    									     lpString < (VS_STRING *) ((BYTE *) lpStringTable + lpStringTable->wSize);
    									     lpString = (VS_STRING *) ((BYTE *) lpString + lpString->wSize + lpString->wSize % sizeof(DWORD)))
    									{
    #if 0
    										if (lpString->wSize % sizeof(DWORD) != 0)
    											PrintConsole(hConsole,
    											             L"Size %hu in \'%ls\' not a multiple of 4!\n",
    											             lpString->wSize, lpString->szKey);
    #endif
    										if (lpString->wType != VS_TEXT)
    											PrintConsole(hConsole,
    											             L"Type %hu in \'%ls\' not \'VS_TEXT\'!\n",
    											             lpString->wType, lpString->szKey);
    
    										if (lpString->wCount != 0)
    										{
    											dwKey = wcslen(lpString->szKey);
    											lpValue = lpString->szKey + (dwKey + dwKey % 2 + 1);
    
    											if (lpString->wCount != wcslen(lpValue) + 1)
    												PrintConsole(hConsole,
    												             L"Count %hu in \'%ls\' not equal number of characters in string!\n",
    												             lpString->wCount, lpString->szKey);
    
    											bOutput &= PrintFormat(hOutput,
    											                       L"\t\t\t\t\t%-16ls = %ls\r\n",
    											                       lpString->szKey, lpValue);
    										}
    										else
    											bOutput &= PrintFormat(hOutput,
    											                       L"\t\t\t\t\t%-16ls =\r\n",
    											                       lpString->szKey);
    									}
    								}
    							}
    #if 0
    							else if (wcscmp(lpVersionInfo->szKey, L"VarFileInfo") == 0)
    #elif 0
    							else if (wmemcmp(lpVersionInfo->szKey, L"VarFileInfo", sizeof("VarFileInfo")) == 0)
    #else
    							else if (memcmp(lpVersionInfo->szKey, L"VarFileInfo", sizeof(L"VarFileInfo")) == 0)
    #endif
    							{
    								lpVarFileInfo = (VS_VARFILEINFO *) lpVersionInfo;
    #if 0
    								if (lpVarFileInfo->wSize % sizeof(DWORD) != 0)
    									PrintConsole(hConsole,
    									             L"Size %hu in \'%ls\' not a multiple of 4!\n",
    									             lpVarFileInfo->wSize, lpVarFileInfo->szKey);
    #endif
    								if (lpVarFileInfo->wCount != 0)
    									PrintConsole(hConsole,
    									             L"Count %hu in \'%ls\' not 0!\n",
    									             lpVarFileInfo->wCount, lpVarFileInfo->szKey);
    
    								if (lpVarFileInfo->wType != VS_TEXT)
    									PrintConsole(hConsole,
    									             L"Type %hu in \'%ls\' not \'VS_TEXT\'!\n",
    									             lpVarFileInfo->wType, lpVarFileInfo->szKey);
    
    								if (lpVarFileInfo->wPadding != 0)
    									PrintConsole(hConsole,
    									             L"Padding %hu in \'%ls\' not 0!\n",
    									             lpVarFileInfo->wPadding, lpVarFileInfo->szKey);
    
    								bOutput &= PrintString(hOutput,
    								                       L"\t\t\tVarFileInfo:\r\n");
    
    								lpVar = (VS_VAR *) (lpVarFileInfo + 1);
    #if 0
    								if (wcscmp(lpVar->szKey, L"Translation") != 0)
    #elif 0
    								if (wmemcmp(lpVar->szKey, L"Translation", sizeof("Translation")) != 0)
    #else
    								if (memcmp(lpVar->szKey, L"Translation", sizeof(L"Translation")) != 0)
    #endif
    									PrintConsole(hConsole,
    									             L"Key string \"%ls\" in \'VAR\' not \"Translation\"!\n",
    									             lpVar->szKey);
    								else
    								{
    									if (lpVar->wCount % sizeof(DWORD) != 0)
    										PrintConsole(hConsole,
    										             L"Count %hu in \'%ls\' not a multiple of 4!\n",
    										             lpVar->wCount, lpVar->szKey);
    
    									if (lpVar->wType != VS_BINARY)
    										PrintConsole(hConsole,
    										             L"Type %hu in \'%ls\' not \'VS_BINARY\'!\n",
    										             lpVar->wType, lpVar->szKey);
    
    									if (lpVar->wPadding != 0)
    										PrintConsole(hConsole,
    										             L"Padding %hu in \'%ls\' not 0!\n",
    										             lpVar->wPadding, lpVar->szKey);
    
    									bOutput &= PrintString(hOutput,
    									                       L"\t\t\t\tTranslation(s) =");
    
    									for (dw = 0; dw < lpVar->wCount / sizeof(DWORD); dw++)
    										bOutput &= PrintFormat(hOutput,
    										                       L" 0x%04hX:%hu",
    										                       LOWORD(lpVar->dwValue[dw]), HIWORD(lpVar->dwValue[dw]));
    
    									bOutput &= PrintString(hOutput, L"\r\n");
    								}
    							}
    							else
    								PrintConsole(hConsole,
    								             L"Unknown key string \"%ls\" in \'VERSIONINFO\'!\n",
    								             lpVersionInfo->szKey);
    						break;
    
    					case RT_HTML:
    					case RT_MANIFEST:
    
    						if (*(DWORD *) lpResource == 0xFFFE0000)
    						{
    							dwValue = 12001;
    							lpValue = L"32BE";
    						}
    						else if (*(DWORD *) lpResource == 0x0000FEFF)
    						{
    							dwValue = 12000;
    							lpValue = L"32LE";
    						}
    						else if (*(WORD *) lpResource == 0xFFFE)
    						{
    							dwValue = 1201;
    							lpValue = L"16BE";
    						}
    						else if (*(WORD *) lpResource == 0xFEFF)
    						{
    							dwValue = 1200;
    							lpValue = L"16LE";
    						}
    						else if ((*(DWORD *) lpResource & 0x00FFFFFF) == 0x00BFBBEF)
    						{
    							dwValue = CP_UTF8;
    							lpValue = L"8 (BOM)";
    						}
    						else if ((*(DWORD *) lpResource == 0x2B762F2B)
    						      || (*(DWORD *) lpResource == 0x2F762F2B)
    						      || (*(DWORD *) lpResource == 0x38762F2B)
    						      || (*(DWORD *) lpResource == 0x39762F2B))
    						{
    							dwValue = CP_UTF7;
    							lpValue = L"7";
    						}
    						else
    						{
    							dwValue = CP_UTF8;
    							lpValue = L"8";
    						}
    
    						bOutput &= PrintFormat(hOutput,
    						                       L"\t\t\tUTF-%-7ls = ",
    						                       lpValue);
    
    						dwUnicode = MultiByteToWideChar(dwValue,
    						                                dwValue == CP_UTF7 ? 0 : MB_ERR_INVALID_CHARS,
    						                                lpResource,
    						                                dwResource,
    						                                (LPWSTR) NULL,
    						                                0);
    						if (dwUnicode == 0)
    							PrintConsole(hConsole,
    							             L"MultiByteToWideChar() returned error %lu\n",
    							             GetLastError());
    						else
    						{
    							lpUnicode = LocalAlloc(NONZEROLPTR, dwUnicode * sizeof(L'\0'));
    
    							if (lpUnicode == NULL)
    								PrintConsole(hConsole,
    								             L"LocalAlloc() returned error %lu\n",
    								             GetLastError());
    							else
    							{
    								dwUnicode = MultiByteToWideChar(dwValue,
    								                                dwValue == CP_UTF7 ? 0 : MB_ERR_INVALID_CHARS,
    								                                lpResource,
    								                                dwResource,
    								                                lpUnicode,
    								                                dwUnicode);
    								if (dwUnicode == 0)
    									PrintConsole(hConsole,
    									             L"MultiByteToWideChar() returned error %lu\n",
    									             GetLastError());
    								else
    									bOutput &= PrintDirect(hOutput, lpUnicode, dwUnicode);
    
    								if (LocalFree(lpUnicode) != NULL)
    									PrintConsole(hConsole,
    									             L"LocalFree() returned error %lu\n",
    									             GetLastError());
    							}
    						}
    
    						bOutput &= PrintString(hOutput, L"\r\n");
    
    						break;
    
    					case RT_LOCALE:
    
    						if (dwResource == sizeof(DWORD))
    							bOutput &= PrintFormat(hOutput,
    							                       L"\t\t\t%lu = 0x%04lX\r\n",
    							                       *(DWORD *) lpResource, *(DWORD *) lpResource);
    						break;
    
    				//	default:
    					}
    				else
    #if 0
    					if (wcscmp(lpType, L"MUI") == 0)
    #elif 0
    					if (wmemcmp(lpType, L"MUI", sizeof("MUI")) == 0)
    #else
    					if (memcmp(lpType, L"MUI", sizeof(L"MUI")) == 0)
    #endif
    					{
    						lpMUI = (MUI_RESOURCE *) lpResource;
    
    						if (lpMUI->dwSignature != MUI_RESOURCE_SIGNATURE)
    							PrintConsole(hConsole,
    							             L"Signature 0x%08lX of resource configuration data not 0x%08lX!\n",
    							             lpMUI->dwSignature, MUI_RESOURCE_SIGNATURE);
    						else
    							bOutput &= PrintFormat(hOutput,
    							                       L"\t\t\tResource Configuration Data:\r\n"
    							                       L"\t\t\t\tVersion           = %hu.%hu\r\n"
    							                       L"\t\t\t\tType              = %lu (%ls)\r\n"
    							                       L"\t\t\t\tLanguage          = %ls\r\n"
    							                       L"\t\t\t\tFallback Language = %ls\r\n"
    							                       L"\t\t\t\tFallback Location = %lu (%ls)\r\n"
    							                       L"\t\t\t\tSystem Attributes = 0x%08lX\r\n"
    							                       L"\t\t\t\tMain Checksum     = %08lX %08lX %08lX %08lX\r\n"
    							                       L"\t\t\t\tService Checksum  = %08lX %08lX %08lX %08lX\r\n",
    							                       HIWORD(lpMUI->dwVersion), LOWORD(lpMUI->dwVersion),
    							                       lpMUI->dwFileType, MUIFileType(lpMUI->dwFileType),
    							                       lpMUI->dwLanguageNameOffset == 0 ? NULL : (BYTE *) lpMUI + lpMUI->dwLanguageNameOffset,
    							                       lpMUI->dwFallbackNameOffset == 0 ? NULL : (BYTE *) lpMUI + lpMUI->dwFallbackNameOffset,
    							                       lpMUI->dwFallbackLocation, MUIFallbackLocation(lpMUI->dwFallbackLocation),
    							                       lpMUI->dwSystemAttributes,
    							                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[0]),
    							                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[1]),
    							                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[2]),
    							                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[3]),
    							                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[0]),
    							                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[1]),
    							                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[2]),
    							                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[3]));
    					}
    #if 0	// OBSOLETE!
    				if (!UnlockResource(lpResource))
    					PrintConsole(hConsole,
    					             L"UnlockResource() failed!\n");
    #endif
    			}
    #if 0	// OBSOLETE!
    			if (!FreeResource(hResData))
    				PrintConsole(hConsole,
    				             L"FreeResource() failed!\n");
    #endif
    		}
    
    		if (!bOutput)
    			PrintConsole(hConsole,
    			             L"WriteFile() returned error %lu\n",
    			             GetLastError());
    	}
    
    	return TRUE;
    }
    
    BOOL	WINAPI	EnumResNameProc(HMODULE hModule,
    		                LPCWSTR lpType,
    		                LPWSTR  lpName,
    		                LPARAM  lParam)
    {
    	BOOL	bOutput;
    	HANDLE	hOutput = ((HANDLE *) lParam)[1];
    	HANDLE	hConsole = ((HANDLE *) lParam)[2];
    
    	if (IS_INTRESOURCE(lpName))
    		bOutput = PrintFormat(hOutput,
    		                      L"\tID: %hu\r\n",
    		                      (WORD) lpName);
    	else
    		bOutput = PrintFormat(hOutput,
    		                      L"\tName: %ls\r\n",
    		                      lpName);
    
    	if (!bOutput)
    		PrintConsole(hConsole,
    		             L"WriteFile() returned error %lu\n",
    		             GetLastError());
    #ifdef NEUTRAL
    	if (!EnumResourceLanguagesEx(hModule,
    	                             lpType,
    	                             lpName,
    	                             EnumResLangProc,
    	                             lParam,
    	                             RESOURCE_ENUM_LN,
    	                             MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)))
    		PrintConsole(hConsole,
    		             L"EnumResourceLanguagesEx() returned error %lu\n",
    		             GetLastError());
    #else
    	if (!EnumResourceLanguages(hModule,
    	                           lpType,
    	                           lpName,
    	                           EnumResLangProc,
    	                           lParam))
    		PrintConsole(hConsole,
    		             L"EnumResourceLanguages() returned error %lu\n",
    		             GetLastError());
    #endif
    	return TRUE;
    }
    
    BOOL	WINAPI	EnumResTypeProc(HMODULE hModule,
    		                LPWSTR  lpType,
    		                LPARAM  lParam)
    {
    	BOOL	bOutput;
    	HANDLE	hOutput = ((HANDLE *) lParam)[1];
    	HANDLE	hConsole = ((HANDLE *) lParam)[2];
    
    	if (IS_INTRESOURCE(lpType))
    		bOutput = PrintFormat(hOutput,
    		                      L"Type: %hu ; %ls\r\n",
    		                      (WORD) lpType, ResourceTypeName((WORD) lpType));
    	else
    		bOutput = PrintFormat(hOutput,
    		                      L"Name: %ls\r\n",
    		                      lpType);
    
    	if (!bOutput)
    		PrintConsole(hConsole,
    		             L"WriteFile() returned error %lu\n",
    		             GetLastError());
    #ifdef NEUTRAL
    	if (!EnumResourceNamesEx(hModule,
    	                         lpType,
    	                         EnumResNameProc,
    	                         lParam,
    	                         RESOURCE_ENUM_LN,
    	                         MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)))
    		PrintConsole(hConsole,
    		             L"EnumResourceNamesEx() returned error %lu\n",
    		             GetLastError());
    #else
    	if (!EnumResourceNames(hModule,
    	                       lpType,
    	                       EnumResNameProc,
    	                       lParam))
    		PrintConsole(hConsole,
    		             L"EnumResourceNames() returned error %lu\n",
    		             GetLastError());
    #endif
    	return TRUE;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	HANDLE	*hHandles[3];
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	HMODULE	hModule;
    	HANDLE	hOutput;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments != 2)
    				PrintConsole(hConsole,
    				             L"No argument: a single (absolute or relative) path name of a binary module\n"
    				             L"             (eventually located per DLL search order) must be given!\n");
    			else
    			{
    				hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    				if (hOutput == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"GetStdHandle() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!FlushFileBuffers(hOutput))
    						PrintConsole(hConsole,
    						             L"FlushFileBuffers() returned error %lu: standard output is not redirected to a file!\n",
    						             dwError = GetLastError());
    					else
    					{
    						hModule = LoadLibraryEx(lpArguments[1],
    						                        (HANDLE) NULL,
    						                        LOAD_LIBRARY_AS_DATAFILE);
    
    						if (hModule == NULL)
    							PrintConsole(hConsole,
    							             L"LoadLibraryEx() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							PrintConsole(hConsole,
    							             L"Module \'%ls\' loaded at address 0x%p\n",
    							             lpArguments[1], hModule);
    
    							if (!PrintFormat(hOutput,
    							                 L"\xFEFF"	// UTF-16LE BOM
    							                 L"Module \'%ls\'\r\n"
    							                 L"\r\n",
    							                 lpArguments[1]))
    								PrintConsole(hConsole,
    								             L"WriteFile() returned error %lu\n",
    								             dwError = GetLastError());
    
    							hHandles[0] = NULL;
    							hHandles[1] = hOutput;
    							hHandles[2] = hConsole;
    #ifdef NEUTRAL
    							if (!EnumResourceTypesEx(hModule,
    							                         EnumResTypeProc,
    							                         (LPARAM) hHandles,
    							                         RESOURCE_ENUM_LN,
    							                         MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)))
    								PrintConsole(hConsole,
    								             L"EnumResourceTypesEx() returned error %lu\n",
    								             dwError = GetLastError());
    #else
    							if (!EnumResourceTypes(hModule,
    							                       EnumResTypeProc,
    							                       (LPARAM) hHandles))
    								PrintConsole(hConsole,
    								             L"EnumResourceTypes() returned error %lu\n",
    								             dwError = GetLastError());
    #endif
    							else
    								dwError = ERROR_SUCCESS;
    
    							if (!FreeLibrary(hModule))
    								PrintConsole(hConsole,
    								             L"FreeLibrary() returned error %lu\n",
    								             GetLastError());
    							else
    								PrintConsole(hConsole,
    								             L"Module \'%ls\' unloaded\n",
    								             lpArguments[1]);
    						}
    					}
    
    					if (!CloseHandle(hOutput))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file RESOURCE.C created in step 1., link the compiled object file RESOURCE.OBJ and cleanup afterwards:

    SET CL=/DLOCALE /DNEUTRAL /GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:6.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeRESOURCE.COM RESOURCE.C KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE RESOURCE.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    RESOURCE.C
    RESOURCE.C(554) : warning C4305: 'type cast' : truncation from 'LPWSTR' to 'WORD'
    RESOURCE.C(576) : warning C4305: 'type cast' : truncation from 'LPWSTR' to 'WORD'
    RESOURCE.C(1046) : warning C4090: 'function' : different 'const' qualifiers
    RESOURCE.C(1055) : warning C4090: 'function' : different 'const' qualifiers
    RESOURCE.C(1151) : warning C4305: 'type cast' : truncation from 'LPWSTR' to 'WORD'
    RESOURCE.C(1196) : warning C4305: 'type cast' : truncation from 'LPWSTR' to 'WORD'
    RESOURCE.C(1196) : warning C4305: 'type cast' : truncation from 'LPWSTR' to 'WORD'
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Source and Build Instructions – Variant 2

Perform the following two simple steps to build the second variant of the console application Portable Executable Resource Enumerator from the source presented hereafter.
  1. Overwrite the text file RESOURCE.C with the following content:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #ifndef MESSAGE_RESOURCE_ANSI
    #define MESSAGE_RESOURCE_ANSI	0
    #endif
    
    #ifndef RT_MENUEX
    #define RT_MENUEX	MAKEINTRESOURCE(13)
    #endif
    
    #ifndef RT_NAMETABLE
    #define RT_NAMETABLE	MAKEINTRESOURCE(15)
    #endif
    
    #ifndef RT_DIALOGEX
    #define RT_DIALOGEX	MAKEINTRESOURCE(18)
    #endif
    
    #ifndef RT_DLGINIT
    #define RT_DLGINIT	MAKEINTRESOURCE(240)
    #endif
    
    #ifndef RT_TOOLBAR
    #define RT_TOOLBAR	MAKEINTRESOURCE(241)
    #endif
    
    #ifndef RT_LOCALE
    #define RT_LOCALE	MAKEINTRESOURCE(255)
    #endif
    
    #define VS_BINARY	0U
    #define VS_TEXT		1U
    
    typedef	struct	_VS_VERSIONINFO
    {
    	WORD	wSize;		// size of 'VERSION' resource
    	WORD	wCount;		// = sizeof(VS_FIXEDFILEINFO)
    				//   (number of bytes in binary value)
    	WORD	wType;		// = VS_BINARY
    	WCHAR	szKey[16];	// = L"VS_VERSION_INFO"
    	WORD	wPadding;	// = 0 (alignment to DWORD)
    #if 0
    	DWORD	dwValue[13];
    #else
    	VS_FIXEDFILEINFO	vsFFI;
    #endif
    } VS_VERSIONINFO;
    
    typedef	struct	_MUI_RESOURCE
    {
    	DWORD	dwSignature;		// = 0xFECDFECD
    	DWORD	dwSize;			// size of "MUI" resource configuration data
    	DWORD	dwVersion;		// = 0x00010000
    	DWORD	dwUnknown;
    	DWORD	dwFileType;		// = 0x00000011: LN, language-neutral main file
    					// = 0x00000012: MUI, language-specific satellite file
    	DWORD	dwSystemAttributes;
    	DWORD	dwFallbackLocation;	// = 0x00000000: none
    					// = 0x00000001: internal
    					// = 0x00000002: external
    	BYTE	bServiceChecksum[16];
    	BYTE	bMainChecksum[16];
    	DWORD	dwReserved[6];
    	DWORD	dwTypeNameMainOffset;	// offset and size of named resource types
    	DWORD	dwTypeNameMainSize;	//  in main file (MULTI_SZ list)
    	DWORD	dwTypeIDMainOffset;	// offset and size of unnamed resource types
    	DWORD	dwTypeIDMainSize;	//  in main file (DWORD array)
    	DWORD	dwTypeNameMUIOffset;	// offset and size of named resource types
    	DWORD	dwTypeNameMUISize;	//  in satellite file (MULTI_SZ list)
    	DWORD	dwTypeIDMUIOffset;	// offset and size of unnamed resource types
    	DWORD	dwTypeIDMUISize;	//  in satellite file (DWORD array)
    	DWORD	dwLanguageNameOffset;	// offset and size of language string
    	DWORD	dwLanguageNameSize;
    	DWORD	dwFallbackNameOffset;	// offset and size of (ultimate) fallback
    	DWORD	dwFallbackNameSize;	//  language string
    	DWORD	dwPadding;
    //	DWORD	dwData[0];
    } MUI_RESOURCE;
    
    #define MUI_RESOURCE_SIGNATURE		0xFECDFECDUL
    #define MUI_RESOURCE_FILETYPE_MAIN	0x00000011UL
    #define MUI_RESOURCE_FILETYPE_SATELLITE	0x00000012UL
    #define MUI_RESOURCE_FALLBACK_NONE	0x00000000UL
    #define MUI_RESOURCE_FALLBACK_INTERNAL	0x00000001UL
    #define MUI_RESOURCE_FALLBACK_EXTERNAL	0x00000002UL
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	LPBYTE	lpOutput;
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	dwOutput *= sizeof(*szOutput);
    	lpOutput = (LPBYTE) szOutput;
    
    	do
    	{
    		if (!WriteFile(hFile, lpOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpOutput += dwFile;
    		dwOutput -= dwFile;
    	} while (dwOutput != 0);
    
    	return TRUE;
    }
    
    #define PrintString(HANDLE, LITERAL)	PrintDirect(HANDLE, LITERAL, sizeof(LITERAL) / sizeof(*LITERAL) - 1)
    
    __inline
    BOOL	WINAPI	PrintDirect(HANDLE hFile, LPCWSTR lpString, DWORD dwString)
    {
    	DWORD	dwFile;
    
    	dwString *= sizeof(*lpString);
    
    	do
    	{
    		if (!WriteFile(hFile, lpString, dwString, &dwFile, (LPOVERLAPPED) NULL))
    			return FALSE;
    
    		lpString = (LPCWSTR) ((LPBYTE) lpString + dwFile);
    		dwString -= dwFile;
    	} while (dwString != 0);
    
    	return TRUE;
    }
    
    __inline
    LPCWSTR	WINAPI	MUIFileType(DWORD dwFileType)
    {
    	switch (dwFileType)
    	{
    	case MUI_RESOURCE_FILETYPE_MAIN:
    		return L"LN: language-neutral main file";
    
    	case MUI_RESOURCE_FILETYPE_SATELLITE:
    		return L"MUI: language-specific satellite file";
    
    	default:
    		return NULL;
    	}
    }
    
    __inline
    LPCWSTR	WINAPI	MUIFallbackLocation(DWORD dwFallbackLocation)
    {
    	switch (dwFallbackLocation)
    	{
    	case MUI_RESOURCE_FALLBACK_NONE:
    		return L"none";
    
    	case MUI_RESOURCE_FALLBACK_INTERNAL:
    		return L"internal";
    
    	case MUI_RESOURCE_FALLBACK_EXTERNAL:
    		return L"external";
    
    	default:
    		return NULL;
    	}
    }
    
    LPCWSTR	WINAPI	ResourceTypeName(WORD wResType)
    {
    	switch (wResType)
    	{
    	case RT_CURSOR:		// MAKEINTRESOURCE(1)
    		return L"RT_CURSOR";
    
    	case RT_BITMAP:		// MAKEINTRESOURCE(2)
    		return L"RT_BITMAP";
    
    	case RT_ICON:		// MAKEINTRESOURCE(3)
    		return L"RT_ICON";
    
    	case RT_MENU:		// MAKEINTRESOURCE(4)
    		return L"RT_MENU";
    
    	case RT_DIALOG:		// MAKEINTRESOURCE(5)
    		return L"RT_DIALOG";
    
    	case RT_STRING:		// MAKEINTRESOURCE(6)
    #if 1
    		return L"RT_STRING";
    #else
    		return L"RT_STRINGTABLE";
    #endif
    	case RT_FONTDIR:	// MAKEINTRESOURCE(7)
    		return L"RT_FONTDIR";
    
    	case RT_FONT:		// MAKEINTRESOURCE(8)
    		return L"RT_FONT";
    
    	case RT_ACCELERATOR:	// MAKEINTRESOURCE(9)
    		return L"RT_ACCELERATOR";
    
    	case RT_RCDATA:		// MAKEINTRESOURCE(10)
    		return L"RT_RCDATA";
    
    	case RT_MESSAGETABLE:	// MAKEINTRESOURCE(11)
    		return L"RT_MESSAGETABLE";
    
    	case RT_GROUP_CURSOR:	// MAKEINTRESOURCE(12)
    		return L"RT_GROUP_CURSOR";
    
    	case RT_MENUEX:		// MAKEINTRESOURCE(13)
    		return L"RT_MENUEX";
    
    	case RT_GROUP_ICON:	// MAKEINTRESOURCE(14)
    		return L"RT_GROUP_ICON";
    
    	case RT_NAMETABLE:	// MAKEINTRESOURCE(15)
    		return L"RT_NAMETABLE";
    
    	case RT_VERSION:	// MAKEINTRESOURCE(16)
    		return L"RT_VERSION";
    
    	case RT_DLGINCLUDE:	// MAKEINTRESOURCE(17)
    		return L"RT_DLGINCLUDE";
    
    	case RT_DIALOGEX:	// MAKEINTRESOURCE(18)
    		return L"RT_DIALOGEX";
    
    	case RT_PLUGPLAY:	// MAKEINTRESOURCE(19)
    		return L"RT_PLUGPLAY";
    
    	case RT_VXD:		// MAKEINTRESOURCE(20)
    		return L"RT_VXD";
    
    	case RT_ANICURSOR:	// MAKEINTRESOURCE(21)
    		return L"RT_ANICURSOR";
    
    	case RT_ANIICON:	// MAKEINTRESOURCE(22)
    		return L"RT_ANIICON";
    
    	case RT_HTML:		// MAKEINTRESOURCE(23)
    		return L"RT_HTML";
    
    	case RT_MANIFEST:	// MAKEINTRESOURCE(24)
    		return L"RT_MANIFEST";
    
    	case RT_DLGINIT:	// MAKEINTRESOURCE(240)
    		return L"RT_DLGINIT";
    
    	case RT_TOOLBAR:	// MAKEINTRESOURCE(241)
    		return L"RT_TOOLBAR";
    
    	case RT_LOCALE:		// MAKEINTRESOURCE(255)
    		return L"RT_LOCALE";
    
    	default:
    		return NULL;
    	}
    }
    
    LPCWSTR	WINAPI	ResourceLanguageName(WORD wLanguageID, BOOL bSymbolic)
    {
    	switch (wLanguageID)
    	{
    	case 0x0000: // = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_NEUTRAL, SUBLANG_NEUTRAL"
    		                 : L"Neutral locale language, neutral sublanguage";
    	case 0x0400: // = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) = LANG_USER_DEFAULT
    		return bSymbolic ? L"LANG_NEUTRAL, SUBLANG_DEFAULT"
    		                 : L"User default locale language, user default sublanguage";
    	case 0x0800: // = MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT) = LANG_SYSTEM_DEFAULT
    		return bSymbolic ? L"LANG_NEUTRAL, SUBLANG_SYS_DEFAULT"
    		                 : L"System default locale language, system default sublanguage";
    	case 0x0C00: // = MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT)
    		return bSymbolic ? L"LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT"
    		                 : L"Default custom locale language, default custom sublanguage";
    	case 0x1000: // = MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED)
    		return bSymbolic ? L"LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED"
    		                 : L"Unspecified custom locale language, unspecified custom sublanguage";
    	case 0x1400: // = MAKELANGID(LANG_NEUTRAL, SUBLANG_UI_CUSTOM_DEFAULT)
    		return bSymbolic ? L"LANG_NEUTRAL, SUBLANG_UI_CUSTOM_DEFAULT"
    		                 : L"Default custom MUI locale language, default custom MUI sublanguage";
    
    	case 0x0001: // = MAKELANGID(LANG_ARABIC, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_NEUTRAL"
    		                 : L"Arabic (ar)";
    	case 0x0401: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA"
    		                 : L"Arabic (ar), Saudi Arabia (SA)";
    	case 0x0801: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_IRAQ)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_IRAQ"
    		                 : L"Arabic (ar), Iraq (IQ)";
    	case 0x0C01: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_EGYPT)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_EGYPT"
    		                 : L"Arabic (ar), Egypt (EG)";
    	case 0x1001: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_LIBYA)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_LIBYA"
    		                 : L"Arabic (ar), Libya (LY)";
    	case 0x1401: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_ALGERIA)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_ALGERIA"
    		                 : L"Arabic (ar), Algeria (DZ)";
    	case 0x1801: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_MOROCCO)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_MOROCCO"
    		                 : L"Arabic (ar), Morocco (MA)";
    	case 0x1C01: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_TUNISIA)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_TUNISIA"
    		                 : L"Arabic (ar), Tunisia (TN)";
    	case 0x2001: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_OMAN)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_OMAN"
    		                 : L"Arabic (ar), Oman (OM)";
    	case 0x2401: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_YEMEN)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_YEMEN"
    		                 : L"Arabic (ar), Yemen (YE)";
    	case 0x2801: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SYRIA)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_SYRIA"
    		                 : L"Arabic (ar), Syria (SY)";
    	case 0x2C01: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_JORDAN)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_JORDAN"
    		                 : L"Arabic (ar), Jordan (JO)";
    	case 0x3001: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_LEBANON)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_LEBANON"
    		                 : L"Arabic (ar), Lebanon (LB)";
    	case 0x3401: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_KUWAIT)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_KUWAIT"
    		                 : L"Arabic (ar), Kuwait (KW)";
    	case 0x3801: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_UAE)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_UAE"
    		                 : L"Arabic (ar), United Arab Emirates (AE)";
    	case 0x3C01: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_BAHRAIN)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_BAHRAIN"
    		                 : L"Arabic (ar), Bahrain (BH)";
    	case 0x4001: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_QATAR"
    		                 : L"Arabic (ar), Qatar (QA)";
    	case 0x4401: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_PSEUDO_SAUDI_ARABIA)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_PSEUDO_SAUDI_ARABIA"
    		                 : L"Arabic (ar), Pseudo locale (Ploc), Saudi Arabia (SA)";
    	case 0x4801: // = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_PALESTINE)
    		return bSymbolic ? L"LANG_ARABIC, SUBLANG_ARABIC_PALESTINE"
    		                 : L"Arabic (ar), Occupied Palestinian Territory (145)";
    
    	case 0x0002: // = MAKELANGID(LANG_BULGARIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BULGARIAN, SUBLANG_NEUTRAL"
    		                 : L"Bulgarian (bg)";
    	case 0x0402: // = MAKELANGID(LANG_BULGARIAN, SUBLANG_BULGARIAN_BULGARIA)
    		return bSymbolic ? L"LANG_BULGARIAN, SUBLANG_BULGARIAN_BULGARIA"
    		                 : L"Bulgarian (bg), Bulgaria (BG)";
    
    	case 0x0003: // = MAKELANGID(LANG_CATALAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_CATALAN, SUBLANG_NEUTRAL"
    		                 : L"Catalan (ca)";
    	case 0x0403: // = MAKELANGID(LANG_CATALAN, SUBLANG_CATALAN_CATALAN)
    		return bSymbolic ? L"LANG_CATALAN, SUBLANG_CATALAN_CATALAN"
    		                 : L"Catalan (ca), Spain (ES)";
    	case 0x0803: // = MAKELANGID(LANG_VALENCIAN, SUBLANG_VALENCIAN_VALENCIA)
    		return bSymbolic ? L"LANG_VALENCIAN, SUBLANG_VALENCIAN_VALENCIA"
    		                 : L"Valencian (ca), Valencia (ES-Valencia)";
    
    	case 0x0004: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED"
    		                 : L"Chinese (zh), Simplified (Hans)";
    	case 0x0404: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TAIWAN)
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE_TAIWAN"
    		                 : L"Chinese (zh), Taiwan (TW)";
    	case 0x0804: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_PRC)
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE_PRC"
    		                 : L"Chinese (zh), People\'s Republic of China (CN)";
    	case 0x0C04: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG)
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE_HONGKONG"
    		                 : L"Chinese (zh), Hongkong S.A.R. (HK)";
    	case 0x1004: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE)
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE"
    		                 : L"Chinese (zh), Singapore (SG)";
    	case 0x1404: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_MACAU)
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE_MACAU"
    		                 : L"Chinese (zh), Macao S.A.R. (MO)";
    	case 0x7804: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE)
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE"
    		                 : L"Chinese (zh)";
    	case 0x7C04: // = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) = LANG_CHINESE_TRADITIONAL
    		return bSymbolic ? L"LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL"
    		                 : L"Chinese (zh), Traditional (Hant)";
    
    	case 0x0005: // = MAKELANGID(LANG_CZECH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_CZECH, SUBLANG_NEUTRAL"
    		                 : L"Czech (cs)";
    	case 0x0405: // = MAKELANGID(LANG_CZECH, SUBLANG_CZECH_CZECH_REPUBLIC)
    		return bSymbolic ? L"LANG_CZECH, SUBLANG_CZECH_CZECH_REPUBLIC"
    		                 : L"Czech (cs), Czech Republic (CZ)";
    
    	case 0x0006: // = MAKELANGID(LANG_DANISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_DANISH, SUBLANG_NEUTRAL"
    		                 : L"Danish (da)";
    	case 0x0406: // = MAKELANGID(LANG_DANISH, SUBLANG_DANISH_DENMARK)
    		return bSymbolic ? L"LANG_DANISH, SUBLANG_DANISH_DENMARK"
    		                 : L"Danish (da), Denmark (DK)";
    
    	case 0x0007: // = MAKELANGID(LANG_GERMAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_GERMAN, SUBLANG_NEUTRAL"
    		                 : L"German (de)";
    #if 0
    	case 0x0407: // = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN)
    		return bSymbolic ? L"LANG_GERMAN, SUBLANG_GERMAN"
    		                 : L"German (de), Germany (DE)";
    #else
    	case 0x0407: // = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_GERMANY)
    		return bSymbolic ? L"LANG_GERMAN, SUBLANG_GERMAN_GERMANY"
    		                 : L"German (de), Germany (DE)";
    #endif
    	case 0x0807: // = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS)
    		return bSymbolic ? L"LANG_GERMAN, SUBLANG_GERMAN_SWISS"
    		                 : L"German (de), Switzerland (CH)";
    	case 0x0C07: // = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN)
    		return bSymbolic ? L"LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN"
    		                 : L"German (de), Austria (AT)";
    	case 0x1007: // = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG)
    		return bSymbolic ? L"LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG"
    		                 : L"German (de), Luxembourg (LU)";
    	case 0x1407: // = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_LIECHTENSTEIN)
    		return bSymbolic ? L"LANG_GERMAN, SUBLANG_GERMAN_LIECHTENSTEIN"
    		                 : L"German (de), Liechtenstein (LI)";
    
    	case 0x0008: // = MAKELANGID(LANG_GREEK, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_GREEK, SUBLANG_NEUTRAL"
    		                 : L"Greek (el)";
    	case 0x0408: // = MAKELANGID(LANG_GREEK, SUBLANG_GREEK_GREECE)
    		return bSymbolic ? L"LANG_GREEK, SUBLANG_GREEK_GREECE"
    		                 : L"Greek (el), Greece (GR)";
    
    	case 0x0009: // = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_NEUTRAL"
    		                 : L"English (en)";
    	case 0x0409: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_US"
    		                 : L"English (en), United States (US)";
    	case 0x0809: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_UK"
    		                 : L"English (en), United Kingdom (GB)";
    	case 0x0C09: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_AUS)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_AUS"
    		                 : L"English (en), Australia (AU)";
    	case 0x1009: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CAN)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_CAN"
    		                 : L"English (en), Canada (CA)";
    	case 0x1409: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_NZ)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_NZ"
    		                 : L"English (en), New Zealand (NZ)";
    #if 0
    	case 0x1809: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_EIRE)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_EIRE"
    		                 : L"English (en), Ireland (IE)";
    #else
    	case 0x1809: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_IRELAND)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_IRELAND"
    		                 : L"English (en), Ireland (IE)";
    #endif
    	case 0x1C09: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_SOUTH_AFRICA"
    		                 : L"English (en), South Africa (ZA)";
    	case 0x2009: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_JAMAICA)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_JAMAICA"
    		                 : L"English (en), Jamaica (JM)";
    	case 0x2409: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CARIBBEAN)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_CARIBBEAN"
    		                 : L"English (en), Caribbean (029)";
    	case 0x2809: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_BELIZE)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_BELIZE"
    		                 : L"English (en), Belize (BZ)";
    	case 0x2C09: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_TRINIDAD)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_TRINIDAD"
    		                 : L"English (en), Trinidad and Tobago (TT)";
    	case 0x3009: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_ZIMBABWE)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_ZIMBABWE"
    		                 : L"English (en), Zimbabwe (ZW)";
    	case 0x3409: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_PHILIPPINES)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_PHILIPPINES"
    		                 : L"English (en), Philippines (PH)";
    	case 0x3809: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_INDONESIA)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_INDONESIO"
    		                 : L"English (en), Indonesia (ID)";
    	case 0x3C09: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_HONGKONG)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_HONGKONG"
    		                 : L"English (en), Hongkong S.A.R. (HK)";
    	case 0x4009: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_INDIA)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_INDIA"
    		                 : L"English (en), India (IN)";
    	case 0x4409: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_MALAYSIA)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_MALAYSIA"
    		                 : L"English (en), Malaysia (MY)";
    	case 0x4809: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_SINGAPORE)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_SINGAPORE"
    		                 : L"English (en), Singapore (SG)";
    	case 0x4C09: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UAE)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_UAE"
    		                 : L"English (en), United Arab Emirates (AE)";
    	case 0x5009: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_BAHRAIN)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_BAHRAIN"
    		                 : L"English (en), Bahrain (BH)";
    	case 0x5409: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_EGYPT)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_EGYPT"
    		                 : L"English (en), Egypt (EG)";
    	case 0x5809: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_JORDAN)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_JORDAN"
    		                 : L"English (en), Jordan (JO)";
    	case 0x5C09: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_KUWAIT)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_KUWAIT"
    		                 : L"English (en), Kuwait (KW)";
    	case 0x6009: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_TURKEY)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_TURKEY"
    		                 : L"English (en), Turkey (TR)";
    	case 0x6409: // = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_YEMEN)
    		return bSymbolic ? L"LANG_ENGLISH, SUBLANG_ENGLISH_YEMEN"
    		                 : L"English (en), Yemen (YE)";
    
    	case 0x000A: // = MAKELANGID(LANG_SPANISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_NEUTRAL"
    		                 : L"Spanish (es)";
    #if 0
    	case 0x040A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH"
    		                 : L"Spanish (es), Spain (ES), Traditional Sort";
    #else
    	case 0x040A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_SPAIN)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_SPAIN"
    		                 : L"Spanish (es), Spain (ES), Traditional Sort";
    #endif
    	case 0x080A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MEXICAN)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_MEXICAN"
    		                 : L"Spanish (es), Mexico (MX)";
    	case 0x0C0A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_MODERN"
    		                 : L"Spanish (es), Spain (ES), Modern Sort";
    	case 0x100A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_GUATEMALA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_GUATEMALA"
    		                 : L"Spanish (es), Guatemala (GT)";
    	case 0x140A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_COSTA_RICA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_COSTA_RICA"
    		                 : L"Spanish (es), Costa Rica (CR)";
    	case 0x180A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_PANAMA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_PANAMA"
    		                 : L"Spanish (es), Panama (PA)";
    	case 0x1C0A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_DOMINICAN_REPUBLIC)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_DOMINICAN_REPUBLIC"
    		                 : L"Spanish (es), Dominican Republic (DO)";
    	case 0x200A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_VENEZUELA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_VENEZUELA"
    		                 : L"Spanish (es), Venezuela (VE)";
    	case 0x240A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_COLOMBIA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_COLOMBIA"
    		                 : L"Spanish (es), Colombia (CO)";
    	case 0x280A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_PERU)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_PERU"
    		                 : L"Spanish (es), Peru (PE)";
    	case 0x2C0A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA"
    		                 : L"Spanish (es), Argentina (AR)";
    	case 0x300A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_ECUADOR)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_ECUADOR"
    		                 : L"Spanish (es), Ecuador (EC)";
    	case 0x340A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_CHILE)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_CHILE"
    		                 : L"Spanish (es), Chile (CL)";
    	case 0x380A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_URUGUAY)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_URUGUAY"
    		                 : L"Spanish (es), Uruguay (UY)";
    	case 0x3C0A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_PARAGUAY)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_PARAGUAY"
    		                 : L"Spanish (es), Paraguay (PY)";
    	case 0x400A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_BOLIVIA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_BOLIVIA"
    		                 : L"Spanish (es), Bolivia (BO)";
    	case 0x440A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_EL_SALVADOR)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_EL_SALVADOR"
    		                 : L"Spanish (es), El Salvador (SV)";
    	case 0x480A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_HONDURAS)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_HONDURAS"
    		                 : L"Spanish (es), Honduras (HN)";
    	case 0x4C0A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_NICARAGUA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_NICARAGUA"
    		                 : L"Spanish (es), Nicaragua (NI)";
    	case 0x500A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_PUERTO_RICO)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_PUERTO_RICO"
    		                 : L"Spanish (es), Puerto Rico (PR)";
    	case 0x540A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_US)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_US"
    		                 : L"Spanish (es), United States (US)";
    	case 0x580A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_LATIN_AMERICA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_LATIN_AMERICA"
    		                 : L"Spanish (es), Latin America (419)";
    	case 0x5C0A: // = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_CUBA)
    		return bSymbolic ? L"LANG_SPANISH, SUBLANG_SPANISH_CUBA"
    		                 : L"Spanish (es), Cuba (CU)";
    
    	case 0x000B: // = MAKELANGID(LANG_FINNISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_FINNISH, SUBLANG_NEUTRAL"
    		                 : L"Finnish (fi)";
    	case 0x040B: // = MAKELANGID(LANG_FINNISH, SUBLANG_FINNISH_FINLAND)
    		return bSymbolic ? L"LANG_FINNISH, SUBLANG_FINNISH_FINLAND"
    		                 : L"Finnish (fi), Finland (FI)";
    
    	case 0x000C: // = MAKELANGID(LANG_FRENCH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_NEUTRAL"
    		                 : L"French (fr)";
    #if 0
    	case 0x040C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH"
    		                 : L"French (fr), France (FR)";
    #else
    	case 0x040C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_FRANCE)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_FRANCE"
    		                 : L"French (fr), France (FR)";
    #endif
    	case 0x080C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_BELGIAN)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_BELGIAN"
    		                 : L"French (fr), Belgium (BE)";
    	case 0x0C0C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CANADIAN)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_CANADIAN"
    		                 : L"French (fr), Canada (CA)";
    	case 0x100C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_SWISS)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_SWISS"
    		                 : L"French (fr), Switzerland (CH)";
    	case 0x140C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_LUXEMBOURG)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_LUXEMBOURG"
    		                 : L"French (fr), Luxembourg (LU)";
    	case 0x180C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_MONACO)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_MONACO"
    		                 : L"French (fr), Monaco (MC)";
    #if 0
    	case 0x1C0C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_WEST_INDIES)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_WEST_INDIES"
    		                 : L"French (fr), West Indies (WI)";
    #else
    	case 0x1C0C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CARIBBEAN)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_CARIBBEAN"
    		                 : L"French (fr), Caribbean (029)";
    #endif
    	case 0x200C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_REUNION)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_REUNION"
    		                 : L"French (fr), Reunion (RE)";
    	case 0x240C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CONGO)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_CONGO"
    		                 : L"French (fr), Congo (CD)";
    	case 0x280C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_SENEGAL)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_SENEGAL"
    		                 : L"French (fr), Senegal (SN)";
    	case 0x2C0C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CAMEROON)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_CAMEROON"
    		                 : L"French (fr), Cameroon (CM)";
    	case 0x300C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_COTE_DE_IVOIRE)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_COTE_DE_IVOIRE"
    		                 : L"French (fr), Côte d’Ivoire (CI)";
    	case 0x340C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_MALI)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_MALI"
    		                 : L"French (fr), Mali (ML)";
    	case 0x380C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_MOROCCO)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_MORROCO"
    		                 : L"French (fr), Morroco (MA)";
    	case 0x3C0C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_HAITI)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_HAITI"
    		                 : L"French (fr), Haiti (HT)";
    #if 0
    	case 0xE40C: // = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_NORTH_AFRICA)
    		return bSymbolic ? L"LANG_FRENCH, SUBLANG_FRENCH_NORTH_AFRICA"
    		                 : L"French (fr), North Africa (015)";
    #endif
    	case 0x000D: // = MAKELANGID(LANG_HEBREW, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_HEBREW, SUBLANG_NEUTRAL"
    		                 : L"Hebrew (he)";
    	case 0x040D: // = MAKELANGID(LANG_HEBREW, SUBLANG_HEBREW_ISRAEL)
    		return bSymbolic ? L"LANG_HEBREW, SUBLANG_HEBREW_ISRAEL"
    		                 : L"Hebrew (he), Israel (IL)";
    
    	case 0x000E: // = MAKELANGID(LANG_HUNGARIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_HUNGARIAN, SUBLANG_NEUTRAL"
    		                 : L"Hungarian (hu)";
    	case 0x040E: // = MAKELANGID(LANG_HUNGARIAN, SUBLANG_HUNGARIAN_HUNGARY)
    		return bSymbolic ? L"LANG_HUNGARIAN, SUBLANG_HUNGARIAN_HUNGARY"
    		                 : L"Hungarian (hu), Hungary (HU)";
    
    	case 0x000F: // = MAKELANGID(LANG_ICELANDIC, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ICELANDIC, SUBLANG_NEUTRAL"
    		                 : L"Icelandic (is)";
    	case 0x040F: // = MAKELANGID(LANG_ICELANDIC, SUBLANG_ICELANDIC_ICELAND)
    		return bSymbolic ? L"LANG_ICELANDIC, SUBLANG_ICELANDIC_ICELAND"
    		                 : L"Icelandic (is), Iceland (IS)";
    
    	case 0x0010: // = MAKELANGID(LANG_ITALIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ITALIAN, SUBLANG_NEUTRAL"
    		                 : L"Italian (it)";
    #if 0
    	case 0x0410: // = MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN)
    		return bSymbolic ? L"LANG_ITALIAN, SUBLANG_ITALIAN"
    		                 : L"Italian (it), Italy (IT)";
    #else
    	case 0x0410: // = MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN_ITALY)
    		return bSymbolic ? L"LANG_ITALIAN, SUBLANG_ITALIAN_ITALY"
    		                 : L"Italian (it), Italy (IT)";
    #endif
    	case 0x0810: // = MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN_SWISS)
    		return bSymbolic ? L"LANG_ITALIAN, SUBLANG_ITALIAN_SWISS"
    		                 : L"Italian (it), Switzerland (CH)";
    
    	case 0x0011: // = MAKELANGID(LANG_JAPANESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_JAPANESE, SUBLANG_NEUTRAL"
    		                 : L"Japanese (ja)";
    	case 0x0411: // = MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN)
    		return bSymbolic ? L"LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN"
    		                 : L"Japanese (ja), Japan (JP)";
    	case 0x0811: // = MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_PSEUDO_JAPAN)
    		return bSymbolic ? L"LANG_JAPANESE, SUBLANG_JAPANESE_PSEUDO_JAPAN"
    		                 : L"Japanese (ja), Pseudo locale (Ploc), Japan (JP)";
    
    	case 0x0012: // = MAKELANGID(LANG_KOREAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KOREAN, SUBLANG_NEUTRAL"
    		                 : L"Korean (ko)";
    #if 0
    	case 0x0412: // = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN)
    		return bSymbolic ? L"LANG_KOREAN, SUBLANG_KOREAN"
    		                 : L"Korean (ko), Korea (KR)";
    #else
    	case 0x0412: // = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN_KOREA)
    		return bSymbolic ? L"LANG_KOREAN, SUBLANG_KOREAN_KOREA"
    		                 : L"Korean (ko), Korea (KR)";
    #endif
    	case 0x0013: // = MAKELANGID(LANG_DUTCH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_DUTCH, SUBLANG_NEUTRAL"
    		                 : L"Dutch (nl)";
    #if 0
    	case 0x0413: // = MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH)
    		return bSymbolic ? L"LANG_DUTCH, SUBLANG_DUTCH"
    		                 : L"Dutch (nl), Netherlands (NL)";
    #else
    	case 0x0413: // = MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_NETHERLANDS)
    		return bSymbolic ? L"LANG_DUTCH, SUBLANG_DUTCH_NETHERLANDS"
    		                 : L"Dutch (nl), Netherlands (NL)";
    #endif
    	case 0x0813: // = MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_BELGIAN)
    		return bSymbolic ? L"LANG_DUTCH, SUBLANG_DUTCH_BELGIAN"
    		                 : L"Dutch (nl), Belgium (BE)";
    
    	case 0x0014: // = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_NORWEGIAN, SUBLANG_NEUTRAL"
    		                 : L"Norwegian (no)";
    	case 0x0414: // = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL)
    		return bSymbolic ? L"LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL"
    		                 : L"Bokmål (nb), Norway (NO)";
    	case 0x0814: // = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK)
    		return bSymbolic ? L"LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK"
    		                 : L"Nynorsk (nn), Norway (NO)";
    	case 0x7814: // = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NYNORSK)
    		return bSymbolic ? L"LANG_NORWEGIAN, SUBLANG_NYNORSK"
    		                 : L"Nynorsk (nn)";
    	case 0x7C14: // = MAKELANGID(LANG_NORWEGIAN, SUBLANG_BOKMAL)
    		return bSymbolic ? L"LANG_NORWEGIAN, SUBLANG_BOKMAL"
    		                 : L"Bokmål (nb)";
    
    	case 0x0015: // = MAKELANGID(LANG_POLISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_POLISH, SUBLANG_NEUTRAL"
    		                 : L"Polish (pl)";
    	case 0x0415: // = MAKELANGID(LANG_POLISH, SUBLANG_POLISH_POLAND)
    		return bSymbolic ? L"LANG_POLISH, SUBLANG_POLISH_POLAND"
    		                 : L"Polish (pl), Poland (PL)";
    
    	case 0x0016: // = MAKELANGID(LANG_PORTUGUESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_PORTUGUESE, SUBLANG_NEUTRAL"
    		                 : L"Portuguese (pt)";
    	case 0x0416: // = MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN)
    		return bSymbolic ? L"LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN"
    		                 : L"Portuguese (pt), Brazil (BR)";
    #if 0
    	case 0x0816: // = MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE)
    		return bSymbolic ? L"LANG_PORTUGUESE, SUBLANG_PORTUGUESE"
    		                 : L"Portuguese (pt), Portugal (PT)";
    #else
    	case 0x0816: // = MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_PORTUGAL)
    		return bSymbolic ? L"LANG_PORTUGUESE, SUBLANG_PORTUGUESE_PORTUGAL"
    		                 : L"Portuguese (pt), Portugal (PT)";
    #endif
    	case 0x0017: // = MAKELANGID(LANG_ROMANSH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ROMANSH, SUBLANG_NEUTRAL"
    		                 : L"Romansh (rm)";
    	case 0x0417: // = MAKELANGID(LANG_ROMANSH, SUBLANG_ROMANSH_SWITZERLAND)
    		return bSymbolic ? L"LANG_ROMANSH, SUBLANG_ROMANSH_SWITZERLAND"
    		                 : L"Romansh (rm), Switzerland (CH)";
    
    	case 0x0018: // = MAKELANGID(LANG_ROMANIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ROMANIAN, SUBLANG_NEUTRAL"
    		                 : L"Romanian (ro)";
    	case 0x0418: // = MAKELANGID(LANG_ROMANIAN, SUBLANG_ROMANIAN_ROMANIA)
    		return bSymbolic ? L"LANG_ROMANIAN, SUBLANG_ROMANIAN_ROMANIA"
    		                 : L"Romanian (ro), Romania (RO)";
    	case 0x0818: // = MAKELANGID(LANG_ROMANIAN, SUBLANG_ROMANIAN_MOLDAVIA)
    		return bSymbolic ? L"LANG_ROMANIAN, SUBLANG_ROMANIAN_MOLDAVIA"
    		                 : L"Romanian (ro), Moldova (MD)";
    
    	case 0x0019: // = MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_RUSSIAN, SUBLANG_NEUTRAL"
    		                 : L"Russian (ru)";
    	case 0x0419: // = MAKELANGID(LANG_RUSSIAN, SUBLANG_RUSSIAN_RUSSIA)
    		return bSymbolic ? L"LANG_RUSSIAN, SUBLANG_RUSSIAN_RUSSIA"
    		                 : L"Russian (ru), Russia (RU)";
    	case 0x0819: // = MAKELANGID(LANG_RUSSIAN, SUBLANG_RUSSIAN_MOLDAVIA)
    		return bSymbolic ? L"LANG_RUSSIAN, SUBLANG_RUSSIAN_MOLDAVIA"
    		                 : L"Russian (ru), Moldova (MD)";
    
    	case 0x001A: // = MAKELANGID(LANG_CROATIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_CROATIAN, SUBLANG_NEUTRAL"
    		                 : L"Croatian (hr)";
    	case 0x041A: // = MAKELANGID(LANG_CROATIAN, SUBLANG_CROATIAN_CROATIA)
    		return bSymbolic ? L"LANG_CROATIAN, SUBLANG_CROATIAN_CROATIA"
    		                 : L"Croatian (hr), Croatia (HR)";
    	case 0x081A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_LATIN)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_LATIN"
    		                 : L"Serbian (sr), Latin (Latn), Serbia and Montenegro, Former (CS)";
    	case 0x0C1A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC"
    		                 : L"Serbian (sr), Cyrillic (Cyrl), Serbia and Montenegro, Former (CS)";
    	case 0x101A: // = MAKELANGID(LANG_CROATIAN, SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN)
    		return bSymbolic ? L"LANG_CROATIAN, SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN"
    		                 : L"Croatian (hr), Latin (Latn), Bosnia and Herzegovina (BA)";
    	case 0x141A: // = MAKELANGID(LANG_BOSNIAN, SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN)
    		return bSymbolic ? L"LANG_BOSNIAN, SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN"
    		                 : L"Bosnian (bs), Latin (Latn), Bosnia and Herzegovina (BA)";
    	case 0x181A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN"
    		                 : L"Serbian (sr), Latin (Latn), Bosnia and Herzegovina (BA)";
    	case 0x1C1A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC"
    		                 : L"Serbian (sr), Cyrillic (Cyrl), Bosnia and Herzegovina (BA)";
    	case 0x201A: // = MAKELANGID(LANG_BOSNIAN, SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC)
    		return bSymbolic ? L"LANG_BOSNIAN, SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC"
    		                 : L"Bosnian (bs), Cyrillic (Cyrl), Bosnia and Herzegovina (BA)";
    	case 0x241A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_LATIN)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_LATIN"
    		                 : L"Serbian (sr), Latin (Latn), Serbia (RS)";
    	case 0x281A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_CYRILLIC)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_CYRILLIC"
    		                 : L"Serbian (sr), Cyrillic (Cyrl), Serbia (RS)";
    	case 0x2C1A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_MONTENEGRO_LATIN)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_MONTENEGRO_LATIN"
    		                 : L"Serbian (sr), Latin (Latn), Montenegro (ME)";
    	case 0x301A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC"
    		                 : L"Serbian (sr), Cyrillic (Cyrl), Montenegro (ME)";
    	case 0x641A: // = MAKELANGID(LANG_BOSNIAN, SUBLANG_BOSNIAN_CYRILLIC)
    		return bSymbolic ? L"LANG_BOSNIAN, SUBLANG_BOSNIAN_CYRILLIC"
    		                 : L"Bosnian (bs), Cyrillic (Cyrl)";
    	case 0x681A: // = MAKELANGID(LANG_BOSNIAN, SUBLANG_BOSNIAN_LATIN)
    		return bSymbolic ? L"LANG_BOSNIAN, SUBLANG_BOSNIAN_LATIN"
    		                 : L"Bosnian (bs), Latin (Latn)";
    	case 0x6C1A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC"
    		                 : L"Serbian (sr), Cyrillic (Cyrl)";
    	case 0x701A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_LATIN)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_LATIN"
    		                 : L"Serbian (sr), Latin (Latn)";
    	case 0x741A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CROATIA)
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN_CROATIA"
    		                 : L"Serbian (sr), Croatia (HR)";
    	case 0x781A: // = MAKELANGID(LANG_BOSNIAN, SUBLANG_BOSNIAN) = LANG_BOSNIAN_NEUTRAL
    		return bSymbolic ? L"LANG_BOSNIAN, SUBLANG_BOSNIAN"
    		                 : L"Bosnian (bs)";
    	case 0x7C1A: // = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN) = LANG_SERBIAN_NEUTRAL
    		return bSymbolic ? L"LANG_SERBIAN, SUBLANG_SERBIAN"
    		                 : L"Serbian (sr)";
    
    	case 0x001B: // = MAKELANGID(LANG_SLOVAK, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SLOVAK, SUBLANG_NEUTRAL"
    		                 : L"Slovak (sk)";
    	case 0x041B: // = MAKELANGID(LANG_SLOVAK, SUBLANG_SLOVAK_SLOVAKIA)
    		return bSymbolic ? L"LANG_SLOVAK, SUBLANG_SLOVAK_SLOVAKIA"
    		                 : L"Slovak (sk), Slovakia (SK)";
    
    	case 0x001C: // = MAKELANGID(LANG_ALBANIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ALBANIAN, SUBLANG_NEUTRAL"
    		                 : L"Albanian (sq)";
    	case 0x041C: // = MAKELANGID(LANG_ALBANIAN, SUBLANG_ALBANIAN_ALBANIA)
    		return bSymbolic ? L"LANG_ALBANIAN, SUBLANG_ALBANIAN_ALBANIA"
    		                 : L"Albanian (sq), Albania (AL)";
    
    	case 0x001D: // = MAKELANGID(LANG_SWEDISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SWEDISH, SUBLANG_NEUTRAL"
    		                 : L"Swedish (sv)";
    #if 0
    	case 0x041D: // = MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH)
    		return bSymbolic ? L"LANG_SWEDISH, SUBLANG_SWEDISH"
    		                 : L"Swedish (sv), Sweden (SE)";
    #else
    	case 0x041D: // = MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH_SWEDEN)
    		return bSymbolic ? L"LANG_SWEDISH, SUBLANG_SWEDISH_SWEDEN"
    		                 : L"Swedish (sv), Sweden (SE)";
    #endif
    	case 0x081D: // = MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH_FINLAND)
    		return bSymbolic ? L"LANG_SWEDISH, SUBLANG_SWEDISH_FINLAND"
    		                 : L"Swedish (sv), Finland (FI)";
    
    	case 0x001E: // = MAKELANGID(LANG_THAI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_THAI, SUBLANG_NEUTRAL"
    		                 : L"Thai (th)";
    	case 0x041E: // = MAKELANGID(LANG_THAI, SUBLANG_THAI_THAILAND)
    		return bSymbolic ? L"LANG_THAI, SUBLANG_THAI_THAILAND"
    		                 : L"Thai (th), Thailand (TH)";
    
    	case 0x001F: // = MAKELANGID(LANG_TURKISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TURKISH, SUBLANG_NEUTRAL"
    		                 : L"Turkish (tr)";
    	case 0x041F: // = MAKELANGID(LANG_TURKISH, SUBLANG_TURKISH_TURKEY)
    		return bSymbolic ? L"LANG_TURKISH, SUBLANG_TURKISH_TURKEY"
    		                 : L"Turkish (tr), Turkey (TR)";
    
    	case 0x0020: // = MAKELANGID(LANG_URDU, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_URDU, SUBLANG_NEUTRAL"
    		                 : L"Urdu (ur)";
    	case 0x0420: // = MAKELANGID(LANG_URDU, SUBLANG_URDU_PAKISTAN)
    		return bSymbolic ? L"LANG_URDU, SUBLANG_URDU_PAKISTAN"
    		                 : L"Urdu (ur), Pakistan (PK)";
    	case 0x0820: // = MAKELANGID(LANG_URDU, SUBLANG_URDU_INDIA)
    		return bSymbolic ? L"LANG_URDU, SUBLANG_URDU_INDIA"
    		                 : L"Urdu (ur), India (IN)";
    
    	case 0x0021: // = MAKELANGID(LANG_INDONESIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_INDONESIAN, SUBLANG_NEUTRAL"
    		                 : L"Indonesian (id)";
    	case 0x0421: // = MAKELANGID(LANG_INDONESIAN, SUBLANG_INDONESIAN_INDONESIA)
    		return bSymbolic ? L"LANG_INDONESIAN, SUBLANG_INDONESIAN_INDONESIA"
    		                 : L"Indonesian (id), Indonesia (ID)";
    
    	case 0x0022: // = MAKELANGID(LANG_UKRAINIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_UKRAINIAN, SUBLANG_NEUTRAL"
    		                 : L"Ukrainian (uk)";
    	case 0x0422: // = MAKELANGID(LANG_UKRAINIAN, SUBLANG_UKRAINIAN_UKRAINE)
    		return bSymbolic ? L"LANG_UKRAINIAN, SUBLANG_UKRAINIAN_UKRAINE"
    		                 : L"Ukrainian (uk), Ukraine (UA)";
    
    	case 0x0023: // = MAKELANGID(LANG_BELARUSIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BELARUSIAN, SUBLANG_NEUTRAL"
    		                 : L"Belarusian (be)";
    	case 0x0423: // = MAKELANGID(LANG_BELARUSIAN, SUBLANG_BELARUSIAN_BELARUS)
    		return bSymbolic ? L"LANG_BELARUSIAN, SUBLANG_BELARUSIAN_BELARUS"
    		                 : L"Belarusian (be), Belarus (BY)";
    
    	case 0x0024: // = MAKELANGID(LANG_SLOVENIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SLOVENIAN, SUBLANG_NEUTRAL"
    		                 : L"Slovenian (sl)";
    	case 0x0424: // = MAKELANGID(LANG_SLOVENIAN, SUBLANG_SLOVENIAN_SLOVENIA)
    		return bSymbolic ? L"LANG_SLOVENIAN, SUBLANG_SLOVENIAN_SLOVENIA"
    		                 : L"Slovenian (sl), Slovenia (SI)";
    
    	case 0x0025: // = MAKELANGID(LANG_ESTONIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ESTONIAN, SUBLANG_NEUTRAL"
    		                 : L"Estonian (et)";
    	case 0x0425: // = MAKELANGID(LANG_ESTONIAN, SUBLANG_ESTONIAN_ESTONIA)
    		return bSymbolic ? L"LANG_ESTONIAN, SUBLANG_ESTONIAN_ESTONIA"
    		                 : L"Estonian (et), Estonia (EE)";
    
    	case 0x0026: // = MAKELANGID(LANG_LATVIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_LATVIAN, SUBLANG_NEUTRAL"
    		                 : L"Latvian (lv)";
    	case 0x0426: // = MAKELANGID(LANG_LATVIAN, SUBLANG_LATVIAN_LATVIA)
    		return bSymbolic ? L"LANG_LATVIAN, SUBLANG_LATVIAN_LATVIA"
    		                 : L"Latvian (lv), Latvia (LV)";
    
    	case 0x0027: // = MAKELANGID(LANG_LITHUANIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_LITHUANIAN, SUBLANG_NEUTRAL"
    		                 : L"Lithuanian (lt)";
    	case 0x0427: // = MAKELANGID(LANG_LITHUANIAN, SUBLANG_LITHUANIAN_LITHUANIA)
    		return bSymbolic ? L"LANG_LITHUANIAN, SUBLANG_LITHUANIAN_LITHUANIA"
    		                 : L"Lithuanian (lt), Lithuania (LT)";
    
    	case 0x0028: // = MAKELANGID(LANG_TAJIK, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TAJIK, SUBLANG_NEUTRAL"
    		                 : L"Tajik (tg)";
    	case 0x0428: // = MAKELANGID(LANG_TAJIK, SUBLANG_TAJIK_TAJIKISTAN)
    		return bSymbolic ? L"LANG_TAJIK, SUBLANG_TAJIK_TAJIKISTAN"
    		                 : L"Tajik (tg), Cyrillic (Cyrl), Tajikistan (TJ)";
    	case 0x7C28: // = MAKELANGID(LANG_TAJIK, SUBLANG_TAJIK_CYRILLIC)
    		return bSymbolic ? L"LANG_TAJIK, SUBLANG_TAJIK_CYRILLIC"
    		                 : L"Tajik (tg), Cyrillic (Cyrl)";
    #if 0
    	case 0x0029: // = MAKELANGID(LANG_FARSI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_FARSI, SUBLANG_NEUTRAL"
    		                 : L"Farsi (fa)";
    	case 0x0429: // = MAKELANGID(LANG_FARSI, SUBLANG_FARSI_IRAN)
    		return bSymbolic ? L"LANG_FARSI, SUBLANG_FARSI_IRAN"
    		                 : L"Farsi (fa), Iran (IR)";
    #else
    	case 0x0029: // = MAKELANGID(LANG_PERSIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_PERSIAN, SUBLANG_NEUTRAL"
    		                 : L"Persian (fa)";
    	case 0x0429: // = MAKELANGID(LANG_PERSIAN, SUBLANG_PERSIAN_IRAN)
    		return bSymbolic ? L"LANG_PERSIAN, SUBLANG_PERSIAN_IRAN"
    		                 : L"Persian (fa), Iran (IR)";
    #endif
    	case 0x002A: // = MAKELANGID(LANG_VIETNAMESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_VIETNAMESE, SUBLANG_NEUTRAL"
    		                 : L"Vietnamese (vi)";
    	case 0x042A: // = MAKELANGID(LANG_VIETNAMESE, SUBLANG_VIETNAMESE_VIETNAM)
    		return bSymbolic ? L"LANG_VIETNAMESE, SUBLANG_VIETNAMESE_VIETNAM"
    		                 : L"Vietnamese (vi), Vietnam (VN)";
    
    	case 0x002B: // = MAKELANGID(LANG_ARMENIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ARMENIAN, SUBLANG_NEUTRAL"
    		                 : L"Armenian (hy)";
    	case 0x042B: // = MAKELANGID(LANG_ARMENIAN, SUBLANG_ARMENIAN_ARMENIA)
    		return bSymbolic ? L"LANG_ARMENIAN, SUBLANG_ARMENIAN_ARMENIA"
    		                 : L"Armenian (hy), Armenia (AM)";
    #if 0
    	case 0x002C: // = MAKELANGID(LANG_AZERI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_AZERI, SUBLANG_NEUTRAL"
    		                 : L"Azeri (az)";
    	case 0x042C: // = MAKELANGID(LANG_AZERI, SUBLANG_AZERI_AZERBAIJAN_LATIN)
    		return bSymbolic ? L"LANG_AZERI, SUBLANG_AZERI_AZERBAIJAN_LATIN"
    		                 : L"Azeri (az), Latin (Latn), Azerbaijan (AZ)";
    	case 0x082C: // = MAKELANGID(LANG_AZERI, SUBLANG_AZERI_AZERBAIJAN_CYRILLIC)
    		return bSymbolic ? L"LANG_AZERI, SUBLANG_AZERI_AZERBAIJAN_CYRILLIC"
    		                 : L"Azeri (az), Cyrillic (Cyrl), Azerbaijan (AZ)";
    	case 0x742C: // = MAKELANGID(LANG_AZERI, SUBLANG_AZERI_CYRILLIC)
    		return bSymbolic ? L"LANG_AZERI, SUBLANG_AZERI_CYRILLIC"
    		                 : L"Azeri (az), Cyrillic (Cyrl)";
    	case 0x782C: // = MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN)
    		return bSymbolic ? L"LANG_AZERI, SUBLANG_AZERI_LATIN"
    		                 : L"Azeri (az), Latin (Latn)";
    #else
    	case 0x002C: // = MAKELANGID(LANG_AZERBAIJANI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_AZERBAIJANI, SUBLANG_NEUTRAL"
    		                 : L"Azerbaijani (az)";
    	case 0x042C: // = MAKELANGID(LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_AZERBAIJAN_LATIN)
    		return bSymbolic ? L"LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_AZERBAIJAN_LATIN"
    		                 : L"Azerbaijani (az), Latin (Latn), Azerbaijan (AZ)";
    	case 0x082C: // = MAKELANGID(LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_AZERBAIJAN_CYRILLIC)
    		return bSymbolic ? L"LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_AZERBAIJAN_CYRILLIC"
    		                 : L"Azerbaijani (az), Cyrillic (Cyrl), Azerbaijan (AZ)";
    	case 0x742C: // = MAKELANGID(LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_CYRILLIC)
    		return bSymbolic ? L"LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_CYRILLIC"
    		                 : L"Azerbaijani (az), Cyrillic (Cyrl)";
    	case 0x782C: // = MAKELANGID(LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_LATIN)
    		return bSymbolic ? L"LANG_AZERBAIJANI, SUBLANG_AZERBAIJANI_LATIN"
    		                 : L"Azerbaijani (az), Latin (Latn)";
    #endif
    	case 0x002D: // = MAKELANGID(LANG_BASQUE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BASQUE, SUBLANG_NEUTRAL"
    		                 : L"Basque (eu)";
    #if 0
    	case 0x042D: // = MAKELANGID(LANG_BASQUE, SUBLANG_BASQUE_BASQUE)
    		return bSymbolic ? L"LANG_BASQUE, SUBLANG_BASQUE_BASQUE"
    		                 : L"Basque (eu), Basque (ES)";
    #else
    	case 0x042D: // = MAKELANGID(LANG_BASQUE, SUBLANG_BASQUE_SPAIN)
    		return bSymbolic ? L"LANG_BASQUE, SUBLANG_BASQUE_SPAIN"
    		                 : L"Basque (eu), Spain (ES)";
    #endif
    	case 0x002E: // = MAKELANGID(LANG_UPPER_SORBIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_UPPER_SORBIAN, SUBLANG_NEUTRAL"
    		                 : L"Upper Sorbian (hsb)";
    	case 0x042E: // = MAKELANGID(LANG_UPPER_SORBIAN, SUBLANG_UPPER_SORBIAN_GERMANY)
    		return bSymbolic ? L"LANG_UPPER_SORBIAN, SUBLANG_UPPER_SORBIAN_GERMANY"
    		                 : L"Upper Sorbian (hsb), Germany (DE)";
    	case 0x082E: // = MAKELANGID(LANG_LOWER_SORBIAN, SUBLANG_LOWER_SORBIAN_GERMANY)
    		return bSymbolic ? L"LANG_LOWER_SORBIAN, SUBLANG_LOWER_SORBIAN_GERMANY"
    		                 : L"Lower Sorbian (dsb), Germany (DE)";
    	case 0x7C2E: // = MAKELANGID(LANG_LOWER_SORBIAN, SUBLANG_LOWER_SORBIAN)
    		return bSymbolic ? L"LANG_LOWER_SORBIAN, SUBLANG_LOWER_SORBIAN"
    		                 : L"Lower Sorbian (dsb)";
    
    	case 0x002F: // = MAKELANGID(LANG_MACEDONIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MACEDONIAN, SUBLANG_NEUTRAL"
    		                 : L"Macedonian (mk)";
    	case 0x042F: // = MAKELANGID(LANG_MACEDONIAN, SUBLANG_MACEDONIAN_MACEDONIA)
    		return bSymbolic ? L"LANG_MACEDONIAN, SUBLANG_MACEDONIAN_MACEDONIA"
    		                 : L"Macedonian (mk), Macedonia, FYROM (MK)";
    #if 0
    	case 0x0030: // = MAKELANGID(LANG_SUTU, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SUTU, SUBLANG_NEUTRAL"
    		                 : L"Sutu (st)";
    	case 0x0430: // = MAKELANGID(LANG_SUTU, SUBLANG_SUTU_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_SUTU, SUBLANG_SUTU_SOUTH_AFRICA"
    		                 : L"Sutu (st), South Africa (ZA)";
    	case 0x0830: // = MAKELANGID(LANG_SUTU, SUBLANG_SUTU_BOTSWANA)
    		return bSymbolic ? L"LANG_SUTU, SUBLANG_SUTU_BOTSWANA"
    		                 : L"Sutu (st), Botswana (BW)";
    #else
    	case 0x0030: // = MAKELANGID(LANG_SESOTHO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SESOTHO, SUBLANG_NEUTRAL"
    		                 : L"Sesotho (st)";
    	case 0x0430: // = MAKELANGID(LANG_SESOTHO, SUBLANG_SESOTHO_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_SESOTHO, SUBLANG_SESOTHO_SOUTH_AFRICA"
    		                 : L"Sesotho (st), South Africa (ZA)";
    	case 0x0830: // = MAKELANGID(LANG_SESOTHO, SUBLANG_SESOTHO_BOTSWANA)
    		return bSymbolic ? L"LANG_SESOTHO, SUBLANG_SESOTHO_BOTSWANA"
    		                 : L"Sesotho (st), Botswana (BW)";
    #endif
    	case 0x0031: // = MAKELANGID(LANG_TSONGA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TSONGA, SUBLANG_NEUTRAL"
    		                 : L"Tsonga (ts)";
    	case 0x0431: // = MAKELANGID(LANG_TSONGA, SUBLANG_TSONGA_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_TSONGA, SUBLANG_TSONGA_SOUTH_AFRICA"
    		                 : L"Tsonga (ts), South Africa (ZA)";
    	case 0x0831: // = MAKELANGID(LANG_TSONGA, SUBLANG_TSONGA_BOTSWANA)
    		return bSymbolic ? L"LANG_TSONGA, SUBLANG_TSONGA_BOTSWANA"
    		                 : L"Tsonga (ts), Botswana (BW)";
    #if 0
    	case 0x0032: // = MAKELANGID(LANG_TSWANA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TSWANA, SUBLANG_NEUTRAL"
    		                 : L"Tswana (tn)";
    	case 0x0432: // = MAKELANGID(LANG_TSWANA, SUBLANG_TSWANA_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_TSWANA, SUBLANG_TSWANA_SOUTH_AFRICA"
    		                 : L"Tswana (tn), South Africa (ZA)";
    	case 0x0832: // = MAKELANGID(LANG_TSWANA, SUBLANG_TSWANA_BOTSWANA)
    		return bSymbolic ? L"LANG_TSWANA, SUBLANG_TSWANA_BOTSWANA"
    		                 : L"Tswana (tn), Botswana (BW)";
    #else
    	case 0x0032: // = MAKELANGID(LANG_SETSWANA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SETSWANA, SUBLANG_NEUTRAL"
    		                 : L"Setswana (tn)";
    	case 0x0432: // = MAKELANGID(LANG_SETSWANA, SUBLANG_SETSWANA_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_SETSWANA, SUBLANG_SETSWANA_SOUTH_AFRICA"
    		                 : L"Setswana (tn), South Africa (ZA)";
    	case 0x0832: // = MAKELANGID(LANG_SETSWANA, SUBLANG_SETSWANA_BOTSWANA)
    		return bSymbolic ? L"LANG_SETSWANA, SUBLANG_SETSWANA_BOTSWANA"
    		                 : L"Setswana (tn), Botswana (BW)";
    #endif
    	case 0x0033: // = MAKELANGID(LANG_VENDA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_VENDA, SUBLANG_NEUTRAL"
    		                 : L"Venda (ve)";
    	case 0x0433: // = MAKELANGID(LANG_VENDA, SUBLANG_VENDA_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_VENDA, SUBLANG_VENDA_SOUTH_AFRICA"
    		                 : L"Venda (ve), South Africa (ZA)";
    
    	case 0x0034: // = MAKELANGID(LANG_XHOSA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_XHOSA, SUBLANG_NEUTRAL"
    		                 : L"Xhosa (xh)";
    	case 0x0434: // = MAKELANGID(LANG_XHOSA, SUBLANG_XHOSA_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_XHOSA, SUBLANG_XHOSA_SOUTH_AFRICA"
    		                 : L"Xhosa (xh), South Africa (ZA)";
    
    	case 0x0035: // = MAKELANGID(LANG_ZULU, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ZULU, SUBLANG_NEUTRAL"
    		                 : L"Zulu (zu)";
    	case 0x0435: // = MAKELANGID(LANG_ZULU, SUBLANG_ZULU_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_ZULU, SUBLANG_ZULU_SOUTH_AFRICA"
    		                 : L"Zulu (zu), South Africa (ZA)";
    
    	case 0x0036: // = MAKELANGID(LANG_AFRIKAANS, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_AFRIKAANS, SUBLANG_NEUTRAL"
    		                 : L"Afrikaans (af)";
    	case 0x0436: // = MAKELANGID(LANG_AFRIKAANS, SUBLANG_AFRIKAANS_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_AFRIKAANS, SUBLANG_AFRIKAANS_SOUTH_AFRICA"
    		                 : L"Afrikaans (af), South Africa (ZA)";
    
    	case 0x0037: // = MAKELANGID(LANG_GEORGIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_GEORGIAN, SUBLANG_NEUTRAL"
    		                 : L"Georgian (ka)";
    	case 0x0437: // = MAKELANGID(LANG_GEORGIAN, SUBLANG_GEORGIAN_GEORGIA)
    		return bSymbolic ? L"LANG_GEORGIAN, SUBLANG_GEORGIAN_GEORGIA"
    		                 : L"Georgian (ka), Georgia (GE)";
    
    	case 0x0038: // = MAKELANGID(LANG_FAEROESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_FAEROESE, SUBLANG_NEUTRAL"
    		                 : L"Faroese (fo)";
    	case 0x0438: // = MAKELANGID(LANG_FAEROESE, SUBLANG_FAEROESE_FAROE_ISLANDS)
    		return bSymbolic ? L"LANG_FAEROESE, SUBLANG_FAEROESE_FAROE_ISLANDS"
    		                 : L"Faroese (fo), Faroe Islands (FO)";
    
    	case 0x0039: // = MAKELANGID(LANG_HINDI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_HINDI, SUBLANG_NEUTRAL"
    		                 : L"Hindi (hi)";
    	case 0x0439: // = MAKELANGID(LANG_HINDI, SUBLANG_HINDI_INDIA)
    		return bSymbolic ? L"LANG_HINDI, SUBLANG_HINDI_INDIA"
    		                 : L"Hindi (hi), India (IN)";
    
    	case 0x003A: // = MAKELANGID(LANG_MALTESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MALTESE, SUBLANG_NEUTRAL"
    		                 : L"Maltese (mt)";
    	case 0x043A: // = MAKELANGID(LANG_MALTESE, SUBLANG_MALTESE_MALTA)
    		return bSymbolic ? L"LANG_MALTESE, SUBLANG_MALTESE_MALTA"
    		                 : L"Maltese (mt), Malta (MT)";
    
    	case 0x003B: // = MAKELANGID(LANG_SAMI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_NEUTRAL"
    		                 : L"Sami (se)";
    	case 0x043B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_NORTHERN_NORWAY)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_NORTHERN_NORWAY"
    		                 : L"Sami (se), Northern, Norway (NO)";
    	case 0x083B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_NORTHERN_SWEDEN)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_NORTHERN_SWEDEN"
    		                 : L"Sami (se), Northern, Sweden (SE)";
    	case 0x0C3B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_NORTHERN_FINLAND)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_NORTHERN_FINLAND"
    		                 : L"Sami (se), Northern, Finland (FI)";
    	case 0x103B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_LULE_NORWAY)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_LULE_NORWAY"
    		                 : L"Sami (smj), Lule, Norway (NO)";
    	case 0x143B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_LULE_SWEDEN)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_LULE_SWEDEN"
    		                 : L"Sami (smj), Lule, Sweden (SE)";
    	case 0x183B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_SOUTHERN_NORWAY)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_SOUTHERN_NORWAY"
    		                 : L"Sami (sma), Southern, Norway (NO)";
    	case 0x1C3B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_SOUTHERN_SWEDEN)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_SOUTHERN_SWEDEN"
    		                 : L"Sami (sma), Southern, Sweden (SE)";
    	case 0x203B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_SKOLT_FINLAND)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_SKOLT_FINLAND"
    		                 : L"Sami (sms), Skolt, Finland (FI)";
    	case 0x243B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_INARI_FINLAND)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_INARI_FINLAND"
    		                 : L"Sami (smn), Inari, Finland (FI)";
    	case 0x703B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_INARI)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_INARI"
    		                 : L"Sami (smn), Inari";
    	case 0x743B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_SKOLT)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_SKOLT"
    		                 : L"Sami (sms), Skolt";
    	case 0x783B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI"
    		                 : L"Sami (sma)";
    	case 0x7C3B: // = MAKELANGID(LANG_SAMI, SUBLANG_SAMI_LULE)
    		return bSymbolic ? L"LANG_SAMI, SUBLANG_SAMI_LULE"
    		                 : L"Sami (smj), Lule";
    
    	case 0x003C: // = MAKELANGID(LANG_IRISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_IRISH, SUBLANG_NEUTRAL"
    		                 : L"Irish (ga)";
    	case 0x083C: // = MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND)
    		return bSymbolic ? L"LANG_IRISH, SUBLANG_IRISH_IRELAND"
    		                 : L"Irish (ga), Ireland (IE)";
    
    	case 0x003D: // = MAKELANGID(LANG_YIDDISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_YIDDISH, SUBLANG_NEUTRAL"
    		                 : L"Yiddish (yi)";
    	case 0x043D: // = MAKELANGID(LANG_YIDDISH, SUBLANG_YIDDISH_HEBREW)
    		return bSymbolic ? L"LANG_YIDDISH, SUBLANG_YIDDISH_HEBREW"
    		                 : L"Yiddish (yi), Hebrew (Hebr)";
    
    	case 0x003E: // = MAKELANGID(LANG_MALAY, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MALAY, SUBLANG_NEUTRAL"
    		                 : L"Malay (ms)";
    	case 0x043E: // = MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA)
    		return bSymbolic ? L"LANG_MALAY, SUBLANG_MALAY_MALAYSIA"
    		                 : L"Malay (ms), Malaysia (MY)";
    	case 0x083E: // = MAKELANGID(LANG_MALAY, SUBLANG_MALAY_BRUNEI_DARUSSALAM)
    		return bSymbolic ? L"LANG_MALAY, SUBLANG_MALAY_BRUNEI_DARUSSALAM"
    		                 : L"Malay (ms), Brunei Darussalam (BN)";
    
    	case 0x003F: // = MAKELANGID(LANG_KAZAK, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KAZAK, SUBLANG_NEUTRAL"
    		                 : L"Kazakh (kk)";
    	case 0x043F: // = MAKELANGID(LANG_KAZAK, SUBLANG_KAZAK_KAZAKHSTAN)
    		return bSymbolic ? L"LANG_KAZAK, SUBLANG_KAZAK_KAZAKHSTAN"
    		                 : L"Kazakh (kk), Kazakhstan (KZ)";
    
    	case 0x0040: // = MAKELANGID(LANG_KYRGYZ, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KYRGYZ, SUBLANG_NEUTRAL"
    		                 : L"Kyrgyz (ky)";
    	case 0x0440: // = MAKELANGID(LANG_KYRGYZ, SUBLANG_KYRGYZ_KYRGYZSTAN)
    		return bSymbolic ? L"LANG_KYRGYZ, SUBLANG_KYRGYZ_KYRGYZSTAN"
    		                 : L"Kyrgyz (ky), Kyrgyzstan (KG)";
    
    	case 0x0041: // = MAKELANGID(LANG_SWAHILI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SWAHILI, SUBLANG_NEUTRAL"
    		                 : L"Kiswahili (sw)";
    #if 0
    	case 0x0441: // = MAKELANGID(LANG_SWAHILI, SUBLANG_SWAHILI)
    		return bSymbolic ? L"LANG_SWAHILI, SUBLANG_SWAHILI"
    		                 : L"Kiswahili (sw), Kenya (KE)";
    #else
    	case 0x0441: // = MAKELANGID(LANG_SWAHILI, SUBLANG_SWAHILI_KENYA)
    		return bSymbolic ? L"LANG_SWAHILI, SUBLANG_SWAHILI_KENYA"
    		                 : L"Kiswahili (sw), Kenya (KE)";
    #endif
    	case 0x0042: // = MAKELANGID(LANG_TURKMEN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TURKMEN, SUBLANG_NEUTRAL"
    		                 : L"Turkmen (tk)";
    	case 0x0442: // = MAKELANGID(LANG_TURKMEN, SUBLANG_TURKMEN_TURKMENISTAN)
    		return bSymbolic ? L"LANG_TURKMEN, SUBLANG_TURKMEN_TURKMENISTAN"
    		                 : L"Turkmen (tk), Turkmenistan (TM)";
    
    	case 0x0043: // = MAKELANGID(LANG_UZBEK, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_UZBEK, SUBLANG_NEUTRAL"
    		                 : L"Uzbek (uz)";
    	case 0x0443: // = MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_UZBEKISTAN_LATIN)
    		return bSymbolic ? L"LANG_UZBEK, SUBLANG_UZBEK_UZBEKISTAN_LATIN"
    		                 : L"Uzbek (uz), Latin (Latn), Uzbekistan (UZ)";
    	case 0x0843: // = MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_UZBEKISTAN_CYRILLIC)
    		return bSymbolic ? L"LANG_UZBEK, SUBLANG_UZBEK_UZBEKISTAN_CYRILLIC"
    		                 : L"Uzbek (uz), Cyrillic (Cyrl), Uzbekistan (UZ)";
    	case 0x7843: // = MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC)
    		return bSymbolic ? L"LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC"
    		                 : L"Uzbek (uz), Cyrillic (Cyrl)";
    	case 0x7C43: // = MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN)
    		return bSymbolic ? L"LANG_UZBEK, SUBLANG_UZBEK_LATIN"
    		                 : L"Uzbek (uz), Latin (Latn)";
    
    	case 0x0044: // = MAKELANGID(LANG_TATAR, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TATAR, SUBLANG_NEUTRAL"
    		                 : L"Tatar (tt)";
    	case 0x0444: // = MAKELANGID(LANG_TATAR, SUBLANG_TATAR_RUSSIA)
    		return bSymbolic ? L"LANG_TATAR, SUBLANG_TATAR_RUSSIA"
    		                 : L"Tatar (tt), Russia (RU)";
    	case 0x0844: // = MAKELANGID(LANG_TATAR, SUBLANG_TATAR_MONGOLIA)
    		return bSymbolic ? L"LANG_TATAR, SUBLANG_TATAR_MONGOLIA"
    		                 : L"Tatar (tt), Mongolia (MN)";
    #if 0
    	case 0x0045: // = MAKELANGID(LANG_BENGALI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BENGALI, SUBLANG_NEUTRAL"
    		                 : L"Bengali (bn)";
    	case 0x0445: // = MAKELANGID(LANG_BENGALI, SUBLANG_BENGALI_INDIA)
    		return bSymbolic ? L"LANG_BENGALI, SUBLANG_BENGALI_INDIA"
    		                 : L"Bengali (bn), India (IN)";
    	case 0x0845: // = MAKELANGID(LANG_BENGALI, SUBLANG_BENGALI_BANGLADESH)
    		return bSymbolic ? L"LANG_BENGALI, SUBLANG_BENGALI_BANGLADESH"
    		                 : L"Bengali (bn), Bangladesh (BD)";
    #else
    	case 0x0045: // = MAKELANGID(LANG_BANGLA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BANGLA, SUBLANG_NEUTRAL"
    		                 : L"Bangla (bn)";
    	case 0x0445: // = MAKELANGID(LANG_BANGLA, SUBLANG_BANGLA_INDIA)
    		return bSymbolic ? L"LANG_BANGLA, SUBLANG_BANGLA_INDIA"
    		                 : L"Bangla (bn), India (IN)";
    	case 0x0845: // = MAKELANGID(LANG_BANGLA, SUBLANG_BANGLA_BANGLADESH)
    		return bSymbolic ? L"LANG_BANGLA, SUBLANG_BANGLA_BANGLADESH"
    		                 : L"Bangla (bn), Bangladesh (BD)";
    #endif
    	case 0x0046: // = MAKELANGID(LANG_PUNJABI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_PUNJABI, SUBLANG_NEUTRAL"
    		                 : L"Punjabi (pa)";
    	case 0x0446: // = MAKELANGID(LANG_PUNJABI, SUBLANG_PUNJABI_INDIA)
    		return bSymbolic ? L"LANG_PUNJABI, SUBLANG_PUNJABI_INDIA"
    		                 : L"Punjabi (pa), Gurmukhi script, India (IN)";
    	case 0x0846: // = MAKELANGID(LANG_PUNJABI, SUBLANG_PUNJABI_PAKISTAN)
    		return bSymbolic ? L"LANG_PUNJABI, SUBLANG_PUNJABI_PAKISTAN"
    		                 : L"Punjabi (pa), Arabic (Arab), Pakistan (PK)";
    	case 0x7C46: // = MAKELANGID(LANG_PUNJABI, SUBLANG_PUNJABI_ARABIC)
    		return bSymbolic ? L"LANG_PUNJABI, SUBLANG_PUNJABI_ARABIC"
    		                 : L"Punjabi (pa), Arabic (Arab)";
    
    	case 0x0047: // = MAKELANGID(LANG_GUJARATI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_GUJARATI, SUBLANG_NEUTRAL"
    		                 : L"Gujarati (gu)";
    	case 0x0447: // = MAKELANGID(LANG_GUJARATI, SUBLANG_GUJARATI_INDIA)
    		return bSymbolic ? L"LANG_GUJARATI, SUBLANG_GUJARATI_INDIA"
    		                 : L"Gujarati (gu), India (IN)";
    #if 0
    	case 0x0048: // = MAKELANGID(LANG_ORIYA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ORIYA, SUBLANG_NEUTRAL"
    		                 : L"Oriya (or)";
    	case 0x0448: // = MAKELANGID(LANG_ORIYA, SUBLANG_ORIYA_INDIA)
    		return bSymbolic ? L"LANG_ORIYA, SUBLANG_ORIYA_INDIA"
    		                 : L"Oriya (or), India (IN)";
    #else
    	case 0x0048: // = MAKELANGID(LANG_ODIA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ODIA, SUBLANG_NEUTRAL"
    		                 : L"Odia (or)";
    	case 0x0448: // = MAKELANGID(LANG_ODIA, SUBLANG_ODIA_INDIA)
    		return bSymbolic ? L"LANG_ODIA, SUBLANG_ODIA_INDIA"
    		                 : L"Odia (or), India (IN)";
    #endif
    	case 0x0049: // = MAKELANGID(LANG_TAMIL, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TAMIL, SUBLANG_NEUTRAL"
    		                 : L"Tamil (ta)";
    	case 0x0449: // = MAKELANGID(LANG_TAMIL, SUBLANG_TAMIL_INDIA)
    		return bSymbolic ? L"LANG_TAMIL, SUBLANG_TAMIL_INDIA"
    		                 : L"Tamil (ta), India (IN)";
    	case 0x0849: // = MAKELANGID(LANG_TAMIL, SUBLANG_TAMIL_SRI_LANKA)
    		return bSymbolic ? L"LANG_TAMIL, SUBLANG_TAMIL_SRI_LANKA"
    		                 : L"Tamil (ta), Sri Lanka (LK)";
    
    	case 0x004A: // = MAKELANGID(LANG_TELUGU, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TELUGU, SUBLANG_NEUTRAL"
    		                 : L"Telugu (te)";
    	case 0x044A: // = MAKELANGID(LANG_TELUGU, SUBLANG_TELUGU_INDIA)
    		return bSymbolic ? L"LANG_TELUGU, SUBLANG_TELUGU_INDIA"
    		                 : L"Telugu (te), India (IN)";
    
    	case 0x004B: // = MAKELANGID(LANG_KANNADA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KANNADA, SUBLANG_NEUTRAL"
    		                 : L"Kannada (kn)";
    	case 0x044B: // = MAKELANGID(LANG_KANNADA, SUBLANG_KANNADA_INDIA)
    		return bSymbolic ? L"LANG_KANNADA, SUBLANG_KANNADA_INDIA"
    		                 : L"Kannada (kn), India (IN)";
    
    	case 0x004C: // = MAKELANGID(LANG_MALAYALAM, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MALAYALAM, SUBLANG_NEUTRAL"
    		                 : L"Malayalam (ml)";
    	case 0x044C: // = MAKELANGID(LANG_MALAYALAM, SUBLANG_MALAYALAM_INDIA)
    		return bSymbolic ? L"LANG_MALAYALAM, SUBLANG_MALAYALAM_INDIA"
    		                 : L"Malayalam (ml), India (IN)";
    
    	case 0x004D: // = MAKELANGID(LANG_ASSAMESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ASSAMESE, SUBLANG_NEUTRAL"
    		                 : L"Assamese (as)";
    	case 0x044D: // = MAKELANGID(LANG_ASSAMESE, SUBLANG_ASSAMESE_INDIA)
    		return bSymbolic ? L"LANG_ASSAMESE, SUBLANG_ASSAMESE_INDIA"
    		                 : L"Assamese (as), India (IN)";
    
    	case 0x004E: // = MAKELANGID(LANG_MARATHI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MARATHI, SUBLANG_NEUTRAL"
    		                 : L"Marathi (mr)";
    	case 0x044E: // = MAKELANGID(LANG_MARATHI, SUBLANG_MARATHI_INDIA)
    		return bSymbolic ? L"LANG_MARATHI, SUBLANG_MARATHI_INDIA"
    		                 : L"Marathi (mr), India (IN)";
    
    	case 0x004F: // = MAKELANGID(LANG_SANSKRIT, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SANSKRIT, SUBLANG_NEUTRAL"
    		                 : L"Sanskrit (sa)";
    	case 0x044F: // = MAKELANGID(LANG_SANSKRIT, SUBLANG_SANSKRIT_INDIA)
    		return bSymbolic ? L"LANG_SANSKRIT, SUBLANG_SANSKRIT_INDIA"
    		                 : L"Sanskrit (sa), India (IN)";
    
    	case 0x0050: // = MAKELANGID(LANG_MONGOLIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MONGOLIAN, SUBLANG_NEUTRAL"
    		                 : L"Mongolian (mn)";
    	case 0x0450: // = MAKELANGID(LANG_MONGOLIAN, SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA)
    		return bSymbolic ? L"LANG_MONGOLIAN, SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA"
    		                 : L"Mongolian (mn), Cyrillic (Cyrl), Mongolia (MN)";
    	case 0x0850: // = MAKELANGID(LANG_MONGOLIAN, SUBLANG_MONGOLIAN_PRC)
    		return bSymbolic ? L"LANG_MONGOLIAN, SUBLANG_MONGOLIAN_PRC"
    		                 : L"Mongolian (mn), Mongolian (Mong), People\'s Republic of China (CN)";
    	case 0x0C50: // = MAKELANGID(LANG_MONGOLIAN, SUBLANG_MONGOLIAN_MONGOLIAN_MONGOLIA)
    		return bSymbolic ? L"LANG_MONGOLIAN, SUBLANG_MONGOLIAN_MONGOLIAN_MONGOLIA"
    		                 : L"Mongolian (mn), Mongolian (Mong), Mongolia (MN)";
    	case 0x7850: // = MAKELANGID(LANG_MONGOLIAN, SUBLANG_MONGOLIAN_CYRILLIC)
    		return bSymbolic ? L"LANG_MONGOLIAN, SUBLANG_MONGOLIAN_CYRILLIC"
    		                 : L"Mongolian (mn), Cyrillic (Cyrl)";
    	case 0x7C50: // = MAKELANGID(LANG_MONGOLIAN, SUBLANG_MONGOLIAN_MONGOLIAN)
    		return bSymbolic ? L"LANG_MONGOLIAN, SUBLANG_MONGOLIAN_MONGOLIAN"
    		                 : L"Mongolian (mn), Mongolian (Mong)";
    
    	case 0x0051: // = MAKELANGID(LANG_TIBETAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TIBETAN, SUBLANG_NEUTRAL"
    		                 : L"Tibetan (bo)";
    	case 0x0451: // = MAKELANGID(LANG_TIBETAN, SUBLANG_TIBETAN_PRC)
    		return bSymbolic ? L"LANG_TIBETAN, SUBLANG_TIBETAN_PRC"
    		                 : L"Tibetan (bo), People\'s Republic of China (CN)";
    	case 0x0851: // = MAKELANGID(LANG_TIBETAN, SUBLANG_TIBETAN_BHUTAN)
    		return bSymbolic ? L"LANG_TIBETAN, SUBLANG_TIBETAN_BHUTAN"
    		                 : L"Tibetan (bo), Bhutan (BT)";
    	case 0x0C51: // = MAKELANGID(LANG_DZONGKHA, SUBLANG_DZONGKHA_BHUTAN)
    		return bSymbolic ? L"LANG_DZONGKHA, SUBLANG_DZONGKHA_BHUTAN"
    		                 : L"Dzongkha (dz), Bhutan (BT)";
    
    	case 0x0052: // = MAKELANGID(LANG_WELSH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_WELSH, SUBLANG_NEUTRAL"
    		                 : L"Welsh (cy)";
    	case 0x0452: // = MAKELANGID(LANG_WELSH, SUBLANG_WELSH_UNITED_KINGDOM)
    		return bSymbolic ? L"LANG_WELSH, SUBLANG_WELSH_UNITED_KINGDOM"
    		                 : L"Welsh (cy), United Kingdom (GB)";
    
    	case 0x0053: // = MAKELANGID(LANG_KHMER, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KHMER, SUBLANG_NEUTRAL"
    		                 : L"Khmer (kh)";
    	case 0x0453: // = MAKELANGID(LANG_KHMER, SUBLANG_KHMER_CAMBODIA)
    		return bSymbolic ? L"LANG_KHMER, SUBLANG_KHMER_CAMBODIA"
    		                 : L"Khmer (kh), Cambodia (KH)";
    
    	case 0x0054: // = MAKELANGID(LANG_LAO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_LAO, SUBLANG_NEUTRAL"
    		                 : L"Lao (lo)";
    	case 0x0454: // = MAKELANGID(LANG_LAO, SUBLANG_LAO_LAO)
    		return bSymbolic ? L"LANG_LAO, SUBLANG_LAO_LAO"
    		                 : L"Lao (lo), Lao P.D.R. (LA)";
    #if 0
    	case 0x0055: // = MAKELANGID(LANG_BIRMESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BIRMESE, SUBLANG_NEUTRAL"
    		                 : L"Birmese (my)";
    	case 0x0455: // = MAKELANGID(LANG_BIRMESE, SUBLANG_BIRMESE_MYANMAR)
    		return bSymbolic ? L"LANG_BIRMESE, SUBLANG_BIRMESE_MYANMAR"
    		                 : L"Birmese (my), Myanmar (MM)";
    #else
    	case 0x0055: // = MAKELANGID(LANG_BURMESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BURMESE, SUBLANG_NEUTRAL"
    		                 : L"Burmese (my)";
    	case 0x0455: // = MAKELANGID(LANG_BURMESE, SUBLANG_BURMESE_MYANMAR)
    		return bSymbolic ? L"LANG_BURMESE, SUBLANG_BURMESE_MYANMAR"
    		                 : L"Burmese (my), Myanmar (MM)";
    #endif
    	case 0x0056: // = MAKELANGID(LANG_GALICIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_GALICIAN, SUBLANG_NEUTRAL"
    		                 : L"Galician (gl)";
    	case 0x0456: // = MAKELANGID(LANG_GALICIAN, SUBLANG_GALICIAN_GALICIAN)
    		return bSymbolic ? L"LANG_GALICIAN, SUBLANG_GALICIAN_GALICIAN"
    		                 : L"Galician (gl), Spain (ES)";
    
    	case 0x0057: // = MAKELANGID(LANG_KONKANI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KONKANI, SUBLANG_NEUTRAL"
    		                 : L"Konkani (kok)";
    	case 0x0457: // = MAKELANGID(LANG_KONKANI, SUBLANG_KONKANI_INDIA)
    		return bSymbolic ? L"LANG_KONKANI, SUBLANG_KONKANI_INDIA"
    		                 : L"Konkani (kok), India (IN)";
    
    	case 0x0058: // = MAKELANGID(LANG_MANIPURI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MANIPURI, SUBLANG_NEUTRAL"
    		                 : L"Manipuri (mni)";
    	case 0x0458: // = MAKELANGID(LANG_MANIPURI, SUBLANG_MANIPURI_INDIA)
    		return bSymbolic ? L"LANG_MANIPURI, SUBLANG_MANIPURI_INDIA"
    		                 : L"Manipuri (mni), India (IN)";
    
    	case 0x0059: // = MAKELANGID(LANG_SINDHI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SINDHI, SUBLANG_NEUTRAL"
    		                 : L"Sindhi (sd)";
    	case 0x0459: // = MAKELANGID(LANG_SINDHI, SUBLANG_SINDHI_INDIA_DEVANAGARI)
    		return bSymbolic ? L"LANG_SINDHI, SUBLANG_SINDHI_INDIA_DEVANAGARI"
    		                 : L"Sindhi (sd), Devanagari (Deva), India (IN)";
    	case 0x0859: // = MAKELANGID(LANG_SINDHI, SUBLANG_SINDHI_PAKISTAN)
    		return bSymbolic ? L"LANG_SINDHI, SUBLANG_SINDHI_PAKISTAN"
    		                 : L"Sindhi (sd), Arabic (Arab), Pakistan (PK)";
    	case 0x0C59: // = MAKELANGID(LANG_SINDHI, SUBLANG_SINDHI_AFGHANISTAN)
    		return bSymbolic ? L"LANG_SINDHI, SUBLANG_SINDHI_AFGHANISTAN"
    		                 : L"Sindhi (sd), Afghanistan (AF)";
    	case 0x7C59: // = MAKELANGID(LANG_SINDHI, SUBLANG_SINDHI_ARABIC)
    		return bSymbolic ? L"LANG_SINDHI, SUBLANG_SINDHI_ARABIC"
    		                 : L"Sindhi (sd), Arabic (Arab)";
    
    	case 0x005A: // = MAKELANGID(LANG_SYRIAC, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SYRIAC, SUBLANG_NEUTRAL"
    		                 : L"Syriac (syr)";
    #if 0
    	case 0x045A: // = MAKELANGID(LANG_SYRIAC, SUBLANG_SYRIAC)
    		return bSymbolic ? L"LANG_SYRIAC, SUBLANG_SYRIAC"
    		                 : L"Syriac (syr), Syria (SY)";
    #else
    	case 0x045A: // = MAKELANGID(LANG_SYRIAC, SUBLANG_SYRIAC_SYRIA)
    		return bSymbolic ? L"LANG_SYRIAC, SUBLANG_SYRIAC_SYRIA"
    		                 : L"Syriac (syr), Syria (SY)";
    #endif
    	case 0x005B: // = MAKELANGID(LANG_SINHALESE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SINHALESE, SUBLANG_NEUTRAL"
    		                 : L"Sinhala (si)";
    	case 0x045B: // = MAKELANGID(LANG_SINHALESE, SUBLANG_SINHALESE_SRI_LANKA)
    		return bSymbolic ? L"LANG_SINHALESE, SUBLANG_SINHALESE_SRI_LANKA"
    		                 : L"Sinhala (si), Sri Lanka (LK)";
    
    	case 0x005C: // = MAKELANGID(LANG_CHEROKEE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_CHEROKEE, SUBLANG_NEUTRAL"
    		                 : L"Cherokee (chr)";
    	case 0x045C: // = MAKELANGID(LANG_CHEROKEE, SUBLANG_CHEROKEE_US)
    		return bSymbolic ? L"LANG_CHEROKEE, SUBLANG_CHEROKEE_US"
    		                 : L"Cherokee (chr), Cherokee (Cher), United States (US)";
    	case 0x7C5C: // = MAKELANGID(LANG_CHEROKEE, SUBLANG_CHEROKEE_CHEROKEE)
    		return bSymbolic ? L"LANG_CHEROKEE, SUBLANG_CHEROKEE_CHEROKEE"
    		                 : L"Cherokee (chr), Cherokee (Cher)";
    
    	case 0x005D: // = MAKELANGID(LANG_INUKTITUT, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_INUKTITUT, SUBLANG_NEUTRAL"
    		                 : L"Inuktitut (iu)";
    	case 0x045D: // = MAKELANGID(LANG_INUKTITUT, SUBLANG_INUKTITUT_CANADA)
    		return bSymbolic ? L"LANG_INUKTITUT, SUBLANG_INUKTITUT_CANADA"
    		                 : L"Inuktitut (iu), Syllabic (Cans), Canada (CA)";
    	case 0x085D: // = MAKELANGID(LANG_INUKTITUT, SUBLANG_INUKTITUT_CANADA_LATIN)
    		return bSymbolic ? L"LANG_INUKTITUT, SUBLANG_INUKTITUT_CANADA_LATIN"
    		                 : L"Inuktitut (iu), Latin (Latn), Canada (CA)";
    	case 0x785D: // = MAKELANGID(LANG_INUKTITUT, SUBLANG_INUKTITUT)
    		return bSymbolic ? L"LANG_INUKTITUT, SUBLANG_INUKTITUT"
    		                 : L"Inuktitut (iu), Syllabic (Cans)";
    	case 0x7C5D: // = MAKELANGID(LANG_INUKTITUT, SUBLANG_INUKTITUT_LATIN)
    		return bSymbolic ? L"LANG_INUKTITUT, SUBLANG_INUKTITUT_LATIN"
    		                 : L"Inuktitut (iu), Latin (Latn)";
    
    	case 0x005E: // = MAKELANGID(LANG_AMHARIC, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_AMHARIC, SUBLANG_NEUTRAL"
    		                 : L"Amharic (am)";
    	case 0x045E: // = MAKELANGID(LANG_AMHARIC, SUBLANG_AMHARIC_ETHIOPIA)
    		return bSymbolic ? L"LANG_AMHARIC, SUBLANG_AMHARIC_ETHIOPIA"
    		                 : L"Amharic (am), Ethiopia (ET)";
    
    	case 0x005F: // = MAKELANGID(LANG_TAMAZIGHT, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TAMAZIGHT, SUBLANG_NEUTRAL"
    		                 : L"Tamazight (tzm)";
    	case 0x045F: // = MAKELANGID(LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_MOROCCO_ARABIC)
    		return bSymbolic ? L"LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_MOROCCO_ARABIC"
    		                 : L"Tamazight (tmz), Arabic (Arab), Morocco (MA)";
    	case 0x085F: // = MAKELANGID(LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_ALGERIA_LATIN)
    		return bSymbolic ? L"LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_ALGERIA_LATIN"
    		                 : L"Tamazight (tzm), Latin (Latn), Algeria (DZ)";
    	case 0x0C5F: // = MAKELANGID(LANG_TAMANAKU, SUBLANG_TAMANAKU_MOROCCO)
    		return bSymbolic ? L"LANG_TAMANAKU, SUBLANG_TAMANAKU_MOROCCO"
    		                 : L"Tamanaku (tmz), Morocco (MA)";
    	case 0x105F: // = MAKELANGID(LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_MOROCCO_TIFINAGH)
    		return bSymbolic ? L"LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_MOROCCO_TIFINAGH"
    		                 : L"Tamazight (tzm), Tifinagh (Tfng), Morocco (MA)";
    	case 0x785F: // = MAKELANGID(LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_TIFINAGH)
    		return bSymbolic ? L"LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_TIFINAGH"
    		                 : L"Tamazight (tzm), Tifinagh (Tfng)";
    	case 0x7C5F: // = MAKELANGID(LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_LATIN)
    		return bSymbolic ? L"LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_LATIN"
    		                 : L"Tamazight (tzm), Latin (Latn)";
    
    	case 0x0060: // = MAKELANGID(LANG_KASHMIRI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KASHMIRI, SUBLANG_NEUTRAL"
    		                 : L"Kashmiri (ks)";
    	case 0x0460: // = MAKELANGID(LANG_KASHMIRI, SUBLANG_KASHMIRI_ARABIC)
    		return bSymbolic ? L"LANG_KASHMIRI, SUBLANG_KASHMIRI_ARABIC"
    		                 : L"Kashmiri (ks), Arabic (Arab)";
    #if 0
    	case 0x0860: // = MAKELANGID(LANG_KASHMIRI, SUBLANG_KASHMIRI_INDIA)
    		return bSymbolic ? L"LANG_KASHMIRI, SUBLANG_KASHMIRI_INDIA"
    		                 : L"Kashmiri (ks), India (IN)";
    #elif 0
    	case 0x0860: // = MAKELANGID(LANG_KASHMIRI, SUBLANG_KASHMIRI_SASIA)
    		return bSymbolic ? L"LANG_KASHMIRI, SUBLANG_KASHMIRI_SASIA"
    		                 : L"Kashmiri (ks), South Asia";
    #else
    	case 0x0860: // = MAKELANGID(LANG_KASHMIRI, SUBLANG_KASHMIRI_DEVANAGARI)
    		return bSymbolic ? L"LANG_KASHMIRI, SUBLANG_KASHMIRI_DEVANAGARI"
    		                 : L"Kashmiri (ks), Devanagari (Deva)";
    #endif
    	case 0x0061: // = MAKELANGID(LANG_NEPALI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_NEPALI, SUBLANG_NEUTRAL"
    		                 : L"Nepali (ne)";
    	case 0x0461: // = MAKELANGID(LANG_NEPALI, SUBLANG_NEPALI_NEPAL)
    		return bSymbolic ? L"LANG_NEPALI, SUBLANG_NEPALI_NEPAL"
    		                 : L"Nepali (ne), Nepal (NP)";
    	case 0x0861: // = MAKELANGID(LANG_NEPALI, SUBLANG_NEPALI_INDIA)
    		return bSymbolic ? L"LANG_NEPALI, SUBLANG_NEPALI_INDIA"
    		                 : L"Nepali (ne), India (IN)";
    
    	case 0x0062: // = MAKELANGID(LANG_FRISIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_FRISIAN, SUBLANG_NEUTRAL"
    		                 : L"Frisian (fy)";
    	case 0x0462: // = MAKELANGID(LANG_FRISIAN, SUBLANG_FRISIAN_NETHERLANDS)
    		return bSymbolic ? L"LANG_FRISIAN, SUBLANG_FRISIAN_NETHERLANDS"
    		                 : L"Frisian (fy), Netherlands (NL)";
    
    	case 0x0063: // = MAKELANGID(LANG_PASHTO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_PASHTO, SUBLANG_NEUTRAL"
    		                 : L"Pashto (ps)";
    	case 0x0463: // = MAKELANGID(LANG_PASHTO, SUBLANG_PASHTO_AFGHANISTAN)
    		return bSymbolic ? L"LANG_PASHTO, SUBLANG_PASHTO_AFGHANISTAN"
    		                 : L"Pashto (ps), Afghanistan (AF)";
    
    	case 0x0064: // = MAKELANGID(LANG_FILIPINO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_FILIPINO, SUBLANG_NEUTRAL"
    		                 : L"Filipino (fil)";
    	case 0x0464: // = MAKELANGID(LANG_FILIPINO, SUBLANG_FILIPINO_PHILIPPINES)
    		return bSymbolic ? L"LANG_FILIPINO, SUBLANG_FILIPINO_PHILIPPINES"
    		                 : L"Filipino (fil), Philippines (PH)";
    
    	case 0x0065: // = MAKELANGID(LANG_DIVEHI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_DIVEHI, SUBLANG_NEUTRAL"
    		                 : L"Divehi (div)";
    	case 0x0465: // = MAKELANGID(LANG_DIVEHI, SUBLANG_DIVEHI_MALDIVES)
    		return bSymbolic ? L"LANG_DIVEHI, SUBLANG_DIVEHI_MALDIVES"
    		                 : L"Divehi (div), Maldives (MV)";
    
    	case 0x0066: // = MAKELANGID(LANG_EDO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_EDO, SUBLANG_NEUTRAL"
    		                 : L"Bini / Edo (bin)";
    	case 0x0466: // = MAKELANGID(LANG_EDO, SUBLANG_EDO_NIGERIA)
    		return bSymbolic ? L"LANG_EDO, SUBLANG_EDO_NIGERIA"
    		                 : L"Bini / Edo (bin), Nigeria (NG)";
    
    	case 0x0067: // = MAKELANGID(LANG_FULAH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_FULAH, SUBLANG_NEUTRAL"
    		                 : L"Fulah (ff)";
    	case 0x0467: // = MAKELANGID(LANG_FULAH, SUBLANG_FULAH_NIGERIA)
    		return bSymbolic ? L"LANG_FULAH, SUBLANG_FULAH_NIGERIA"
    		                 : L"Fulah (ff), Nigeria (NG)";
    	case 0x0867: // = MAKELANGID(LANG_FULAH, SUBLANG_FULAH_SENEGAL)
    		return bSymbolic ? L"LANG_FULAH, SUBLANG_FULAH_SENEGAL"
    		                 : L"Fulah (ff), Latin (Latn), Senegal (SN)";
    	case 0x7C67: // = MAKELANGID(LANG_FULAH, SUBLANG_FULAH_LATIN)
    		return bSymbolic ? L"LANG_FULAH, SUBLANG_FULAH_LATIN"
    		                 : L"Fulah (ff), Latin (Latn)";
    
    	case 0x0068: // = MAKELANGID(LANG_HAUSA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_HAUSA, SUBLANG_NEUTRAL"
    		                 : L"Hausa (ha)";
    	case 0x0468: // = MAKELANGID(LANG_HAUSA, SUBLANG_HAUSA_NIGERIA_LATIN)
    		return bSymbolic ? L"LANG_HAUSA, SUBLANG_HAUSA_NIGERIA_LATIN"
    		                 : L"Hausa (ha), Latin (Latn), Nigeria (NG)";
    	case 0x7C68: // = MAKELANGID(LANG_HAUSA, SUBLANG_HAUSA_LATIN)
    		return bSymbolic ? L"LANG_HAUSA, SUBLANG_HAUSA_LATIN"
    		                 : L"Hausa (ha), Latin (Latn)";
    
    	case 0x0069: // = MAKELANGID(LANG_IBIBIO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_IBIBIO, SUBLANG_NEUTRAL"
    		                 : L"Ibibio (ibb)";
    	case 0x0469: // = MAKELANGID(LANG_IBIBIO, SUBLANG_IBIBIO_NIGERIA)
    		return bSymbolic ? L"LANG_IBIBIO, SUBLANG_IBIBIO_NIGERIA"
    		                 : L"Ibibio (ibb), Nigeria (NG)";
    
    	case 0x006A: // = MAKELANGID(LANG_YORUBA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_YORUBA, SUBLANG_NEUTRAL"
    		                 : L"Yoruba (yo)";
    	case 0x046A: // = MAKELANGID(LANG_YORUBA, SUBLANG_YORUBA_NIGERIA)
    		return bSymbolic ? L"LANG_YORUBA, SUBLANG_YORUBA_NIGERIA"
    		                 : L"Yoruba (yo), Nigeria (NG)";
    
    	case 0x006B: // = MAKELANGID(LANG_QUECHUA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_QUECHUA, SUBLANG_NEUTRAL"
    		                 : L"Quechua (quz)";
    	case 0x046B: // = MAKELANGID(LANG_QUECHUA, SUBLANG_QUECHUA_BOLIVIA)
    		return bSymbolic ? L"LANG_QUECHUA, SUBLANG_QUECHUA_BOLIVIA"
    		                 : L"Quechua (quz), Bolivia (BO)";
    	case 0x086B: // = MAKELANGID(LANG_QUECHUA, SUBLANG_QUECHUA_ECUADOR)
    		return bSymbolic ? L"LANG_QUECHUA, SUBLANG_QUECHUA_ECUADOR"
    		                 : L"Quechua (quz), Ecuador (EC)";
    	case 0x0C6B: // = MAKELANGID(LANG_QUECHUA, SUBLANG_QUECHUA_PERU)
    		return bSymbolic ? L"LANG_QUECHUA, SUBLANG_QUECHUA_PERU"
    		                 : L"Quechua (quz), Peru (PE)";
    #if 0
    	case 0x006C: // = MAKELANGID(LANG_SOTHO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SOTHO, SUBLANG_NEUTRAL"
    		                 : L"Sesotho sa Leboa (nso)";
    	case 0x046C: // = MAKELANGID(LANG_SOTHO, SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_SOTHO, SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA"
    		                 : L"Sesotho sa Leboa (nso), South Africa (ZA)";
    #else
    	case 0x006C: // = MAKELANGID(LANG_SESOTHO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SESOTHO, SUBLANG_NEUTRAL"
    		                 : L"Sesotho sa Leboa (nso)";
    	case 0x046C: // = MAKELANGID(LANG_SESOTHO, SUBLANG_SESOTHO_NORTHERN_SOUTH_AFRICA)
    		return bSymbolic ? L"LANG_SESOTHO, SUBLANG_SESOTHO_NORTHERN_SOUTH_AFRICA"
    		                 : L"Sesotho sa Leboa (nso), South Africa (ZA)";
    #endif
    	case 0x006D: // = MAKELANGID(LANG_BASHKIR, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BASHKIR, SUBLANG_NEUTRAL"
    		                 : L"Bashkir (ba)";
    	case 0x046D: // = MAKELANGID(LANG_BASHKIR, SUBLANG_BASHKIR_RUSSIA)
    		return bSymbolic ? L"LANG_BASHKIR, SUBLANG_BASHKIR_RUSSIA"
    		                 : L"Bashkir (ba), Russia (RU)";
    
    	case 0x006E: // = MAKELANGID(LANG_LUXEMBOURGISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_LUXEMBOURGISH, SUBLANG_NEUTRAL"
    		                 : L"Luxembourgish (lb)";
    	case 0x046E: // = MAKELANGID(LANG_LUXEMBOURGISH, SUBLANG_LUXEMBOURGISH_LUXEMBOURG)
    		return bSymbolic ? L"LANG_LUXEMBOURGISH, SUBLANG_LUXEMBOURGISH_LUXEMBOURG"
    		                 : L"Luxembourgish (lb), Luxembourg (LU)";
    #if 0
    	case 0x006F: // = MAKELANGID(LANG_GREENLANDIC, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_GREENLANDIC, SUBLANG_NEUTRAL"
    		                 : L"Greenlandic (kl)";
    	case 0x046F: // = MAKELANGID(LANG_GREENLANDIC, SUBLANG_GREENLANDIC_GREENLAND)
    		return bSymbolic ? L"LANG_GREENLANDIC, SUBLANG_GREENLANDIC_GREENLAND"
    		                 : L"Greenlandic (kl), Greenland (GL)";
    #else
    	case 0x006F: // = MAKELANGID(LANG_KALAALLISUT, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KALAALLISUT, SUBLANG_NEUTRAL"
    		                 : L"Kalaallisut (kl)";
    	case 0x046F: // = MAKELANGID(LANG_KALAALLISUT, SUBLANG_KALAALLISUT_GREENLAND)
    		return bSymbolic ? L"LANG_KALAALLISUT, SUBLANG_KALAALLISUT_GREENLAND"
    		                 : L"Kalaallisut (kl), Greenland (GL)";
    #endif
    	case 0x0070: // = MAKELANGID(LANG_IGBO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_IGBO, SUBLANG_NEUTRAL"
    		                 : L"Igbo (ig)";
    	case 0x0470: // = MAKELANGID(LANG_IGBO, SUBLANG_IGBO_NIGERIA)
    		return bSymbolic ? L"LANG_IGBO, SUBLANG_IGBO_NIGERIA"
    		                 : L"Igbo (ig), Nigeria (NG)";
    
    	case 0x0071: // = MAKELANGID(LANG_KANURI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KANURI, SUBLANG_NEUTRAL"
    		                 : L"Kanuri (kr)";
    	case 0x0471: // = MAKELANGID(LANG_KANURI, SUBLANG_KANURI_NIGERIA)
    		return bSymbolic ? L"LANG_KANURI, SUBLANG_KANURI_NIGERIA"
    		                 : L"Kanuri (kr), Nigeria (NG)";
    
    	case 0x0072: // = MAKELANGID(LANG_OROMO, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_OROMO, SUBLANG_NEUTRAL"
    		                 : L"Oromo (om)";
    	case 0x0472: // = MAKELANGID(LANG_OROMO, SUBLANG_OROMO_ETHIOPIA)
    		return bSymbolic ? L"LANG_OROMO, SUBLANG_OROMO_ETHIOPIA"
    		                 : L"Oromo (om), Ethiopia (ET)";
    #if 0
    	case 0x0073: // = MAKELANGID(LANG_TIGRIGNA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TIGRIGNA, SUBLANG_NEUTRAL"
    		                 : L"Tigrigna (ti)";
    	case 0x0473: // = MAKELANGID(LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ETHIOPIA)
    		return bSymbolic ? L"LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ETHIOPIA"
    		                 : L"Tigrigna (ti), Ethiopia (ET)";
    	case 0x0873: // = MAKELANGID(LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ERITREA)
    		return bSymbolic ? L"LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ERITREA"
    		                 : L"Tigrigna (ti), Eritrea (ER)";
    #else
    	case 0x0073: // = MAKELANGID(LANG_TIGRINYA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TIGRINYA, SUBLANG_NEUTRAL"
    		                 : L"Tigrinya (ti)";
    	case 0x0473: // = MAKELANGID(LANG_TIGRINYA, SUBLANG_TIGRINYA_ETHIOPIA)
    		return bSymbolic ? L"LANG_TIGRINYA, SUBLANG_TIGRINYA_ETHIOPIA"
    		                 : L"Tigrinya (ti), Ethiopia (ET)";
    	case 0x0873: // = MAKELANGID(LANG_TIGRINYA, SUBLANG_TIGRINYA_ERITREA)
    		return bSymbolic ? L"LANG_TIGRINYA, SUBLANG_TIGRINYA_ERITREA"
    		                 : L"Tigrinya (ti), Eritrea (ER)";
    #endif
    	case 0x0074: // = MAKELANGID(LANG_GUARANI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_GUARANI, SUBLANG_NEUTRAL"
    		                 : L"Guarani (gn)";
    	case 0x0474: // = MAKELANGID(LANG_GUARANI, SUBLANG_GUARANI_PARAGUAY)
    		return bSymbolic ? L"LANG_GUARANI, SUBLANG_GUARANI_PARAGUAY"
    		                 : L"Guarani (gn), Paraguay (PY)";
    
    	case 0x0075: // = MAKELANGID(LANG_HAWAIIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_HAWAIIAN, SUBLANG_NEUTRAL"
    		                 : L"Hawaiian (haw)";
    	case 0x0475: // = MAKELANGID(LANG_HAWAIIAN, SUBLANG_HAWAIIAN_US)
    		return bSymbolic ? L"LANG_HAWAIIAN, SUBLANG_HAWAIIAN_US"
    		                 : L"Hawaiian (haw), United States (US)";
    
    	case 0x0076: // = MAKELANGID(LANG_LATIN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_LATIN, SUBLANG_NEUTRAL"
    		                 : L"Latin (la)";
    	case 0x0476: // = MAKELANGID(LANG_LATIN, SUBLANG_LATIN_VATICAN)
    		return bSymbolic ? L"LANG_LATIN, SUBLANG_LATIN_VATICAN"
    		                 : L"Latin (la), Vatican (VA)";
    
    	case 0x0077: // = MAKELANGID(LANG_SOMALI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SOMALI, SUBLANG_NEUTRAL"
    		                 : L"Somali (so)";
    	case 0x0477: // = MAKELANGID(LANG_SOMALI, SUBLANG_SOMALI_SOMALIA)
    		return bSymbolic ? L"LANG_SOMALI, SUBLANG_SOMALI_SOMALIA"
    		                 : L"Somali (so), Somalia (SO)";
    
    	case 0x0078: // = MAKELANGID(LANG_YI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_YI, SUBLANG_NEUTRAL"
    		                 : L"Yi (ii)";
    	case 0x0478: // = MAKELANGID(LANG_YI, SUBLANG_YI_PRC)
    		return bSymbolic ? L"LANG_YI, SUBLANG_YI_PRC"
    		                 : L"Yi (ii), People\'s Republic of China (CN)";
    
    	case 0x0079: // = MAKELANGID(LANG_PAPIAMENTU, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_PAPIAMENTU, SUBLANG_NEUTRAL"
    		                 : L"Papiamentu (pap)";
    	case 0x0479: // = MAKELANGID(LANG_PAPIAMENTU, SUBLANG_PAPIAMENTU_ANTILLES)
    		return bSymbolic ? L"LANG_PAPIAMENTU, SUBLANG_PAPIAMENTU_ANTILLES"
    		                 : L"Papiamentu (pap), Netherlands Antilles (AN)";
    	case 0x0879: // = MAKELANGID(LANG_PAPIAMENTU, SUBLANG_PAPIAMENTU_ARUBA)
    		return bSymbolic ? L"LANG_PAPIAMENTU, SUBLANG_PAPIAMENTU_ARUBA"
    		                 : L"Papiamentu (pap), Aruba (AW)";
    #if 0
    	case 0x007A: // = MAKELANGID(LANG_MAPUDUNGUN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MAPUDUNGUN, SUBLANG_NEUTRAL"
    		                 : L"Mapudungun (arn)";
    	case 0x047A: // = MAKELANGID(LANG_MAPUDUNGUN, SUBLANG_MAPUDUNGUN_CHILE)
    		return bSymbolic ? L"LANG_MAPUDUNGUN, SUBLANG_MAPUDUNGUN_CHILE"
    		                 : L"Mapudungun (arn), Chile (CL)";
    #else
    	case 0x007A: // = MAKELANGID(LANG_MAPUCHE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MAPUCHE, SUBLANG_NEUTRAL"
    		                 : L"Mapuche (arn)";
    	case 0x047A: // = MAKELANGID(LANG_MAPUCHE, SUBLANG_MAPUCHE_CHILE)
    		return bSymbolic ? L"LANG_MAPUCHE, SUBLANG_MAPUCHE_CHILE"
    		                 : L"Mapuche (arn), Chile (CL)";
    #endif
    	case 0x007C: // = MAKELANGID(LANG_MOHAWK, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MOHAWK, SUBLANG_NEUTRAL"
    		                 : L"Mohawk (moh)";
    	case 0x047C: // = MAKELANGID(LANG_MOHAWK, SUBLANG_MOHAWK_MOHAWK)
    		return bSymbolic ? L"LANG_MOHAWK, SUBLANG_MOHAWK_MOHAWK"
    		                 : L"Mohawk (moh), Canada (CA)";
    
    	case 0x007E: // = MAKELANGID(LANG_BRETON, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_BRETON, SUBLANG_NEUTRAL"
    		                 : L"Breton (br)";
    	case 0x047E: // = MAKELANGID(LANG_BRETON, SUBLANG_BRETON_FRANCE)
    		return bSymbolic ? L"LANG_BRETON, SUBLANG_BRETON_FRANCE"
    		                 : L"Breton (br), France (FR)";
    
    	case 0x007F: // = MAKELANGID(LANG_INVARIANT, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_INVARIANT, SUBLANG_NEUTRAL"
    		                 : L"Invariant Language, Invariant Country";
    
    	case 0x0080: // = MAKELANGID(LANG_UIGHUR, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_UIGHUR, SUBLANG_NEUTRAL"
    		                 : L"Uyghur (ug)";
    	case 0x0480: // = MAKELANGID(LANG_UIGHUR, SUBLANG_UIGHUR_PRC)
    		return bSymbolic ? L"LANG_UIGHUR, SUBLANG_UIGHUR_PRC"
    		                 : L"Uyghur (ug), People\'s Republic of China (CN)";
    
    	case 0x0081: // = MAKELANGID(LANG_MAORI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MAORI, SUBLANG_NEUTRAL"
    		                 : L"Maori (mi)";
    	case 0x0481: // = MAKELANGID(LANG_MAORI, SUBLANG_MAORI_NEW_ZEALAND)
    		return bSymbolic ? L"LANG_MAORI, SUBLANG_MAORI_NEW_ZEALAND"
    		                 : L"Maori (mi), New Zealand (NZ)";
    
    	case 0x0082: // = MAKELANGID(LANG_OCCITAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_OCCITAN, SUBLANG_NEUTRAL"
    		                 : L"Occitan (oc)";
    	case 0x0482: // = MAKELANGID(LANG_OCCITAN, SUBLANG_OCCITAN_FRANCE)
    		return bSymbolic ? L"LANG_OCCITAN, SUBLANG_OCCITAN_FRANCE"
    		                 : L"Occitan (oc), France (FR)";
    
    	case 0x0083: // = MAKELANGID(LANG_CORSICAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_CORSICAN, SUBLANG_NEUTRAL"
    		                 : L"Corsican (co)";
    	case 0x0483: // = MAKELANGID(LANG_CORSICAN, SUBLANG_CORSICAN_FRANCE)
    		return bSymbolic ? L"LANG_CORSICAN, SUBLANG_CORSICAN_FRANCE"
    		                 : L"Corsican (co), France (FR)";
    
    	case 0x0084: // = MAKELANGID(LANG_ALSATIAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_ALSATIAN, SUBLANG_NEUTRAL"
    		                 : L"Alsatian (gsw)";
    	case 0x0484: // = MAKELANGID(LANG_ALSATIAN, SUBLANG_ALSATIAN_FRANCE)
    		return bSymbolic ? L"LANG_ALSATIAN, SUBLANG_ALSATIAN_FRANCE"
    		                 : L"Alsatian (gsw), France (FR)";
    #if 0
    	case 0x0085: // = MAKELANGID(LANG_YAKUT, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_YAKUT, SUBLANG_NEUTRAL"
    		                 : L"Yakut (sah)";
    	case 0x0485: // = MAKELANGID(LANG_YAKUT, SUBLANG_YAKUT_RUSSIA)
    		return bSymbolic ? L"LANG_YAKUT, SUBLANG_YAKUT_RUSSIA"
    		                 : L"Yakut (sah), Russia (RU)";
    #else
    	case 0x0085: // = MAKELANGID(LANG_SAKHA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SAKHA, SUBLANG_NEUTRAL"
    		                 : L"Sakha (sah)";
    	case 0x0485: // = MAKELANGID(LANG_SAKHA, SUBLANG_SAKHA_RUSSIA)
    		return bSymbolic ? L"LANG_SAKHA, SUBLANG_SAKHA_RUSSIA"
    		                 : L"Sakha (sah), Russia (RU)";
    #endif
    	case 0x0086: // = MAKELANGID(LANG_KICHE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KICHE, SUBLANG_NEUTRAL"
    		                 : L"K\'iche (qut)";
    	case 0x0486: // = MAKELANGID(LANG_KICHE, SUBLANG_KICHE_GUATEMALA)
    		return bSymbolic ? L"LANG_KICHE, SUBLANG_KICHE_GUATEMALA"
    		                 : L"K\'iche (qut), Guatemala (GT)";
    	case 0x7C86: // = MAKELANGID(LANG_KICHE, SUBLANG_KICHE_GUATEMALA)
    		return bSymbolic ? L"LANG_KICHE, SUBLANG_KICHE_GUATEMALA"
    		                 : L"K\'iche (qut), Guatemala (GT)";
    
    	case 0x0087: // = MAKELANGID(LANG_KINYARWANDA, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_KINYARWANDA, SUBLANG_NEUTRAL"
    		                 : L"Kinyarwanda (rw)";
    	case 0x0487: // = MAKELANGID(LANG_KINYARWANDA, SUBLANG_KINYARWANDA_RWANDA)
    		return bSymbolic ? L"LANG_KINYARWANDA, SUBLANG_KINYARWANDA_RWANDA"
    		                 : L"Kinyarwanda (rw), Rwanda (RW)";
    
    	case 0x0088: // = MAKELANGID(LANG_WOLOF, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_WOLOF, SUBLANG_NEUTRAL"
    		                 : L"Wolof (wo)";
    	case 0x0488: // = MAKELANGID(LANG_WOLOF, SUBLANG_WOLOF_SENEGAL)
    		return bSymbolic ? L"LANG_WOLOF, SUBLANG_WOLOF_SENEGAL"
    		                 : L"Wolof (wo), Senegal (SN)";
    
    	case 0x008C: // = MAKELANGID(LANG_DARI, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_DARI, SUBLANG_NEUTRAL"
    		                 : L"Dari (prs)";
    	case 0x048C: // = MAKELANGID(LANG_DARI, SUBLANG_DARI_AFGHANISTAN)
    		return bSymbolic ? L"LANG_DARI, SUBLANG_DARI_AFGHANISTAN"
    		                 : L"Dari (prs), Afghanistan (AF)";
    
    	case 0x008D: // = MAKELANGID(LANG_MALAGASY, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_MALAGASY, SUBLANG_NEUTRAL"
    		                 : L"Plateau Malagasy (plt)";
    	case 0x048D: // = MAKELANGID(LANG_MALAGASY, SUBLANG_MALAGASY_MADAGASCAR)
    		return bSymbolic ? L"LANG_MALAGASY, SUBLANG_MALAGASY_MADAGASCAR"
    		                 : L"Plateau Malagasy (plt), Madagascar (MG)";
    
    	case 0x008E: // = MAKELANGID(LANG_YUE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_YUE, SUBLANG_NEUTRAL"
    		                 : L"Yue (yue)";
    	case 0x048E: // = MAKELANGID(LANG_YUE, SUBLANG_YUE_HONGKONG)
    		return bSymbolic ? L"LANG_YUE, SUBLANG_YUE_HONGKONG"
    		                 : L"Yue (yue), Hongkong S.A.R. (HK)";
    
    	case 0x008F: // = MAKELANGID(LANG_SHAN, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SHAN, SUBLANG_NEUTRAL"
    		                 : L"Tai Nüa (tdd)";
    	case 0x048F: // = MAKELANGID(LANG_SHAN, SUBLANG_SHAN_PRC)
    		return bSymbolic ? L"LANG_SHAN, SUBLANG_SHAN_PRC"
    		                 : L"Tai Nüa (tdd), People\'s Republic of China (CN)";
    
    	case 0x0090: // = MAKELANGID(LANG_TAILUE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_TAILUE, SUBLANG_NEUTRAL"
    		                 : L"Tai Lü (khb)";
    	case 0x0490: // = MAKELANGID(LANG_TAILUE, SUBLANG_TAILUE_PRC)
    		return bSymbolic ? L"LANG_TAILUE, SUBLANG_TAILUE_PRC"
    		                 : L"Tai Lü (khb), People\'s Republic of China (CN)";
    
    	case 0x0091: // = MAKELANGID(LANG_SCOTTISH_GAELIC, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_SCOTTISH_GAELIC, SUBLANG_NEUTRAL"
    		                 : L"Scottish Gaelic (gd)";
    	case 0x0491: // = MAKELANGID(LANG_SCOTTISH_GAELIC, SUBLANG_SCOTTISH_GAELIC)
    		return bSymbolic ? L"LANG_SCOTTISH_GAELIC, SUBLANG_SCOTTISH_GAELIC"
    		                 : L"Scottish Gaelic (gd), Great Britain (GB)";
    
    	case 0x0092: // = MAKELANGID(LANG_CENTRAL_KURDISH, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_CENTRAL_KURDISH, SUBLANG_NEUTRAL"
    		                 : L"Central Kurdish (ku)";
    	case 0x0492: // = MAKELANGID(LANG_CENTRAL_KURDISH, SUBLANG_CENTRAL_KURDISH_IRAQ)
    		return bSymbolic ? L"LANG_CENTRAL_KURDISH, SUBLANG_CENTRAL_KURDISH_IRAQ"
    		                 : L"Central Kurdish (ku), Arabic (Arab), Iraq (IQ)";
    	case 0x7C92: // = MAKELANGID(LANG_CENTRAL_KURDISH, SUBLANG_CENTRAL_KURDISH_ARABIC)
    		return bSymbolic ? L"LANG_CENTRAL_KURDISH, SUBLANG_CENTRAL_KURDISH_ARABIC"
    		                 : L"Central Kurdish (ku), Arabic (Arab)";
    
    	case 0x0093: // = MAKELANGID(LANG_QUICHE, SUBLANG_NEUTRAL)
    		return bSymbolic ? L"LANG_QUICHE, SUBLANG_NEUTRAL"
    		                 : L"Quiche (quc)";
    	case 0x0493: // = MAKELANGID(LANG_QUICHE, SUBLANG_QUICHE_COLOMBIA)
    		return bSymbolic ? L"LANG_QUICHE, SUBLANG_QUICHE_COLOMBIA"
    		                 : L"Quiche (quc), Colombia (CO)";
    
    	case 0x0501: // = MAKELANGID(LANG_PSEUDO_BASE, SUBLANG_DEFAULT)
    		return bSymbolic ? L"LANG_PSEUDO_BASE, SUBLANG_DEFAULT"
    		                 : L"Pseudo locale language (qps), Base (ploc)";
    
    	case 0x0901: // = MAKELANGID(LANG_PSEUDO_SELFHOST, SUBLANG_DEFAULT)
    		return bSymbolic ? L"LANG_PSEUDO_SELFHOST, SUBLANG_DEFAULT"
    		                 : L"Pseudo locale language (qps), Latin (Latn)";
    
    	case 0x05FE: // = MAKELANGID(LANG_PSEUDO_EAST_ASIA, SUBLANG_DEFAULT)
    		return bSymbolic ? L"LANG_PSEUDO_EAST_ASIA, SUBLANG_DEFAULT"
    		                 : L"Pseudo locale language (qps), East Asian (ploca)";
    
    	case 0x09FF: // = MAKELANGID(LANG_PSEUDO_MIRRORED, SUBLANG_PSEUDO_MIRRORED)
    		return bSymbolic ? L"LANG_PSEUDO_MIRRORED, SUBLANG_PSEUDO_MIRRORED"
    		                 : L"Pseudo locale language (qps), Mirrored (plocm)";
    
    	default:
    		return NULL;
    	}
    }
    
    const	LPCWSTR	szFileOSHigh[] = {L"Unknown",				// VOS_UNKNOWN
    		                  L"MS-DOS",				// VOS_DOS
    		                  L"OS/2 (16-bit)",			// VOS_OS216
    		                  L"OS/2 (32-bit)",			// VOS_OS232
    		                  L"Windows NT",			// VOS_NT
    		                  L"Windows CE"};			// VOS_WINCE
    
    const	LPCWSTR	szFileOSLow[] = {L"Base",				// VOS__BASE
    		                 L"Windows (16-bit)",			// VOS__WINDOWS16
    		                 L"Presentation Manager (16-bit)",	// VOS__PM16
    		                 L"Presentation Manager (32-bit)",	// VOS__PM32
    		                 L"Windows (32-bit)"};			// VOS__WINDOWS32
    
    const	LPCWSTR	szFileType[] = {L"Unknown",				// VFT_UNKNOWN
    		                L"Application",				// VFT_APP
    		                L"DLL",					// VFT_DLL
    		                L"Driver",				// VFT_DRV
    		                L"Font",				// VFT_FONT
    		                L"Virtual Device",			// VFT_VXD
    		                L"Undefined",
    		                L"Static Library"};			// VFT_STATIC_LIB
    
    const	LPCWSTR	szFileDriverType[] = {L"Unknown",			// VFT2_UNKNOWN
    		                      L"Printer",			// VFT2_DRV_PRINTER
    		                      L"Keyboard",			// VFT2_DRV_KEYBOARD
    		                      L"Language",			// VFT2_DRV_LANGUAGE
    		                      L"Display",			// VFT2_DRV_DISPLAY
    		                      L"Mouse",				// VFT2_DRV_MOUSE
    		                      L"Network",			// VFT2_DRV_NETWORK
    		                      L"System",			// VFT2_DRV_SYSTEM
    		                      L"Installable",			// VFT2_DRV_INSTALLABLE
    		                      L"Sound",				// VFT2_DRV_SOUND
    		                      L"Communications",		// VFT2_DRV_COMM
    		                      L"Input Method",			// VFT2_DRV_INPUTMETHOD
    		                      L"Versioned Printer"};		// VFT2_DRV_VERSIONED_PRINTER
    
    const	LPCWSTR	szFileFontType[] = {L"Unknown",				// VFT2_UNKNOWN
    		                    L"Raster",				// VFT2_FONT_RASTER
    		                    L"Vector",				// VFT2_FONT_VECTOR
    		                    L"TrueType"};			// VFT2_FONT_TRUETYPE
    
    BOOL	WINAPI	Resource(HANDLE                   hConsole,
    		         HANDLE                   hOutput,
    		         BYTE                     *lpAddress,
    		         IMAGE_RESOURCE_DIRECTORY *lpRoot,
    		         IMAGE_RESOURCE_DIRECTORY *lpLevel,
    		         LPCWSTR                  lpType,
    		         LPCWSTR                  lpName,
    		         DWORD                    dwLevel)	// 0 = Type, 1 = Id, 2 = Language
    {
    	BOOL	bOutput = TRUE;
    	DWORD	dwManifest;
    	DWORD	dwUnicode;
    	DWORD	dwMessage;
    	DWORD	dwBlock;
    	DWORD	dwEntry;
    	DWORD	dwValue;
    	DWORD	dwKey;
    	DWORD	dw;
    	LPVOID	lp;
    	LPVOID	lpManifest;
    	LPCWSTR	lpValue;
    
    	VS_VERSIONINFO	*lpVersion;
    	MUI_RESOURCE	*lpMUI;
    
    	MESSAGE_RESOURCE_DATA	*lpTable;
    	MESSAGE_RESOURCE_BLOCK	*lpBlock;
    	MESSAGE_RESOURCE_ENTRY	*lpMessage;
    
    	IMAGE_RESOURCE_DATA_ENTRY	*lpData;
    	IMAGE_RESOURCE_DIR_STRING_U	*lpUnicode;
    	IMAGE_RESOURCE_DIRECTORY_ENTRY	*lpEntry;
    
    	for (lpEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *) (lpLevel + 1),
    	     dwEntry = 0;
    	     dwEntry < lpLevel->NumberOfNamedEntries + lpLevel->NumberOfIdEntries;
    	     dwEntry++)
    	{
    		if ((lpEntry[dwEntry].Name & IMAGE_RESOURCE_NAME_IS_STRING) == IMAGE_RESOURCE_NAME_IS_STRING)
    		{
    			lpUnicode = (IMAGE_RESOURCE_DIR_STRING_U *) ((BYTE *) lpRoot + (lpEntry[dwEntry].Name ^ IMAGE_RESOURCE_NAME_IS_STRING));
    
    			bOutput &= PrintDirect(hOutput, L"\t\t\t\tName   = " + 2 - dwLevel, dwLevel + 11);
    			bOutput &= PrintDirect(hOutput, lpUnicode->NameString, lpUnicode->Length);
    			bOutput &= PrintString(hOutput, L"\r\n");
    			bOutput &= PrintFormat(hOutput, L"\t\t\t\tOffset = 0x%08lX\r\n" + 2 - dwLevel, lpEntry[dwEntry].OffsetToData);
    
    			if (dwLevel == 1)
    				lpName = lpUnicode->NameString;
    			else if (dwLevel == 0)
    				lpType = lpUnicode->NameString;
    		}
    		else
    			if (dwLevel > 1)
    				bOutput &= PrintFormat(hOutput,
    				                       L"\t\t\t\tLanguage = %hu (%ls)\r\n"
    				                       L"\t\t\t\tOffset   = 0x%08lX\r\n",
    				                       lpEntry[dwEntry].Id, ResourceLanguageName(lpEntry[dwEntry].Id, TRUE),
    				                       lpEntry[dwEntry].OffsetToData);
    			else if (dwLevel > 0)
    			{
    				bOutput &= PrintFormat(hOutput,
    				                       L"\t\t\tId     = %hu\r\n"
    				                       L"\t\t\tOffset = 0x%08lX\r\n",
    				                       lpEntry[dwEntry].Id,
    				                       lpEntry[dwEntry].OffsetToData);
    
    				lpName = MAKEINTRESOURCE(lpEntry[dwEntry].Id);
    			}
    			else
    			{
    				bOutput &= PrintFormat(hOutput,
    				                       L"\t\tType   = %hu (%ls)\r\n"
    				                       L"\t\tOffset = 0x%08lX\r\n",
    				                       lpEntry[dwEntry].Id, ResourceTypeName(lpEntry[dwEntry].Id),
    				                       lpEntry[dwEntry].OffsetToData);
    
    				lpType = MAKEINTRESOURCE(lpEntry[dwEntry].Id);
    			}
    
    		if ((lpEntry[dwEntry].OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY) == IMAGE_RESOURCE_DATA_IS_DIRECTORY)
    			bOutput &= Resource(hConsole,
    			                    hOutput,
    			                    lpAddress,
    			                    lpRoot,
    			                    (IMAGE_RESOURCE_DIRECTORY *) ((BYTE *) lpRoot + (lpEntry[dwEntry].OffsetToData ^ IMAGE_RESOURCE_DATA_IS_DIRECTORY)),
    			                    lpType,
    			                    lpName,
    			                    dwLevel + 1);
    		else
    		{
    			lpData = (IMAGE_RESOURCE_DATA_ENTRY *) ((BYTE *) lpRoot + lpEntry[dwEntry].OffsetToData);
    
    			bOutput &= PrintFormat(hOutput,
    			                       L"\t\t\t\t\tAddress   = 0x%08lX\r\n"
    			                       L"\t\t\t\t\tSize      = %lu\r\n"
    			                       L"\t\t\t\t\tCode Page = %lu\r\n"
    			                       L"\t\t\t\t\tReserved  = 0x%08lX\r\n",
    			                       lpData->OffsetToData,
    			                       lpData->Size,
    			                       lpData->CodePage,
    			                       lpData->Reserved);
    
    			if (IS_INTRESOURCE(lpType))
    				switch ((WORD) lpType)
    				{
    				case RT_STRING:
    
    					// NOTE: every RT_STRING resource, a STRINGTABLE, holds 16 UNICODE strings
    					//       IMAGE_RESOURCE_DIR_STRING_U of up to 65535 characters each, which
    					//       need not be L'\0' terminated and may contain L'\0', with their
    					//       character count (including the terminating L'\0' if present)
    					//       stored in front of them.
    
    					for (lpUnicode = (IMAGE_RESOURCE_DIR_STRING_U *) (lpAddress + lpData->OffsetToData),
    					     dwUnicode = 16; dwUnicode > 0; dwUnicode--,
    					     lpUnicode = (IMAGE_RESOURCE_DIR_STRING_U *) (lpUnicode->NameString + lpUnicode->Length))
    					{
    						dw = lpUnicode->Length;
    
    						if (dw == 0)
    							continue;
    
    						bOutput &= PrintFormat(hOutput,
    						                       L"\t\t\t\t\t%6lu:\tLength = %lu\r\n"
    						                       L"\t\t\t\t\t\tString = ",
    							               IS_INTRESOURCE(lpName) ? (WORD) lpName * 16 - dwUnicode : 16 - dwUnicode, dw);
    
    						while (dw-- > 0)
    							if (lpUnicode->NameString[dw] < L' ')
    								lpUnicode->NameString[dw] += L'\x2400';
    
    						bOutput &= PrintDirect(hOutput, lpUnicode->NameString, lpUnicode->Length);
    						bOutput &= PrintString(hOutput, L"\r\n");
    					}
    
    					break;
    
    				case RT_MESSAGETABLE:
    
    					for (lpTable = (MESSAGE_RESOURCE_DATA *) (lpAddress + lpData->OffsetToData),
    					     lpBlock = lpTable->Blocks,
    					     dwBlock = 0; dwBlock < lpTable->NumberOfBlocks; dwBlock++)
    					{
    						if (lpBlock[dwBlock].LowId == lpBlock[dwBlock].HighId)
    							bOutput &= PrintFormat(hOutput,
    							                       L"\t\t\t%6lu:\tMessage ID 0x%08lX\r\n",
    							                       dwBlock, lpBlock[dwBlock].LowId);
    						else
    							bOutput &= PrintFormat(hOutput,
    							                       L"\t\t\t%6lu:\tMessage IDs 0x%08lX to 0x%08lX\r\n",
    							                       dwBlock, lpBlock[dwBlock].LowId, lpBlock[dwBlock].HighId);
    
    						for (lpMessage = (MESSAGE_RESOURCE_ENTRY *) ((BYTE *) lpTable + lpBlock[dwBlock].OffsetToEntries),
    						     dwMessage = lpBlock[dwBlock].LowId; dwMessage <= lpBlock[dwBlock].HighId; dwMessage++,
    						     lpMessage = (MESSAGE_RESOURCE_ENTRY *) ((BYTE *) lpMessage + lpMessage->Length))
    							if (lpMessage->Flags == MESSAGE_RESOURCE_UNICODE)
    							{
    								bOutput &= PrintFormat(hOutput,
    								                       L"\t\t\t\t0x%08lX:\tSize = %hu\r\n"
    								                       L"\t\t\t\t\t\tText = ",
    								                       dwMessage, lpMessage->Length);
    
    								for (dw = 0; dw < ((BYTE *) lpMessage + lpMessage->Length - lpMessage->Text) / sizeof(L'\0'); dw++)
    									if (((LPWSTR) lpMessage->Text)[dw] < L' ')
    										((LPWSTR) lpMessage->Text)[dw] += L'\x2400';
    
    								bOutput &= PrintDirect(hOutput, (LPCWSTR) lpMessage->Text, dw);
    								bOutput &= PrintString(hOutput, L"\r\n");
    							}
    							else if (lpMessage->Flags == MESSAGE_RESOURCE_ANSI)
    								bOutput &= PrintFormat(hOutput,
    								                       L"\t\t\t\t0x%08lX:\tSize = %hu\r\n"
    								                       L"\t\t\t\t\t\tText = %.999hs\r\n",
    								                       dwMessage, lpMessage->Length, lpMessage->Text);
    							else
    								PrintConsole(hConsole,
    								             L"Text type %hu of message 0x%08lX neither UNICODE nor ANSI!\n",
    								             lpMessage->Flags, dwMessage);
    					}
    
    					break;
    
    				case RT_VERSION:
    
    					lpVersion = (VS_VERSIONINFO *) (lpAddress + lpData->OffsetToData);
    
    					bOutput &= PrintFormat(hOutput,
    					                       L"\t\t\t\t\tFixedFileInfo:\r\n"
    					                       L"\t\t\t\t\t\tProduct Version   = %hu.%hu:%hu.%hu\r\n"
    					                       L"\t\t\t\t\t\tModule Version    = %hu.%hu:%hu.%hu\r\n"
    					                       L"\t\t\t\t\t\tModule Flags      = 0x%08lX\r\n"
    					                       L"\t\t\t\t\t\tModule Type       = 0x%08lX (%ls)\r\n"
    					                       L"\t\t\t\t\t\tModule Subtype    = 0x%08lX (%ls)\r\n"
    					                       L"\t\t\t\t\t\tModule Time Stamp = 0x%08lX:%08lX\r\n"
    					                       L"\t\t\t\t\t\tTarget OS         = %hu:%hu (%ls, %ls)\r\n",
    					                       HIWORD(lpVersion->vsFFI.dwProductVersionMS), LOWORD(lpVersion->vsFFI.dwProductVersionMS),
    					                       HIWORD(lpVersion->vsFFI.dwProductVersionLS), LOWORD(lpVersion->vsFFI.dwProductVersionLS),
    					                       HIWORD(lpVersion->vsFFI.dwFileVersionMS), LOWORD(lpVersion->vsFFI.dwFileVersionMS),
    					                       HIWORD(lpVersion->vsFFI.dwFileVersionLS), LOWORD(lpVersion->vsFFI.dwFileVersionLS),
    					                       lpVersion->vsFFI.dwFileFlags,
    					                       lpVersion->vsFFI.dwFileType,
    					                       lpVersion->vsFFI.dwFileType < sizeof(szFileType) / sizeof(*szFileType) ? szFileType[lpVersion->vsFFI.dwFileType] : L"Undefined",
    					                       lpVersion->vsFFI.dwFileSubtype,
    					                       lpVersion->vsFFI.dwFileType == VFT_DRV ? (lpVersion->vsFFI.dwFileSubtype < sizeof(szFileDriverType) / sizeof(*szFileDriverType) ? szFileDriverType[lpVersion->vsFFI.dwFileSubtype] : L"Undefined") :
    							       lpVersion->vsFFI.dwFileType == VFT_FONT ? (lpVersion->vsFFI.dwFileSubtype < sizeof(szFileFontType) / sizeof(*szFileFontType) ? szFileFontType[lpVersion->vsFFI.dwFileSubtype] : L"Undefined") : L"Undefined",
    					                       lpVersion->vsFFI.dwFileDateMS,
    					                       lpVersion->vsFFI.dwFileDateLS,
    					                       HIWORD(lpVersion->vsFFI.dwFileOS), LOWORD(lpVersion->vsFFI.dwFileOS),
    					                       HIWORD(lpVersion->vsFFI.dwFileOS) < sizeof(szFileOSHigh) / sizeof(*szFileOSHigh) ? szFileOSHigh[HIWORD(lpVersion->vsFFI.dwFileOS)] : L"Undefined",
    					                       LOWORD(lpVersion->vsFFI.dwFileOS) < sizeof(szFileOSLow) / sizeof(*szFileOSLow) ? szFileOSLow[LOWORD(lpVersion->vsFFI.dwFileOS)] : L"Undefined");
    
    					for (lp = (BYTE *) lpVersion + lpVersion->wSize,
    					     lpVersion += 1;
    					     lpVersion < (VS_VERSIONINFO *) lp;
    					     lpVersion = (VS_VERSIONINFO *) lpValue)
    					{
    						dwKey = wcslen(lpVersion->szKey);
    						lpValue = lpVersion->szKey + (dwKey + dwKey % 2 + 1);
    
    						if ((lpVersion->wCount == 0)
    					//	 && (lpVersion->wType == VS_TEXT)
    						 && (lpVersion->wSize + (BYTE *) lpVersion > (BYTE *) lpValue))
    							bOutput &= PrintFormat(hOutput,
    							                       L"\t\t\t\t\t\t%ls:\r\n" + (dwKey != 8),
    							                       lpVersion->szKey);
    						else
    						{
    							if (lpVersion->wType == VS_TEXT)
    								bOutput &= PrintFormat(hOutput,
    								                       L"\t\t\t\t\t\t\t%-16ls = %ls\r\n",
    								                       lpVersion->szKey, lpVersion->wCount != 0 ? lpValue : L"");
    							else
    							{
    								bOutput &= PrintFormat(hOutput,
    								                       L"\t\t\t\t\t\t%ls =",
    								                       lpVersion->szKey);
    
    								for (dw = 0; dw < lpVersion->wCount / sizeof(WORD); dw++)
    									bOutput &= PrintFormat(hOutput,
    									                       dw % sizeof(WORD) ? L":%hu" : L" 0x%04hX",
    									                       lpValue[dw]);
    
    								bOutput &= PrintString(hOutput, L"\r\n");
    							}
    
    							lpValue = (LPCWSTR) ((BYTE *) lpVersion + lpVersion->wSize + lpVersion->wSize % sizeof(DWORD));
    						}
    					}
    
    					break;
    
    				case RT_HTML:
    				case RT_MANIFEST:
    
    					lpManifest = lpAddress + lpData->OffsetToData;
    					dwManifest = lpData->Size;
    
    					if (*(DWORD *) lpManifest == 0xFFFE0000)
    					{
    						dwValue = 12001;
    						lpValue = L"32BE";
    					}
    					else if (*(DWORD *) lpManifest == 0x0000FEFF)
    					{
    						dwValue = 12000;
    						lpValue = L"32BE";
    					}
    					else if (*(WCHAR *) lpManifest == L'\xFFFE')
    					{
    						dwValue = 1201;
    						lpValue = L"16BE";
    					}
    					else if (*(WCHAR *) lpManifest == L'\xFEFF')
    					{
    						dwValue = 1200;
    						lpValue = L"16LE";
    					}
    					else if ((*(DWORD *) lpManifest & 0x00FFFFFF) == 0x00BFBBEF)
    					{
    						dwValue = CP_UTF8;
    						lpValue = L"8 (BOM)";
    					}
    					else if ((*(DWORD *) lpManifest == 0x2B762F2B)
    					      || (*(DWORD *) lpManifest == 0x2F762F2B)
    					      || (*(DWORD *) lpManifest == 0x38762F2B)
    					      || (*(DWORD *) lpManifest == 0x39762F2B))
    					{
    						dwValue = CP_UTF7;
    						lpValue = L"7";
    					}
    					else
    					{
    						dwValue = CP_UTF8;
    						lpValue = L"8";
    					}
    
    					bOutput &= PrintFormat(hOutput,
    					                       L"\t\t\t\t\tUTF-%-5ls = ",
    					                       lpValue);
    
    					dw = MultiByteToWideChar(dwValue,
    					                         dwValue == CP_UTF7 ? 0 : MB_ERR_INVALID_CHARS,
    					                         lpManifest,
    					                         dwManifest,
    					                         (LPWSTR) NULL,
    					                         0);
    					if (dw == 0)
    						PrintConsole(hConsole,
    						             L"MultiByteToWideChar() returned error %lu\n",
    						             GetLastError());
    					else
    					{
    						lp = LocalAlloc(NONZEROLPTR, dw * sizeof(L'\0'));
    
    						if (lp == NULL)
    							PrintConsole(hConsole,
    							             L"LocalAlloc() returned error %lu\n",
    							             GetLastError());
    						else
    						{
    							dw = MultiByteToWideChar(dwValue,
    							                         dwValue == CP_UTF7 ? 0 : MB_ERR_INVALID_CHARS,
    							                         lpManifest,
    							                         dwManifest,
    							                         lp,
    							                         dw);
    							if (dw == 0)
    								PrintConsole(hConsole,
    								             L"MultiByteToWideChar() returned error %lu\n",
    								             GetLastError());
    							else
    								bOutput &= PrintDirect(hOutput, lp, dw);
    
    							if (LocalFree(lp) != NULL)
    								PrintConsole(hConsole,
    								             L"LocalFree() returned error %lu\n",
    								             GetLastError());
    						}
    					}
    
    					bOutput &= PrintString(hOutput, L"\r\n");
    
    					break;
    
    				// NOTE: insert code to handle other RT_* resource types here!
    
    				default:
    					break;
    				}
    			else
    				if ((lpType[-1] == L'\3')
    				 && (lpType[0] == L'M')
    				 && (lpType[1] == L'U')
    				 && (lpType[2] == L'I'))
    				{
    					lpMUI = (MUI_RESOURCE *) (lpAddress + lpData->OffsetToData);
    
    					if (lpMUI->dwSignature != MUI_RESOURCE_SIGNATURE)
    						PrintConsole(hConsole,
    						             L"Signature 0x%08lX of resource configuration data not 0x%08lX!\n",
    						             lpMUI->dwSignature, MUI_RESOURCE_SIGNATURE);
    					else
    						bOutput &= PrintFormat(hOutput,
    						                       L"\t\t\t\t\tResource Configuration Data:\r\n"
    						                       L"\t\t\t\t\t\tVersion           = %hu.%hu\r\n"
    						                       L"\t\t\t\t\t\tType              = %lu (%ls)\r\n"
    						                       L"\t\t\t\t\t\tLanguage          = %ls\r\n"
    						                       L"\t\t\t\t\t\tFallback Language = %ls\r\n"
    						                       L"\t\t\t\t\t\tFallback Location = %lu (%ls)\r\n"
    						                       L"\t\t\t\t\t\tSystem Attributes = 0x%08lX\r\n"
    						                       L"\t\t\t\t\t\tMain Checksum     = %08lX %08lX %08lX %08lX\r\n"
    						                       L"\t\t\t\t\t\tService Checksum  = %08lX %08lX %08lX %08lX\r\n",
    						                       HIWORD(lpMUI->dwVersion), LOWORD(lpMUI->dwVersion),
    						                       lpMUI->dwFileType, MUIFileType(lpMUI->dwFileType),
    						                       lpMUI->dwLanguageNameOffset == 0 ? NULL : (BYTE *) lpMUI + lpMUI->dwLanguageNameOffset,
    						                       lpMUI->dwFallbackNameOffset == 0 ? NULL : (BYTE *) lpMUI + lpMUI->dwFallbackNameOffset,
    						                       lpMUI->dwFallbackLocation, MUIFallbackLocation(lpMUI->dwFallbackLocation),
    						                       lpMUI->dwSystemAttributes,
    						                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[0]),
    						                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[1]),
    						                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[2]),
    						                       _byteswap_ulong(((DWORD *) lpMUI->bMainChecksum)[3]),
    						                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[0]),
    						                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[1]),
    						                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[2]),
    						                       _byteswap_ulong(((DWORD *) lpMUI->bServiceChecksum)[3]));
    				}
    		}
    	}
    
    	return bOutput;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	IMAGE_DOS_HEADER	*lpMZ;
    	IMAGE_NT_HEADERS	*lpPE;
    	IMAGE_NT_HEADERS32	*lpPE32;
    	IMAGE_NT_HEADERS64	*lpPE64;
    	IMAGE_SECTION_HEADER	*lpSection;
    	IMAGE_DATA_DIRECTORY	*lpDirectory = NULL;
    
    	IMAGE_RESOURCE_DIRECTORY	*lpResource;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	HANDLE	hOutput;
    	HANDLE	hInput;
    	DWORD	dwInput;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwSection;
    	DWORD	dwResource;
    	DWORD	dwDirectory = 0;
    	LPBYTE	lpImage;
    	HANDLE	hImage;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments != 2)
    				PrintConsole(hConsole,
    				             L"No argument: a single file or path name of an image file must be given!\n");
    			else
    			{
    				hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    				if (hOutput == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"GetStdHandle() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!FlushFileBuffers(hOutput))
    						PrintConsole(hConsole,
    						             L"FlushFileBuffers() returned error %lu: standard output is not redirected to a file!\n",
    						             dwError = GetLastError());
    					else
    					{
    						hInput = CreateFile(lpArguments[1],
    						                    FILE_READ_DATA,
    						                    FILE_SHARE_READ,
    						                    (SECURITY_ATTRIBUTES *) NULL,
    						                    OPEN_EXISTING,
    						                    FILE_FLAG_SEQUENTIAL_SCAN,
    						                    (HANDLE) NULL);
    
    						if (hInput == INVALID_HANDLE_VALUE)
    							PrintConsole(hConsole,
    							             L"CreateFile() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							dwInput = GetFileSize(hInput, (DWORD *) NULL);
    
    							if (dwInput == INVALID_FILE_SIZE)
    								PrintConsole(hConsole,
    								             L"GetFileSize() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								hImage = CreateFileMapping(hInput,
    								                           (LPSECURITY_ATTRIBUTES) NULL,
    								                           PAGE_WRITECOPY,
    								                           0, 0,
    								                           (LPCWSTR) NULL);
    
    								if (hImage == NULL)
    									PrintConsole(hConsole,
    									             L"CreateFileMapping() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    								{
    									lpImage = MapViewOfFile(hImage,
    									                        FILE_MAP_COPY,
    									                        0, 0,
    									                        (SIZE_T) 0);
    
    									if (lpImage == NULL)
    										PrintConsole(hConsole,
    										             L"MapViewOfFile() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    										dwError = ERROR_INVALID_EXE_SIGNATURE;
    
    										lpMZ = (IMAGE_DOS_HEADER *) lpImage;
    
    										if (lpMZ->e_magic != IMAGE_DOS_SIGNATURE)
    											PrintConsole(hConsole,
    											             L"No signature \'%ls\' at offset 0x%08lX in file \'%ls\'!\n",
    											             L"MZ", 0, lpArguments[1]);
    										else
    										{
    											lpPE = (IMAGE_NT_HEADERS *) ((BYTE *) lpMZ + lpMZ->e_lfanew);
    
    											if (((DWORD) lpMZ->e_lfanew > dwInput)
    											 || (lpPE->Signature != IMAGE_NT_SIGNATURE))
    												PrintConsole(hConsole,
    												             L"No signature \'%ls\' at offset 0x%08lX in file \'%ls\'!\n",
    												             L"PE\\0\\0", lpMZ->e_lfanew, lpArguments[1]);
    											else
    											{
    												dwError = ERROR_BAD_EXE_FORMAT;
    
    												if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    												{
    													lpPE64 = (IMAGE_NT_HEADERS64 *) lpPE;
    												//	lpSection = (IMAGE_SECTION_HEADER *) (lpPE64->OptionalHeader.DataDirectory + lpPE64->OptionalHeader.NumberOfRvaAndSizes);
    													lpDirectory = (IMAGE_DATA_DIRECTORY *) lpPE64->OptionalHeader.DataDirectory;
    													dwDirectory = lpPE64->OptionalHeader.NumberOfRvaAndSizes;
    												}
    												else if (lpPE->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    												{
    													lpPE32 = (IMAGE_NT_HEADERS32 *) lpPE;
    												//	lpSection = (IMAGE_SECTION_HEADER *) (lpPE32->OptionalHeader.DataDirectory + lpPE32->OptionalHeader.NumberOfRvaAndSizes);
    													lpDirectory = (IMAGE_DATA_DIRECTORY *) lpPE32->OptionalHeader.DataDirectory;
    													dwDirectory = lpPE32->OptionalHeader.NumberOfRvaAndSizes;
    												}
    											//	else
    											//		dwDirectory = 0;
    
    												if (dwDirectory == 0)
    													PrintConsole(hConsole,
    													             L"Invalid \'PE\' image format 0x%04hX in file \'%ls\'!\n",
    														     lpPE->OptionalHeader.Magic, lpArguments[1]);
    												else
    												{
    													dwError = ERROR_RESOURCE_DATA_NOT_FOUND;
    
    													for (lpSection = (IMAGE_SECTION_HEADER *) ((BYTE *) &(lpPE->OptionalHeader) + lpPE->FileHeader.SizeOfOptionalHeader),
    													     dwSection = 0;
    													     dwSection < lpPE->FileHeader.NumberOfSections;
    													     dwSection++)
    														if (memcmp(lpSection[dwSection].Name, ".rsrc", sizeof(".rsrc")) == 0)
    															break;
    
    													if (dwSection == lpPE->FileHeader.NumberOfSections)
    														PrintConsole(hConsole,
    														             L"No section \'.rsrc\' in file \'%ls\'!\n",
    															     lpArguments[1]);
    													else if (dwDirectory <= IMAGE_DIRECTORY_ENTRY_RESOURCE)
    														PrintConsole(hConsole,
    														             L"No IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_RESOURCE] in file \'%ls\'!\n",
    															     lpArguments[1]);
    													else
    													{
    														if ((lpDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress != lpSection[dwSection].VirtualAddress)
    														 || (lpDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != lpSection[dwSection].Misc.VirtualSize))
    															PrintConsole(hConsole,
    															             L"Address/size in IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_RESOURCE] differ from address/size of section \'.rsrc\' in file \'%ls\'!\n",
    																     lpArguments[1]);
    
    														lpResource = (IMAGE_RESOURCE_DIRECTORY *) (lpImage + lpSection[dwSection].PointerToRawData);
    														dwResource = lpSection[dwSection].VirtualAddress - lpSection[dwSection].PointerToRawData;
    
    														if (!PrintFormat(hOutput,
    														                 L"\xFEFF"	// UTF-16LE BOM
    														                 L"Image File = %ls\r\n"
    														                 L"Image Size = %lu\r\n"
    														                 L"\r\n"
    														                 L"Section \'.rsrc\':\r\n"
    														                 L"\tOffset  = 0x%08lX\r\n"
    														                 L"\tSize    = 0x%08lX\r\n"
    														                 L"\tAddress = 0x%08lX\r\n"
    														                 L"\tData    = 0x%08lX\r\n"
    														                 L"\r\n"
    														                 L"Resource Directory:\r\n"
    														                 L"\tCharacteristics = 0x%08lX\r\n"
    														                 L"\tTime/Date Stamp = 0x%08lX\r\n"
    														                 L"\tVersion         = %hu.%hu\r\n"
    														                 L"\tNamed Entries   = %hu\r\n"
    														                 L"\tUnnamed Entries = %hu\r\n"
    														                 L"\tEntries:\r\n",
    														                 lpArguments[1],
    														                 dwInput,
    														                 lpSection[dwSection].PointerToRawData,
    														                 lpSection[dwSection].SizeOfRawData,
    														                 lpSection[dwSection].VirtualAddress,
    														                 lpSection[dwSection].Misc.VirtualSize,
    														                 lpResource->Characteristics,
    														                 lpResource->TimeDateStamp,
    														                 lpResource->MajorVersion,
    														                 lpResource->MinorVersion,
    														                 lpResource->NumberOfNamedEntries,
    														                 lpResource->NumberOfIdEntries)
    														 || !Resource(hConsole, hOutput,
    														              lpImage - dwResource,
    														              lpResource, lpResource,
    														              MAKEINTRESOURCE(0), MAKEINTRESOURCE(0), 0))
    															PrintConsole(hConsole,
    															             L"WriteFile() returned error %lu\n",
    															             dwError = GetLastError());
    														else
    															dwError = ERROR_SUCCESS;
    													}
    												}
    											}
    										}
    
    										if (!UnmapViewOfFile(lpImage))
    											PrintConsole(hConsole,
    											             L"UnmapViewOfFile() returned error %lu\n",
    											             GetLastError());
    									}
    
    									if (!CloseHandle(hImage))
    										PrintConsole(hConsole,
    										             L"CloseHandle() returned error %lu\n",
    										             GetLastError());
    								}
    							}
    
    							if (!CloseHandle(hInput))
    								PrintConsole(hConsole,
    								             L"CloseHandle() returned error %lu\n",
    								             GetLastError());
    						}
    					}
    
    					if (!CloseHandle(hOutput))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
    Note: this variant prints control characters within Unicode strings of RT_MESSAGETABLE and RT_STRING resources, especially the formatting L'\a', L'\b', L'\f', L'\n', L'\r', L'\t' and L'\v' characters plus the terminating L'\0' character, as , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , and respectively.
  2. Run the following four command lines to compile the source file RESOURCE.C created in step 1., link the compiled object file RESOURCE.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:6.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeRESOURCE.COM RESOURCE.C KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE RESOURCE.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    RESOURCE.C
    RESOURCE.C(2145) : warning C4018: '<' : signed/unsigned mismatch
    RESOURCE.C(2214) : warning C4305: 'type cast' : truncation from 'LPCWSTR' to 'WORD'
    RESOURCE.C(2236) : warning C4305: 'type cast' : truncation from 'LPCWSTR' to 'WORD'
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Security Descriptor Definition Language Decoder

Purpose
Background Information
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source, Build Instructions and Demonstration

Purpose

Decode SDDL strings.

Background Information

The MSDN articles Security Descriptor String Format, ACE Strings and SID Strings plus Security Descriptor Definition Language for Conditional ACEs specify the format of SDDL strings.

Synopsis

SDDL.COM ‹SDDL string› …

Demonstration

Decode two SDDL strings:
.\SDDL.COM O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0) O:DAG:DAD:(A;;RPWPCCDCLCRCWOWDSDSW;;;SY)(A;;RPWPCCDCLCRCWOWDSDSW;;;DA)(OA;;CCDC;BF967ABA-0DE6-11D0-A285-00AA003049E2;;AO)(OA;;CCDC;BF967A9C-0DE6-11D0-A285-00AA003049E2;;AO)(OA;;CCDC;6DA8A4FF-0E52-11D0-A286-00AA003049E2;;AO)(OA;;CCDC;BF967AA8-0DE6-11D0-A285-00AA003049E2;;PO)(A;;RPLCRC;;;AU)S:(AU;SAFA;WDWOSDWPCCDCSW;;;WD)

O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)
        Revision:       1
        Control:        0x8004
                DACL Present
        Owner:          'S-1-5-32-548' = alias 'BUILTIN\Account Operators'
        Group:          'S-1-5-21-820728443-44925810-1835867902-512' = group 'AMNESIAC\Domain Administrators'
        DACL:           28 bytes, 1 ACE(s)
        [0]     ACE:    20 bytes
                Type:           0x00 = Access Allowed
                Flags:          0x00
                Access Mask:    0x100E003F
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                                Directory Add Subdirectory, File Append Data, Pipe Create Instance, Key Create Subkey, Job Query, Process Set Session Id, Section Map Read, Service Query Status, Token Impersonate
                                Directory/File Read Extended Attributes, Key Enumerate Subkeys, Job Terminate, Process Virtual Memory Operation, Section Map Execute, Service Enumerate Dependencies, Thread Get Context, Token Query
                                Directory/File Write Extended Attributes, Key Notify, Job Set Security Attributes, Process Virtual Memory Read, Section Extend Size, Service Start, Thread Set Context, Token Query Source
                                Directory Traverse, File Execute, Key Create Link, Job Impersonate, Process Virtual Memory Write, Section Map Execute Explicit, Service Stop, Thread Set Information, Token Adjust Privileges
                                Read Control
                                Write DACL
                                Write Owner
                                Generic All
                Trustee:        'S-1-0-0' = well-known group 'NULL SID'
        SACL:           NONE

O:DAG:DAD:(A;;RPWPCCDCLCRCWOWDSDSW;;;SY)(A;;RPWPCCDCLCRCWOWDSDSW;;;DA)(OA;;CCDC;BF967ABA-0DE6-11D0-A285-00AA003049E2;;AO)(OA;;CCDC;BF967A9C-0DE6-11D0-A285-00AA003049E2;;AO)(OA;;CCDC;6DA8A4FF-0E52-11D0-A286-00AA003049E2;;AO)(OA;;CCDC;BF967AA8-0DE6-11D0-A285-00AA003049E2;;PO)(A;;RPLCRC;;;AU)S:(AU;SAFA;WDWOSDWPCCDCSW;;;WD)
        Revision:       1
        Control:        0x8014
                DACL Present
                SACL Present
        Owner:          'S-1-5-21-820728443-44925810-1835867902-512' = group 'AMNESIAC\Domain Administrators'
        Group:          'S-1-5-21-820728443-44925810-1835867902-512' = group 'AMNESIAC\Domain Administrators'
        DACL:           248 bytes, 7 ACE(s)
        [0]     ACE:    20 bytes
                Type:           0x00 = Access Allowed
                Flags:          0x00
                Access Mask:    0x000F003F
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                                Directory Add Subdirectory, File Append Data, Pipe Create Instance, Key Create Subkey, Job Query, Process Set Session Id, Section Map Read, Service Query Status, Token Impersonate
                                Directory/File Read Extended Attributes, Key Enumerate Subkeys, Job Terminate, Process Virtual Memory Operation, Section Map Execute, Service Enumerate Dependencies, Thread Get Context, Token Query
                                Directory/File Write Extended Attributes, Key Notify, Job Set Security Attributes, Process Virtual Memory Read, Section Extend Size, Service Start, Thread Set Context, Token Query Source
                                Directory Traverse, File Execute, Key Create Link, Job Impersonate, Process Virtual Memory Write, Section Map Execute Explicit, Service Stop, Thread Set Information, Token Adjust Privileges
                                Standard Delete
                                Read Control
                                Write DACL
                                Write Owner
                Trustee:        'S-1-5-18' = well-known group 'NT AUTHORITY\SYSTEM'
        [1]     ACE:    24 bytes
                Type:           0x00 = Access Allowed
                Flags:          0x00
                Access Mask:    0x000F003F
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                                Directory Add Subdirectory, File Append Data, Pipe Create Instance, Key Create Subkey, Job Query, Process Set Session Id, Section Map Read, Service Query Status, Token Impersonate
                                Directory/File Read Extended Attributes, Key Enumerate Subkeys, Job Terminate, Process Virtual Memory Operation, Section Map Execute, Service Enumerate Dependencies, Thread Get Context, Token Query
                                Directory/File Write Extended Attributes, Key Notify, Job Set Security Attributes, Process Virtual Memory Read, Section Extend Size, Service Start, Thread Set Context, Token Query Source
                                Directory Traverse, File Execute, Key Create Link, Job Impersonate, Process Virtual Memory Write, Section Map Execute Explicit, Service Stop, Thread Set Information, Token Adjust Privileges
                                Standard Delete
                                Read Control
                                Write DACL
                                Write Owner
                Trustee:        'S-1-5-21-820728443-44925810-1835867902-512' = group 'AMNESIAC\Domain Administrators'
        [2]     ACE:    44 bytes
                Type:           0x05 = Object Access Allowed
                Flags:          0x00
                Access Mask:    0x00000003
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                Trustee:        'S-1-5-32-548' = alias 'BUILTIN\Account Operators'
        [3]     ACE:    44 bytes
                Type:           0x05 = Object Access Allowed
                Flags:          0x00
                Access Mask:    0x00000003
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                Trustee:        'S-1-5-32-548' = alias 'BUILTIN\Account Operators'
        [4]     ACE:    44 bytes
                Type:           0x05 = Object Access Allowed
                Flags:          0x00
                Access Mask:    0x00000003
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                Trustee:        'S-1-5-32-548' = alias 'BUILTIN\Account Operators'
        [5]     ACE:    44 bytes
                Type:           0x05 = Object Access Allowed
                Flags:          0x00
                Access Mask:    0x00000003
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                Trustee:        'S-1-5-32-550' = alias 'BUILTIN\Print Operators'
        [6]     ACE:    20 bytes
                Type:           0x00 = Access Allowed
                Flags:          0x00
                Access Mask:    0x00020014
                                Directory Add Subdirectory, File Append Data, Pipe Create Instance, Key Create Subkey, Job Query, Process Set Session Id, Section Map Read, Service Query Status, Token Impersonate
                                Directory/File Write Extended Attributes, Key Notify, Job Set Security Attributes, Process Virtual Memory Read, Section Extend Size, Service Start, Thread Set Context, Token Query Source
                                Read Control
                Trustee:        'S-1-5-11' = well-known group 'NT AUTHORITY\Authenticated Users'
        SACL:           28 bytes, 1 ACE(s)
        [0]     ACE:    20 bytes
                Type:           0x02 = Access Audit
                Flags:          0xC0
                                Access Success
                                Access Failure
                Access Mask:    0x000D002B
                                Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary
                                Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate
                                Directory/File Read Extended Attributes, Key Enumerate Subkeys, Job Terminate, Process Virtual Memory Operation, Section Map Execute, Service Enumerate Dependencies, Thread Get Context, Token Query
                                Directory Traverse, File Execute, Key Create Link, Job Impersonate, Process Virtual Memory Write, Section Map Execute Explicit, Service Stop, Thread Set Information, Token Adjust Privileges
                                Standard Delete
                                Write DACL
                                Write Owner
                Trustee:        'S-1-1-0' = well-known group 'Everyone'

Downloads

The console application is available in two functional identical forms: SDDL.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and SDDL.COM, a small form without these extras.

Implementation and Build Details

Security Descriptor Definition Language Decoder is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source, Build Instructions and Demonstration

Perform the following two simple steps to build the console application Security Descriptor Definition Language Decoder from the source presented hereafter.
  1. Create the text file SDDL.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    #include <sddl.h>
    #include <lmcons.h>
    #include <aclapi.h>
    
    #ifndef LABEL_SECURITY_INFORMATION
    #define LABEL_SECURITY_INFORMATION			0x00000010UL
    #endif
    
    #ifndef ATTRIBUTE_SECURITY_INFORMATION
    #define ATTRIBUTE_SECURITY_INFORMATION			0x00000020UL
    #endif
    
    #ifndef SCOPE_SECURITY_INFORMATION
    #define SCOPE_SECURITY_INFORMATION			0x00000040UL
    #endif
    
    #ifndef PROCESS_TRUST_LABEL_SECURITY_INFORMATION
    #define PROCESS_TRUST_LABEL_SECURITY_INFORMATION	0x00000080UL
    #endif
    
    #ifndef BACKUP_SECURITY_INFORMATION
    #define BACKUP_SECURITY_INFORMATION			0x00010000UL
    #endif
    
    #ifndef CRITICAL_ACE_FLAG
    #define CRITICAL_ACE_FLAG	0x20
    #endif
    
    #ifndef SYSTEM_MANDATORY_LABEL_ACE_TYPE
    #define SYSTEM_MANDATORY_LABEL_ACE_TYPE		0x11
    
    typedef	struct	_SYSTEM_MANDATORY_LABEL_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_MANDATORY_LABEL_ACE;
    #endif
    
    #ifndef SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE
    #define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE	0x12
    
    typedef	struct	_SYSTEM_RESOURCE_ATTRIBUTE_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_RESOURCE_ATTRIBUTE_ACE;
    #endif
    
    #ifndef SYSTEM_SCOPED_POLICY_ID_ACE_TYPE
    #define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE	0x13
    
    typedef	struct	_SYSTEM_SCOPED_POLICY_ID_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_SCOPED_POLICY_ID_ACE;
    #endif
    
    #ifndef SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE
    #define SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE	0x14
    
    typedef	struct	_SYSTEM_PROCESS_TRUST_LABEL_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_PROCESS_TRUST_LABEL_ACE;
    #endif
    
    #ifndef SYSTEM_ACCESS_FILTER_ACE_TYPE
    #define SYSTEM_ACCESS_FILTER_ACE_TYPE		0x15
    
    typedef	struct	_SYSTEM_ACCESS_FILTER_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_ACCESS_FILTER_ACE;
    #endif
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    const	LPCWSTR	szSNU[] = {NULL,
    		           L"user",
    		           L"group",
    		           L"domain",
    		           L"alias",
    		           L"well-known group",
    		           L"deleted account",
    		           L"invalid",
    		           L"unknown",
    		           L"computer",
    		           L"label",
    		           L"logon session"};
    
    __declspec(safebuffers)
    BOOL	WINAPI	PrintSID(HANDLE hConsole, SID *sid, LPCWSTR lpWhich)
    {
    	LPWSTR	lpSID;
    	DWORD	dwError = ERROR_SUCCESS;
    	WCHAR	szAccount[UNLEN + 1];
    	DWORD	dwAccount = sizeof(szAccount) / sizeof(*szAccount);
    	WCHAR	szDomain[GNLEN + 1];
    	DWORD	dwDomain = sizeof(szDomain) / sizeof(*szDomain);
    
    	SID_NAME_USE	snu = 0;
    
    	if (!ConvertSidToStringSid(sid, &lpSID))
    		PrintConsole(hConsole,
    		             L"ConvertSidToStringSid() returned error %lu\n",
    		             dwError = GetLastError());
    	else
    	{
    		if (!LookupAccountSid((LPCWSTR) NULL,
    		                      sid,
    		                      szAccount, &dwAccount,
    		                      szDomain, &dwDomain,
    		                      &snu))
    		{
    			dwError = GetLastError();
    
    			if (dwError != ERROR_NONE_MAPPED)
    				PrintConsole(hConsole,
    				             L"LookupAccountSid() returned error %lu for security identifier \'%ls\'\n",
    				             dwError, lpSID);
    
    			PrintConsole(hConsole,
    			             L"%ls\'%ls\'\n",
    			             lpWhich, lpSID);
    		}
    		else
    			if (*szDomain == L'\0')
    				PrintConsole(hConsole,
    				             L"%ls\'%ls\' = %ls \'%ls\'\n",
    				             lpWhich, lpSID, szSNU[snu], szAccount);
    			else if (*szAccount == L'\0')
    				PrintConsole(hConsole,
    				             L"%ls\'%ls\' = %ls \'%ls\'\n",
    				             lpWhich, lpSID, szSNU[snu], szDomain);
    			else
    				PrintConsole(hConsole,
    				             L"%ls\'%ls\' = %ls \'%ls\\%ls\'\n",
    				             lpWhich, lpSID, szSNU[snu], szDomain, szAccount);
    
    		if (LocalFree(lpSID) != NULL)
    			PrintConsole(hConsole,
    			             L"LocalFree() returned error %lu\n",
    			             GetLastError());
    	}
    
    //	SetLastError(dwError);
    
    	return dwError == ERROR_SUCCESS;
    }
    
    const	LPCWSTR	szSDC[16] = {L"Owner Defaulted",		// SE_OWNER_DEFAULTED
    		             L"Group Defaulted",		// SE_GROUP_DEFAULTED
    		             L"DACL Present",			// SE_DACL_PRESENT
    		             L"DACL Defaulted",			// SE_DACL_DEFAULTED
    		             L"SACL Present",			// SE_SACL_PRESENT
    		             L"SACL Defaulted",			// SE_SACL_DEFAULTED
    		             NULL,
    		             NULL,
    		             L"DACL Auto Inheritance Request",	// SE_DACL_AUTO_INHERIT_REQ
    		             L"SACL Auto Inheritance Request",	// SE_SACL_AUTO_INHERIT_REQ
    		             L"DACL Auto Inherited",		// SE_DACL_AUTO_INHERITED
    		             L"SACL Auto Inherited",		// SE_SACL_AUTO_INHERITED
    		             L"DACL Protected",			// SE_DACL_PROTECTED
    		             L"SACL Protected",			// SE_SACL_PROTECTED
    		             L"Resource Manager Control",	// SE_RM_CONTROL_VALID
    		             L"Self Relative"};			// SE_SELF_RELATIVE
    
    const	LPCWSTR	szType[22] = {L"Access Allowed",
    		              L"Access Denied",
    		              L"Access Audit",
    		              L"Access Alarm",
    		              L"Compound Access Allowed",
    		              L"Object Access Allowed",
    		              L"Object Access Denied",
    		              L"Object Access Audit",
    		              L"Object Access Alarm",
    		              L"Access Allowed Callback",
    		              L"Access Denied Callback",
    		              L"Object Access Allowed Callback",
    		              L"Object Access Denied Callback",
    		              L"Access Audit Callback",
    		              L"Access Alarm Callback",
    		              L"Object Access Audit Callback",
    		              L"Object Access Alarm Callback",
    		              L"Mandatory Label",
    		              L"Resource Attribute",
    		              L"Scoped Policy Identification",
    		              L"Process Trust Label",
    		              L"Access Filter"};
    
    const	LPCWSTR	szFlag[8] = {L"Object Inherit",		// OBJECT_INHERIT_ACE
    		             L"Container Inherit",	// CONTAINER_INHERIT_ACE
    		             L"No Propagate Inherit",	// NO_PROPAGATE_INHERIT_ACE
    		             L"Inherit Only",		// INHERIT_ONLY_ACE
    		             L"Inherited",		// INHERITED_ACE
    		             L"Critical",		// CRITICAL_ACE_FLAG
    		             L"Access Success",		// SUCCESSFUL_ACCESS_ACE_FLAG
    		             L"Access Failure"};	// FAILED_ACCESS_ACE_FLAG
    
    const	LPCWSTR	szMask[32] = {L"Directory List Directory, File/Pipe Read Data, Key Query Value, Event/Mutant/Semaphore/Timer Query State, Job Assign Process, Process Terminate, Section Query, Service Query Configuration, Session Query Access, Thread Terminate, Token Assign Primary",
    		              L"Directory Add File, File/Pipe Write Data, Key Set Value, Event/IO Completion/Mutant/Semaphore/Timer Modify State, Job Set Attributes, Process Create Thread, Section Map Write, Service Change Configuration, Session Modify Access, Thread Suspend/Resume, Token Duplicate",
    		              L"Directory Add Subdirectory, File Append Data, Pipe Create Instance, Key Create Subkey, Job Query, Process Set Session Id, Section Map Read, Service Query Status, Token Impersonate",
    		              L"Directory/File Read Extended Attributes, Key Enumerate Subkeys, Job Terminate, Process Virtual Memory Operation, Section Map Execute, Service Enumerate Dependencies, Thread Get Context, Token Query",
    		              L"Directory/File Write Extended Attributes, Key Notify, Job Set Security Attributes, Process Virtual Memory Read, Section Extend Size, Service Start, Thread Set Context, Token Query Source",
    		              L"Directory Traverse, File Execute, Key Create Link, Job Impersonate, Process Virtual Memory Write, Section Map Execute Explicit, Service Stop, Thread Set Information, Token Adjust Privileges",
    		              L"Directory Delete Child, Process Duplicate Handle, Service Pause, Thread Query Information, Token Adjust Groups",
    		              L"Directory/File/Pipe Read Attributes, Process Create Process, Service Interrogate, Thread Set Thread Token, Token Adjust Default",
    		              L"Directory/File/Pipe Write Attributes, Process Set Quota, Service User Defined, Thread Impersonate, Token Adjust Session Id",
    		              L"Process Set Information, Thread Direct Impersonation",
    		              L"Process Query Information, Thread Set Limited Information",
    		              L"Process Suspend/Resume, Thread Query Limited Information",
    		              L"Process Query Limited Information, Thread Resume",
    		              L"Process Set Limited Information",
    		              NULL,
    		              NULL,
    		              L"Standard Delete",
    		              L"Read Control",
    		              L"Write DACL",
    		              L"Write Owner",
    		              L"Synchronize",
    		              NULL,
    		              NULL,
    		              NULL,
    		              L"Access SACL",
    		              L"Maximum Allowed",
    		              NULL,
    		              NULL,
    		              L"Generic All",
    		              L"Generic Execute/Traverse",
    		              L"Generic Write",
    		              L"Generic Read"};
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	SECURITY_DESCRIPTOR	*lpSD;
    	SECURITY_DESCRIPTOR_CONTROL	sdc;
    	SID	*lpSID;
    	ACL	*lpACL;
    	ACE_HEADER	*lpACE;
    
    	INT	nArgument = 1;
    	INT	nArguments;
    	LPWSTR	*lpArguments;
    	BYTE	rmControl;
    	BOOL	bDefaulted;
    	BOOL	bPresent;
    	WORD	wACE;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwIndex;
    	DWORD	dwValue;
    	DWORD	dwLength;
    	DWORD	dwRevision;
    	DWORD	dwSD;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"No arguments: at least one SDDL string must be given!\n");
    			else
    				do
    					if (!ConvertStringSecurityDescriptorToSecurityDescriptor(lpArguments[nArgument],
    					                                                         SDDL_REVISION_1,
    					                                                         &lpSD,
    					                                                         &dwSD))
    						PrintConsole(hConsole,
    						             L"ConvertStringSecurityDescriptorToSecurityDescriptor() returned error %lu for argument \'%ls\'\n",
    						             dwError = GetLastError(), lpArguments[nArgument]);
    					else
    					{
    						PrintConsole(hConsole,
    						             L"\n"
    						             L"%ls\n",
    						             lpArguments[nArgument]);
    
    						dwLength = GetSecurityDescriptorLength(lpSD);
    
    						if (dwSD != dwLength)
    							PrintConsole(hConsole,
    							             L"ConvertStringSecurityDescriptorToSecurityDescriptor() returned a security descriptor of %lu bytes, but GetSecurityDescriptorLength() returned %lu bytes\n",
    							             dwSD, dwLength);
    
    						if (!GetSecurityDescriptorControl(lpSD, &sdc, &dwRevision))
    							PrintConsole(hConsole,
    							             L"GetSecurityDescriptorControl() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							PrintConsole(hConsole,
    							             L"\tRevision:\t%lu\n"
    							             L"\tControl:\t0x%04hX\n",
    							             dwRevision,
    							             sdc);
    
    							for (dwValue = sdc & ~SE_SELF_RELATIVE;
    							     _BitScanForward(&dwIndex, dwValue);
    							     dwValue &= dwValue - 1)
    								PrintConsole(hConsole, L"\t\t%ls\n", szSDC[dwIndex]);
    						}
    
    						if (sdc & SE_RM_CONTROL_VALID)
    						{
    							dwError = GetSecurityDescriptorRMControl(lpSD, &rmControl);
    
    							if (dwError != ERROR_SUCCESS)
    								PrintConsole(hConsole,
    								             L"GetSecurityDescriptorRMControl() returned error %lu\n",
    								             dwError);
    							else
    								PrintConsole(hConsole,
    								             L"\tRM Control:\t0x%02X\n",
    								             rmControl);
    						}
    
    						if (!GetSecurityDescriptorOwner(lpSD, &lpSID, &bDefaulted))
    							PrintConsole(hConsole,
    							             L"GetSecurityDescriptorOwner() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    							if (lpSID != NULL)
    								PrintSID(hConsole, lpSID, L"\tOwner:\t\t");
    
    						if (!GetSecurityDescriptorGroup(lpSD, &lpSID, &bDefaulted))
    							PrintConsole(hConsole,
    							             L"GetSecurityDescriptorGroup() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    							if (lpSID != NULL)
    								PrintSID(hConsole, lpSID, L"\tGroup:\t\t");
    
    						if (!GetSecurityDescriptorDacl(lpSD, &bPresent, &lpACL, &bDefaulted))
    							PrintConsole(hConsole,
    							             L"GetSecurityDescriptorDacl() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    							if (!bPresent)
    								PrintConsole(hConsole,
    								             L"\tDACL:\t\tNONE\n");
    							else
    								if (lpACL == NULL)
    									PrintConsole(hConsole,
    									             L"\tDACL:\t\tNULL\n");
    								else
    									if (lpACL->AceCount == 0)
    										PrintConsole(hConsole,
    										             L"\tDACL:\t\tEMPTY\n");
    									else
    									{
    										PrintConsole(hConsole,
    										             L"\tDACL:\t\t%hu bytes, %hu ACE(s)\n",
    										             lpACL->AclSize, lpACL->AceCount);
    
    										for (lpACE = (ACE_HEADER *) (lpACL + 1),
    										     wACE = 0; wACE < lpACL->AceCount; wACE++,
    										     lpACE = (ACE_HEADER *) ((BYTE *) lpACE + lpACE->AceSize))
    										{
    											switch (lpACE->AceType)
    											{
    											case ACCESS_ALLOWED_ACE_TYPE:
    
    												lpSID = (SID *) &(((ACCESS_ALLOWED_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case ACCESS_DENIED_ACE_TYPE:
    
    												lpSID = (SID *) &(((ACCESS_DENIED_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
    
    												continue;
    
    											case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
    
    												if (((((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											case ACCESS_DENIED_OBJECT_ACE_TYPE:
    
    												if (((((ACCESS_DENIED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((ACCESS_DENIED_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((ACCESS_DENIED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((ACCESS_DENIED_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((ACCESS_DENIED_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((ACCESS_DENIED_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
    
    												lpSID = (SID *) &(((ACCESS_ALLOWED_CALLBACK_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case ACCESS_DENIED_CALLBACK_ACE_TYPE:
    
    												lpSID = (SID *) &(((ACCESS_DENIED_CALLBACK_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
    
    												if (((((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
    
    												if (((((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											default:
    												PrintConsole(hConsole,
    												             L"Unknown ACE type %u in DACL\n",
    												             lpACE->AceType);
    												continue;
    											}
    
    											PrintConsole(hConsole,
    											             L"\t[%hu]\tACE:\t%hu bytes\n"
    											             L"\t\tType:\t\t0x%02X = %ls\n"
    											             L"\t\tFlags:\t\t0x%02X\n",
    											             wACE, lpACE->AceSize,
    											             lpACE->AceType, szType[lpACE->AceType],
    											             lpACE->AceFlags);
    
    											for (dwValue = lpACE->AceFlags & (VALID_INHERIT_FLAGS | CRITICAL_ACE_FLAG);
    											     _BitScanForward(&dwIndex, dwValue);
    											     dwValue &= dwValue - 1)
    												PrintConsole(hConsole, L"\t\t\t\t%ls\n", szFlag[dwIndex]);
    
    											PrintConsole(hConsole,
    											             L"\t\tAccess Mask:\t0x%08lX\n",
    											             ((ACCESS_ALLOWED_ACE *) lpACE)->Mask);
    
    											for (dwValue = ((ACCESS_ALLOWED_ACE *) lpACE)->Mask;
    											     _BitScanForward(&dwIndex, dwValue);
    											     dwValue &= dwValue - 1)
    												PrintConsole(hConsole, L"\t\t\t\t%ls\n", szMask[dwIndex]);
    
    											PrintSID(hConsole, lpSID, L"\t\tTrustee:\t");
    										}
    									}
    
    						if (!GetSecurityDescriptorSacl(lpSD, &bPresent, &lpACL, &bDefaulted))
    							PrintConsole(hConsole,
    							             L"GetSecurityDescriptorSacl() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    							if (!bPresent)
    								PrintConsole(hConsole,
    								             L"\tSACL:\t\tNONE\n");
    							else
    								if (lpACL == NULL)
    									PrintConsole(hConsole,
    									             L"\tSACL:\t\tNULL\n");
    								else
    									if (lpACL->AceCount == 0)
    										PrintConsole(hConsole,
    										             L"\tSACL:\t\tEMPTY\n");
    									else
    									{
    										PrintConsole(hConsole,
    										             L"\tSACL:\t\t%hu bytes, %hu ACE(s)\n",
    										             lpACL->AclSize, lpACL->AceCount);
    
    										for (lpACE = (ACE_HEADER *) (lpACL + 1),
    										     wACE = 0; wACE < lpACL->AceCount; wACE++,
    										     lpACE = (ACE_HEADER *) ((BYTE *) lpACE + lpACE->AceSize))
    										{
    											switch (lpACE->AceType)
    											{
    											case SYSTEM_AUDIT_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_AUDIT_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_ALARM_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_ALARM_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
    
    												if (((((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											case SYSTEM_ALARM_OBJECT_ACE_TYPE:
    
    												if (((((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_AUDIT_CALLBACK_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_ALARM_CALLBACK_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_ALARM_CALLBACK_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
    
    												if (((((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE:
    
    												if (((((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    												 == ((((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    													if ((((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    														lpSID = (SID *) &(((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    													else
    														lpSID = (SID *) &(((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    												else
    													lpSID = (SID *) &(((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    												break;
    
    											case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_MANDATORY_LABEL_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_RESOURCE_ATTRIBUTE_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_SCOPED_POLICY_ID_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_SCOPED_POLICY_ID_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_PROCESS_TRUST_LABEL_ACE *) lpACE)->SidStart);
    
    												break;
    
    											case SYSTEM_ACCESS_FILTER_ACE_TYPE:
    
    												lpSID = (SID *) &(((SYSTEM_ACCESS_FILTER_ACE *) lpACE)->SidStart);
    
    												break;
    
    											default:
    												PrintConsole(hConsole,
    												             L"Unknown ACE type %u in SACL\n",
    												             lpACE->AceType);
    												continue;
    											}
    
    											PrintConsole(hConsole,
    											             L"\t[%hu]\tACE:\t%hu bytes\n"
    											             L"\t\tType:\t\t0x%02X = %ls\n"
    											             L"\t\tFlags:\t\t0x%02X\n",
    											             wACE, lpACE->AceSize,
    											             lpACE->AceType, szType[lpACE->AceType],
    											             lpACE->AceFlags);
    
    											for (dwValue = lpACE->AceFlags & (SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG);
    											     _BitScanForward(&dwIndex, dwValue);
    											     dwValue &= dwValue - 1)
    												PrintConsole(hConsole, L"\t\t\t\t%ls\n", szFlag[dwIndex]);
    
    											PrintConsole(hConsole,
    											             L"\t\tAccess Mask:\t0x%08lX\n",
    											             ((SYSTEM_MANDATORY_LABEL_ACE *) lpACE)->Mask);
    
    											if (lpACE->AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
    											{
    												if (((SYSTEM_MANDATORY_LABEL_ACE *) lpACE)->Mask & SYSTEM_MANDATORY_LABEL_NO_WRITE_UP)
    													PrintConsole(hConsole,
    													             L"\t\t\t\tNo Write Up\n");
    
    												if (((SYSTEM_MANDATORY_LABEL_ACE *) lpACE)->Mask & SYSTEM_MANDATORY_LABEL_NO_READ_UP)
    													PrintConsole(hConsole,
    													             L"\t\t\t\tNo Read Up\n");
    
    												if (((SYSTEM_MANDATORY_LABEL_ACE *) lpACE)->Mask & SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP)
    													PrintConsole(hConsole,
    													             L"\t\t\t\tNo Execute Up\n");
    											}
    											else
    												for (dwValue = ((SYSTEM_AUDIT_ACE *) lpACE)->Mask;
    												     _BitScanForward(&dwIndex, dwValue);
    												     dwValue &= dwValue - 1)
    													PrintConsole(hConsole, L"\t\t\t\t%ls\n", szMask[dwIndex]);
    
    											PrintSID(hConsole, lpSID, L"\t\tTrustee:\t");
    										}
    									}
    
    						if (LocalFree(lpSD) != NULL)
    							PrintConsole(hConsole,
    							             L"LocalFree() returned error %lu\n",
    							             dwError = GetLastError());
    					}
    				while (++nArgument < nArguments);
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file SDDL.C created in step 1., link the compiled object file SDDL.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeSDDL.COM SDDL.C ADVAPI32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE SDDL.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    SDDL.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Security Descriptor Inspector

Purpose
Background Information
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Find directories and files on NTFS filesystems that have a security descriptor which contains unknown security principals, i.e. user or group accounts that don’t exist on the local machine.

Background Information

The TechNet articles What are Security Identifiers?, How Security Identifiers Work and Security Identifiers Technical Overview provide an overview.

Synopsis

SECURITY.COM { ‹directory name› | ‹file name› } …
Note: when run under a user account which has the privileges SeBackupPrivilege and SeSecurityPrivilege assigned, the Security Descriptor Inspector enables them to access all directories and files.

Downloads

The console application is available in two functional identical forms: SECURITY.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and SECURITY.COM, a small form without these extras.

Implementation and Build Details

Security Descriptor Inspector is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two (plus two optional) simple steps to build the console application Security Descriptor Inspector from the source presented hereafter.
  1. Create the text file SECURITY.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define _CRT_SECURE_NO_WARNINGS
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    #include <sddl.h>
    #include <lmcons.h>
    #include <aclapi.h>
    
    #define memcpy	__movsb
    #define wmemcpy	__movsw
    
    #define SE_SECURITY_PRIVILEGE	8UL	// "SeSecurityPrivilege"
    #define SE_BACKUP_PRIVILEGE	17UL	// "SeBackupPrivilege"
    
    const	TOKEN_PRIVILEGES	tpBackup = {1, {SE_BACKUP_PRIVILEGE, 0, SE_PRIVILEGE_ENABLED}};
    const	TOKEN_PRIVILEGES	tpSecurity = {1, {SE_SECURITY_PRIVILEGE, 0, SE_PRIVILEGE_ENABLED}};
    
    typedef	unsigned long long	QWORD, *LPQWORD;
    
    #ifndef LABEL_SECURITY_INFORMATION
    #define LABEL_SECURITY_INFORMATION			0x00000010UL
    #endif
    
    #ifndef ATTRIBUTE_SECURITY_INFORMATION
    #define ATTRIBUTE_SECURITY_INFORMATION			0x00000020UL
    #endif
    
    #ifndef SCOPE_SECURITY_INFORMATION
    #define SCOPE_SECURITY_INFORMATION			0x00000040UL
    #endif
    
    #ifndef PROCESS_TRUST_LABEL_SECURITY_INFORMATION
    #define PROCESS_TRUST_LABEL_SECURITY_INFORMATION	0x00000080UL
    #endif
    
    #ifndef BACKUP_SECURITY_INFORMATION
    #define BACKUP_SECURITY_INFORMATION			0x00010000UL
    #endif
    
    #ifndef SYSTEM_MANDATORY_LABEL_ACE_TYPE
    #define SYSTEM_MANDATORY_LABEL_ACE_TYPE		0x11
    
    typedef	struct	_SYSTEM_MANDATORY_LABEL_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_MANDATORY_LABEL_ACE;
    #endif
    
    #ifndef SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE
    #define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE	0x12
    
    typedef	struct	_SYSTEM_RESOURCE_ATTRIBUTE_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_RESOURCE_ATTRIBUTE_ACE;
    #endif
    
    #ifndef SYSTEM_SCOPED_POLICY_ID_ACE_TYPE
    #define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE	0x13
    
    typedef	struct	_SYSTEM_SCOPED_POLICY_ID_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_SCOPED_POLICY_ID_ACE;
    #endif
    
    #ifndef SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE
    #define SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE	0x14
    
    typedef	struct	_SYSTEM_PROCESS_TRUST_LABEL_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_PROCESS_TRUST_LABEL_ACE;
    #endif
    
    #ifndef SYSTEM_ACCESS_FILTER_ACE_TYPE
    #define SYSTEM_ACCESS_FILTER_ACE_TYPE		0x15
    
    typedef	struct	_SYSTEM_ACCESS_FILTER_ACE
    {
    	ACE_HEADER	Header;
    	ACCESS_MASK	Mask;
    	DWORD		SidStart;
    } SYSTEM_ACCESS_FILTER_ACE;
    #endif
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    DWORD	WINAPI	Security(HANDLE hConsole, QWORD qwPrivileges, WCHAR szPathName[])
    {
    	SECURITY_DESCRIPTOR	*lpSD;
    	SID	*lpOwner, *lpGroup, *lpTrustee;
    	ACL	*lpDACL, *lpSACL;
    	ACE_HEADER	*lpACE;
    	SID_NAME_USE	snu;
    	WORD	wACE;
    	LPWSTR	lpStringSID;
    	WCHAR	szAccount[UNLEN + 1];
    	WCHAR	szDomain[GNLEN + 1];
    	DWORD	dwAccount;
    	DWORD	dwDomain;
    	DWORD	dwError = GetNamedSecurityInfo(szPathName,
    		                               SE_FILE_OBJECT,
    		                               qwPrivileges & (1 << SE_SECURITY_PRIVILEGE) ? OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
    		                               &lpOwner,
    		                               &lpGroup,
    		                               &lpDACL,
    		                               &lpSACL,
    		                               &lpSD);
    
    	if (dwError != ERROR_SUCCESS)
    		PrintConsole(hConsole,
    		             L"GetNamedSecurityInfo() returned error %lu for \'%ls\'\n",
    		             dwError, szPathName);
    	else
    		if (!IsValidSecurityDescriptor(lpSD))
    			PrintConsole(hConsole,
    			             L"IsValidSecurityDescriptor() failed for security descriptor of \'%ls\'\n",
    			             szPathName);
    		else
    		{
    			if (lpOwner == NULL)
    				PrintConsole(hConsole,
    				             L"No owner in security descriptor of \'%ls\'\n",
    				             szPathName);
    			else
    				if (!IsValidSid(lpOwner))
    					PrintConsole(hConsole,
    					             L"IsValidSid() failed for owner of \'%ls\'\n",
    					             szPathName);
    				else
    				{
    					dwAccount = sizeof(szAccount) / sizeof(*szAccount);
    					dwDomain = sizeof(szDomain) / sizeof(*szDomain);
    
    					if (!LookupAccountSid((LPCWSTR) NULL,
    					                      lpOwner,
    					                      szAccount, &dwAccount,
    					                      szDomain, &dwDomain,
    					                      &snu))
    					{
    						dwError = GetLastError();
    
    						if (dwError != ERROR_NONE_MAPPED)
    							PrintConsole(hConsole,
    							             L"LookupAccountSid() returned error %lu for owner of \'%ls\'\n",
    							             dwError, szPathName);
    						else
    							if (!ConvertSidToStringSid(lpOwner, &lpStringSID))
    								PrintConsole(hConsole,
    								             L"ConvertSidToStringSid() returned error %lu for unknown owner of \'%ls\'\n",
    								             dwError = GetLastError(), szPathName);
    							else
    							{
    								PrintConsole(hConsole,
    								             L"Unknown owner \'%ls\' in security descriptor of \'%ls\'\n",
    								             lpStringSID, szPathName);
    
    								if (LocalFree(lpStringSID) != NULL)
    									PrintConsole(hConsole,
    									             L"LocalFree() returned error %lu\n",
    									             GetLastError());
    							}
    					}
    				}
    
    			if (lpGroup == NULL)
    				PrintConsole(hConsole,
    				             L"No group in security descriptor of \'%ls\'\n",
    				             szPathName);
    			else
    				if (!IsValidSid(lpGroup))
    					PrintConsole(hConsole,
    					             L"IsValidSid() failed for group of \'%ls\'\n",
    					             szPathName);
    				else
    				{
    					dwAccount = sizeof(szAccount) / sizeof(*szAccount);
    					dwDomain = sizeof(szDomain) / sizeof(*szDomain);
    
    					if (!LookupAccountSid((LPCWSTR) NULL,
    					                      lpGroup,
    					                      szAccount, &dwAccount,
    					                      szDomain, &dwDomain,
    					                      &snu))
    					{
    						dwError = GetLastError();
    
    						if (dwError != ERROR_NONE_MAPPED)
    							PrintConsole(hConsole,
    							             L"LookupAccountSid() returned error %lu for group of \'%ls\'\n",
    							             dwError, szPathName);
    						else
    							if (!ConvertSidToStringSid(lpGroup, &lpStringSID))
    								PrintConsole(hConsole,
    								             L"ConvertSidToStringSid() returned error %lu for unknown group of \'%ls\'\n",
    								             dwError = GetLastError(), szPathName);
    							else
    							{
    								PrintConsole(hConsole,
    								             L"Unknown group \'%ls\' in security descriptor of \'%ls\'\n",
    								             lpStringSID, szPathName);
    
    								if (LocalFree(lpStringSID) != NULL)
    									PrintConsole(hConsole,
    									             L"LocalFree() returned error %lu\n",
    									             GetLastError());
    							}
    					}
    				}
    
    			if (lpDACL == NULL)
    				PrintConsole(hConsole,
    				             L"No DACL in security descriptor of \'%ls\'\n",
    				             szPathName);
    			else
    				if (!IsValidAcl(lpDACL))
    					PrintConsole(hConsole,
    					             L"IsValidAcl() failed for DACL of \'%ls\'\n",
    					             szPathName);
    				else
    					if (lpDACL->AceCount == 0)
    						PrintConsole(hConsole,
    						             L"Empty DACL in security descriptor of \'%ls\'\n",
    						             szPathName);
    					else
    						for (lpACE = (ACE_HEADER *) (lpDACL + 1),
    						     wACE = 0; wACE < lpDACL->AceCount; wACE++,
    						     lpACE = (ACE_HEADER *) ((BYTE *) lpACE + lpACE->AceSize))
    						{
    							switch (lpACE->AceType)
    							{
    							case ACCESS_ALLOWED_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((ACCESS_ALLOWED_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case ACCESS_DENIED_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((ACCESS_DENIED_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
    
    								continue;
    
    							case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
    
    								if (((((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((ACCESS_ALLOWED_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							case ACCESS_DENIED_OBJECT_ACE_TYPE:
    
    								if (((((ACCESS_DENIED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((ACCESS_DENIED_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((ACCESS_DENIED_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((ACCESS_DENIED_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((ACCESS_DENIED_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((ACCESS_DENIED_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((ACCESS_ALLOWED_CALLBACK_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case ACCESS_DENIED_CALLBACK_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((ACCESS_DENIED_CALLBACK_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
    
    								if (((((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
    
    								if (((((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((ACCESS_DENIED_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							default:
    								PrintConsole(hConsole,
    								             L"Unknown ACE type %u in DACL of \'%ls\'\n",
    								             lpACE->AceType, szPathName);
    								continue;
    							}
    
    							if (!IsValidSid(lpTrustee))
    								PrintConsole(hConsole,
    								             L"IsValidSid() failed for trustee in DACL of \'%ls\'\n",
    								             szPathName);
    							else
    							{
    								dwAccount = sizeof(szAccount) / sizeof(*szAccount);
    								dwDomain = sizeof(szDomain) / sizeof(*szDomain);
    
    								if (!LookupAccountSid((LPCWSTR) NULL,
    								                      lpTrustee,
    								                      szAccount, &dwAccount,
    								                      szDomain, &dwDomain,
    								                      &snu))
    								{
    									dwError = GetLastError();
    
    									if (dwError != ERROR_NONE_MAPPED)
    										PrintConsole(hConsole,
    										             L"LookupAccountSid() returned error %lu for trustee in DACL of \'%ls\'\n",
    										             dwError, szPathName);
    									else
    										if (!ConvertSidToStringSid(lpTrustee, &lpStringSID))
    											PrintConsole(hConsole,
    											             L"ConvertSidToStringSid() returned error %lu for unknown trustee in DACL of \'%ls\'\n",
    											             dwError = GetLastError(), szPathName);
    										else
    										{
    											PrintConsole(hConsole,
    											             L"Unknown trustee \'%ls\' in DACL of \'%ls\'\n",
    											             lpStringSID, szPathName);
    
    											if (LocalFree(lpStringSID) != NULL)
    												PrintConsole(hConsole,
    												             L"LocalFree() returned error %lu\n",
    												             GetLastError());
    										}
    								}
    							}
    						}
    
    			if (lpSACL == NULL)
    				PrintConsole(hConsole,
    				             L"No SACL in security descriptor of \'%ls\'\n",
    				             szPathName);
    			else
    				if (!IsValidAcl(lpSACL))
    					PrintConsole(hConsole,
    					             L"IsValidAcl() failed for SACL of \'%ls\'\n",
    					             szPathName);
    				else
    					if (lpSACL->AceCount == 0)
    						PrintConsole(hConsole,
    						             L"Empty SACL in security descriptor of \'%ls\'\n",
    						             szPathName);
    					else
    						for (lpACE = (ACE_HEADER *) (lpSACL + 1),
    						     wACE = 0; wACE < lpSACL->AceCount; wACE++,
    						     lpACE = (ACE_HEADER *) ((BYTE *) lpACE + lpACE->AceSize))
    						{
    							switch (lpACE->AceType)
    							{
    							case SYSTEM_AUDIT_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_AUDIT_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_ALARM_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_ALARM_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
    
    								if (((((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((SYSTEM_AUDIT_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							case SYSTEM_ALARM_OBJECT_ACE_TYPE:
    
    								if (((((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((SYSTEM_ALARM_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_AUDIT_CALLBACK_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_ALARM_CALLBACK_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_ALARM_CALLBACK_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
    
    								if (((((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((SYSTEM_AUDIT_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE:
    
    								if (((((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    								 == ((((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) == ACE_INHERITED_OBJECT_TYPE_PRESENT))
    									if ((((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->Flags & ACE_OBJECT_TYPE_PRESENT) == ACE_OBJECT_TYPE_PRESENT)
    										lpTrustee = (SID *) &(((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->SidStart);
    									else
    										lpTrustee = (SID *) &(((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->ObjectType);
    								else
    									lpTrustee = (SID *) &(((SYSTEM_ALARM_CALLBACK_OBJECT_ACE *) lpACE)->InheritedObjectType);
    								break;
    
    							case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_MANDATORY_LABEL_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_RESOURCE_ATTRIBUTE_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_SCOPED_POLICY_ID_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_SCOPED_POLICY_ID_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_PROCESS_TRUST_LABEL_ACE *) lpACE)->SidStart);
    
    								break;
    
    							case SYSTEM_ACCESS_FILTER_ACE_TYPE:
    
    								lpTrustee = (SID *) &(((SYSTEM_ACCESS_FILTER_ACE *) lpACE)->SidStart);
    
    								break;
    
    							default:
    								PrintConsole(hConsole,
    								             L"Unknown ACE type %u in SACL of \'%ls\'\n",
    								             lpACE->AceType, szPathName);
    								continue;
    							}
    
    							if (!IsValidSid(lpTrustee))
    								PrintConsole(hConsole,
    								             L"IsValidSid() failed for trustee in SACL of \'%ls\'\n",
    								             szPathName);
    							else
    							{
    								dwAccount = sizeof(szAccount) / sizeof(*szAccount);
    								dwDomain = sizeof(szDomain) / sizeof(*szDomain);
    
    								if (!LookupAccountSid((LPCWSTR) NULL,
    								                      lpTrustee,
    								                      szAccount, &dwAccount,
    								                      szDomain, &dwDomain,
    								                      &snu))
    								{
    									dwError = GetLastError();
    
    									if (dwError != ERROR_NONE_MAPPED)
    										PrintConsole(hConsole,
    										             L"LookupAccountSid() returned error %lu for trustee in SACL of \'%ls\'\n",
    										             dwError, szPathName);
    									else
    										if (!ConvertSidToStringSid(lpTrustee, &lpStringSID))
    											PrintConsole(hConsole,
    											             L"ConvertSidToStringSid() returned error %lu for unknown trustee in SACL of \'%ls\'\n",
    											             dwError = GetLastError(), szPathName);
    										else
    										{
    											PrintConsole(hConsole,
    											             L"Unknown trustee \'%ls\' in SACL of \'%ls\'\n",
    											             lpStringSID, szPathName);
    
    											if (LocalFree(lpStringSID) != NULL)
    												PrintConsole(hConsole,
    												             L"LocalFree() returned error %lu\n",
    												             GetLastError());
    										}
    								}
    							}
    						}
    
    		if (LocalFree(lpSD) != NULL)
    			PrintConsole(hConsole,
    			             L"LocalFree() returned error %lu\n",
    			             GetLastError());
    	}
    
    	return dwError;
    }
    
    __declspec(safebuffers)
    DWORD	WINAPI	Traverse(HANDLE hConsole, QWORD qwPrivileges, WCHAR szPathName[32768])
    {
    	WIN32_FIND_DATA	wfd;
    
    	HANDLE	hPathName;
    	DWORD	dwPathName;
    	DWORD	dwError = Security(hConsole, qwPrivileges, szPathName);
    
    	dwPathName = wcslen(szPathName);
    #if 0
    	wcscat(szPathName, L"\\*");
    #elif 0
    	wmemcpy(szPathName + dwPathName, L"\\*", sizeof("\\*"));
    #elif 0
    	memcpy(szPathName + dwPathName, L"\\*", sizeof(L"\\*"));
    #else
    	szPathName[dwPathName + 0] = L'\\';
    	szPathName[dwPathName + 1] = L'*';
    	szPathName[dwPathName + 2] = L'\0';
    #endif
    	hPathName = FindFirstFile(szPathName, &wfd);
    
    	if (hPathName != INVALID_HANDLE_VALUE)
    	{
    		do
    		{
    			wcscpy(szPathName + dwPathName + 1, wfd.cFileName);
    
    			if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
    			{
    				if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
    					continue;
    #if 0
    				if ((wcscmp(wfd.cFileName, L".") == 0)
    				 || (wcscmp(wfd.cFileName, L"..") == 0))
    					continue;
    #elif 0
    				if ((wmemcmp(wfd.cFileName, L".", sizeof(".")) == 0)
    				 || (wmemcmp(wfd.cFileName, L"..", sizeof("..")) == 0))
    					continue;
    #elif 0
    				if ((memcmp(wfd.cFileName, L".", sizeof(L".")) == 0)
    				 || (memcmp(wfd.cFileName, L"..", sizeof(L"..")) == 0))
    					continue;
    #else
    				if ((wfd.cFileName[0] == L'.')
    				 && (wfd.cFileName[1] == L'\0'))
    					continue;
    
    				if ((wfd.cFileName[0] == L'.')
    				 && (wfd.cFileName[1] == L'.')
    				 && (wfd.cFileName[2] == L'\0'))
    					continue;
    #endif
    				dwError = Traverse(hConsole, qwPrivileges, szPathName);
    			}
    			else
    				dwError = Security(hConsole, qwPrivileges, szPathName);
    		}
    		while (FindNextFile(hPathName, &wfd));
    
    		dwError = GetLastError();
    
    		if (dwError == ERROR_NO_MORE_FILES)
    			dwError = ERROR_SUCCESS;
    		else
    			PrintConsole(hConsole,
    			             L"FindNextFile() returned error %lu for path \'%ls\'\n",
    			             dwError, szPathName);
    
    		if (!FindClose(hPathName))
    			PrintConsole(hConsole,
    			             L"FindClose() returned error %lu for path \'%ls\'\n",
    			             GetLastError(), szPathName);
    	}
    	else
    	{
    		dwError = GetLastError();
    
    		if (dwError == ERROR_FILE_NOT_FOUND)
    			dwError = ERROR_SUCCESS;
    		else
    			PrintConsole(hConsole,
    			             L"FindFirstFile() returned error %lu for path \'%ls\'\n",
    			             dwError, szPathName);
    	}
    
    //	szPathName[dwPathName] = L'\0';
    
    	return dwError;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	WIN32_FIND_DATA	wfd;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 1;
    	QWORD	qwPrivileges = 0;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwArgument;
    	WCHAR	szArgument[32768];
    	LPWSTR	lpArgument;
    	HANDLE	hArgument;
    	HANDLE	hToken;
    	HANDLE	hProcess = GetCurrentProcess();
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"No arguments: at least one directory or file name must be given!\n");
    			else
    			{
    				if (!OpenProcessToken(hProcess,
    				                      TOKEN_ADJUST_PRIVILEGES,
    				                      &hToken))
    					PrintConsole(hConsole,
    					             L"OpenProcessToken() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!AdjustTokenPrivileges(hToken,
    					                           FALSE,
    					                           &tpBackup,
    					                           sizeof(TOKEN_PRIVILEGES),
    					                           (TOKEN_PRIVILEGES *) NULL,
    					                           (LPDWORD) NULL))
    						PrintConsole(hConsole,
    						             L"AdjustTokenPrivileges() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						if (GetLastError() == ERROR_SUCCESS)
    							qwPrivileges |= 1 << SE_BACKUP_PRIVILEGE;
    
    					if (!AdjustTokenPrivileges(hToken,
    					                           FALSE,
    					                           &tpSecurity,
    					                           sizeof(TOKEN_PRIVILEGES),
    					                           (TOKEN_PRIVILEGES *) NULL,
    					                           (LPDWORD) NULL))
    						PrintConsole(hConsole,
    						             L"AdjustTokenPrivileges() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						if (GetLastError() == ERROR_SUCCESS)
    							qwPrivileges |= 1 << SE_SECURITY_PRIVILEGE;
    
    					if (!CloseHandle(hToken))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    
    				do
    				{
    					dwArgument = GetFileAttributes(lpArguments[nArgument]);
    
    					if (dwArgument == INVALID_FILE_ATTRIBUTES)
    					{
    						hArgument = FindFirstFile(lpArguments[nArgument], &wfd);
    
    						if (hArgument == INVALID_HANDLE_VALUE)
    							PrintConsole(hConsole,
    							             L"FindFirstFile() returned error %lu for argument \'%ls\'\n",
    							             dwError = GetLastError(), lpArguments[nArgument]);
    						else
    						{
    							dwArgument = 0;
    							lpArgument = NULL;
    
    							do
    							{
    								szArgument[dwArgument] = lpArguments[nArgument][dwArgument];
    
    								if (szArgument[dwArgument] == L'\\')
    									lpArgument = szArgument + dwArgument;
    							}
    							while (szArgument[dwArgument++] != L'\0');
    
    							if (dwArgument > MAX_PATH)
    								PrintConsole(hConsole,
    								             L"Argument \'%ls\' exceeds MAX_PATH!\n",
    								             szArgument);
    
    							if (lpArgument != NULL)
    								lpArgument++;
    							else
    								lpArgument = szArgument + 2 * (szArgument[1] == L':');
    
    							dwArgument = 0;
    
    							do
    							{
    								wcscpy(lpArgument, wfd.cFileName);
    
    								if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
    								{
    									if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
    										continue;
    #if 0
    									if ((wcscmp(wfd.cFileName, L".") == 0)
    									 || (wcscmp(wfd.cFileName, L"..") == 0))
    										continue;
    #elif 0
    									if ((wmemcmp(wfd.cFileName, L".", sizeof(".")) == 0)
    									 || (wmemcmp(wfd.cFileName, L"..", sizeof("..")) == 0))
    										continue;
    #elif 0
    									if ((memcmp(wfd.cFileName, L".", sizeof(L".")) == 0)
    									 || (memcmp(wfd.cFileName, L"..", sizeof(L"..")) == 0))
    										continue;
    #else
    									if ((wfd.cFileName[0] == L'.')
    									 && (wfd.cFileName[1] == L'\0'))
    										continue;
    
    									if ((wfd.cFileName[0] == L'.')
    									 && (wfd.cFileName[1] == L'.')
    									 && (wfd.cFileName[2] == L'\0'))
    										continue;
    #endif
    									dwError = Traverse(hConsole, qwPrivileges, szArgument);
    								}
    								else
    									dwError = Security(hConsole, qwPrivileges, szArgument);
    
    								dwArgument++;
    							}
    							while (FindNextFile(hArgument, &wfd));
    
    							dwError = GetLastError();
    
    							if (dwError == ERROR_NO_MORE_FILES)
    								dwError = ERROR_SUCCESS;
    							else
    								PrintConsole(hConsole,
    								             L"FindNextFile() returned error %lu for argument \'%ls\'\n",
    								             dwError, lpArguments[nArgument]);
    
    							if (dwArgument == 0)
    								PrintConsole(hConsole,
    								             L"No wildcard match for argument \'%ls\'!\n",
    								             lpArguments[nArgument]);
    
    							if (!FindClose(hArgument))
    								PrintConsole(hConsole,
    								             L"FindClose() returned error %lu for argument \'%ls\'\n",
    								             GetLastError(), lpArguments[nArgument]);
    						}
    					}
    					else if ((dwArgument & FILE_ATTRIBUTE_DIRECTORY) == 0)
    						dwError = Security(hConsole, qwPrivileges, szArgument);
    					else
    						dwError = Traverse(hConsole, qwPrivileges, szArgument);
    				}
    				while (++nArgument < nArguments);
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
    Note: the console application SECURITY.COM supports long pathnames with the \\?\ prefix.
  2. Run the following four command lines to compile the source file SECURITY.C created in step 1., link the compiled object file SECURITY.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gs69632 /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /STACK:1048576,65536 /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeSECURITY.COM SECURITY.C ADVAPI32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE SECURITY.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    SECURITY.C
    SECURITY.C(726) : warning C4090: 'function' : different 'const' qualifiers
    SECURITY.C(739) : warning C4090: 'function' : different 'const' qualifiers
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …
  3. (Optional) Create the text file SECURITY.XML with the following content next to the console application SECURITY.COM built in step 2.:

    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
    <!-- Copyright (C) 2004-2024, Stefan Kanthak -->
    <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
        <assemblyIdentity name="eSKamation.Tidbits.Security Descriptor Inspector" processorArchitecture="*" type="win32" version="0.8.1.5" />
        <application xmlns="urn:schemas-microsoft-com:asm.v3">
            <windowsSettings>
                <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
            </windowsSettings>
        </application>
        <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
            <application>
                <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
                <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
                <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
                <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
                <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
            </application>
        </compatibility>
        <description>Security Descriptor Inspector</description>
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
            <security>
                <requestedPrivileges>
                    <requestedExecutionLevel level="highestAvailable" uiAccess="false" />
                </requestedPrivileges>
            </security>
        </trustInfo>
    </assembly>
    Note: the double use of an XML element named application is (at least) clumsy and error-prone!
  4. (Optional) Embed the application manifest SECURITY.XML created in step 3. in the console application SECURITY.COM built in step 2.:

    MT.EXE /CANONICALIZE /MANIFEST SECURITY.XML /OUTPUTRESOURCE:SECURITY.COM
    Note: the Manifest Tool MT.exe is shipped with the Windows Software Development Kit.
    Microsoft (R) Manifest Tool version 6.1.7716.0
    Copyright (c) Microsoft Corporation 2009.
    All rights reserved.
    Note: on Windows 10 1607 alias Anniversary Update and newer versions of Windows NT, the console application SECURITY.COM supports long pathnames when the following Registry. entry is present:
    REGEDIT4
    
    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
    "LongPathsEnabled"=dword:00000001
    Note: without this Registry entry and on older versions of Windows NT, the console application SECURITY.COM supports long pathnames with the \\?\ prefix.

Really Known SIDs Enumerator

Purpose
Background Information
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source, Build Instructions and Output

Purpose

Enumerate (most of) the Security Identifiers really known on a machine, translate them to their (fully qualified) account name plus type and print these 3 pieces.

Background Information

The TechNet articles What are Security Identifiers?, How Security Identifiers Work and Security Identifiers Technical Overview provide an overview.

Synopsis

SIDEREAL.COM

Demonstration

VER
.\SIDEREAL.COM
Microsoft Windows [Version 10.0.19044.2486]

S-1-0-0: well-known group 'NULL SID'
S-1-1-0: well-known group 'Everyone'
S-1-2-0: well-known group 'LOCAL'
S-1-2-1: well-known group 'CONSOLE LOGON'
S-1-3-0: well-known group 'CREATOR OWNER'
S-1-3-1: well-known group 'CREATOR GROUP'
S-1-3-2: well-known group 'CREATOR OWNER SERVER'
S-1-3-3: well-known group 'CREATOR GROUP SERVER'
S-1-3-4: well-known group 'OWNER RIGHTS'
S-1-5: domain 'NT Pseudo Domain\NT Pseudo Domain'
S-1-5-1: well-known group 'NT AUTHORITY\DIALUP'
S-1-5-2: well-known group 'NT AUTHORITY\NETWORK'
S-1-5-3: well-known group 'NT AUTHORITY\BATCH'
S-1-5-4: well-known group 'NT AUTHORITY\INTERACTIVE'
S-1-5-6: well-known group 'NT AUTHORITY\SERVICE'
S-1-5-7: well-known group 'NT AUTHORITY\ANONYMOUS LOGON'
S-1-5-8: well-known group 'NT AUTHORITY\PROXY'
S-1-5-9: well-known group 'NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS'
S-1-5-10: well-known group 'NT AUTHORITY\SELF'
S-1-5-11: well-known group 'NT AUTHORITY\Authenticated Users'
S-1-5-12: well-known group 'NT AUTHORITY\RESTRICTED'
S-1-5-13: well-known group 'NT AUTHORITY\TERMINAL SERVER USER'
S-1-5-14: well-known group 'NT AUTHORITY\REMOTE INTERACTIVE LOGON'
S-1-5-15: well-known group 'NT AUTHORITY\This Organization'
S-1-5-17: well-known group 'NT AUTHORITY\IUSR'
S-1-5-18: well-known group 'NT AUTHORITY\SYSTEM'
S-1-5-19: well-known group 'NT AUTHORITY\LOCAL SERVICE'
S-1-5-20: well-known group 'NT AUTHORITY\NETWORK SERVICE'
S-1-5-22: well-known group 'NT AUTHORITY\ENTERPRISE READ-ONLY DOMAIN CONTROLLERS BETA'
S-1-5-32: domain 'BUILTIN\BUILTIN'
S-1-5-32-544: alias 'BUILTIN\Administrators'
S-1-5-32-545: alias 'BUILTIN\Users'
S-1-5-32-546: alias 'BUILTIN\Guests'
S-1-5-32-547: alias 'BUILTIN\Power Users'
S-1-5-32-551: alias 'BUILTIN\Backup Operators'
S-1-5-32-552: alias 'BUILTIN\Replicator'
S-1-5-32-555: alias 'BUILTIN\Remote Desktop Users'
S-1-5-32-556: alias 'BUILTIN\Network Configuration Operators'
S-1-5-32-558: alias 'BUILTIN\Performance Monitor Users'
S-1-5-32-559: alias 'BUILTIN\Performance Log Users'
S-1-5-32-562: alias 'BUILTIN\Distributed COM Users'
S-1-5-32-568: alias 'BUILTIN\IIS_IUSRS'
S-1-5-32-569: alias 'BUILTIN\Cryptographic Operators'
S-1-5-32-573: alias 'BUILTIN\Event Log Readers'
S-1-5-32-578: alias 'BUILTIN\Hyper-V Administrators'
S-1-5-32-579: alias 'BUILTIN\Access Control Assistance Operators'
S-1-5-32-580: alias 'BUILTIN\Remote Management Users'
S-1-5-32-581: alias 'BUILTIN\System Managed Accounts Group'
S-1-5-32-583: alias 'BUILTIN\Device Owners'
S-1-5-33: well-known group 'NT AUTHORITY\WRITE RESTRICTED'
S-1-5-64-10: well-known group 'NT AUTHORITY\NTLM Authentication'
S-1-5-64-14: well-known group 'NT AUTHORITY\SChannel Authentication'
S-1-5-64-21: well-known group 'NT AUTHORITY\Digest Authentication'
S-1-5-64-32: well-known group 'NT AUTHORITY\Microsoft Account Authentication'
S-1-5-65-1: well-known group 'NT AUTHORITY\This Organization Certificate'
S-1-5-80: domain 'NT SERVICE\NT SERVICE'
S-1-5-80-0: well-known group 'NT SERVICE\ALL SERVICES'
S-1-5-87: domain 'NT TASK\NT TASK'
S-1-5-90: domain 'Window Manager\Window Manager'
S-1-5-90-0: well-known group 'Window Manager\Window Manager Group'
S-1-5-96: domain 'Font Driver Host\Font Driver Host'
S-1-5-113: well-known group 'NT AUTHORITY\Local account'
S-1-5-114: well-known group 'NT AUTHORITY\Local account and member of Administrators group'
S-1-5-1000: well-known group 'NT AUTHORITY\Other Organization'
S-1-7: domain 'Internet$\Internet$'
S-1-15-2-1: well-known group 'APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES'
S-1-15-3-1: well-known group 'APPLICATION PACKAGE AUTHORITY\Your Internet connection'
S-1-15-3-2: well-known group 'APPLICATION PACKAGE AUTHORITY\Your Internet connection, including incoming connections from the Internet'
S-1-15-3-3: well-known group 'APPLICATION PACKAGE AUTHORITY\Your home or work networks'
S-1-15-3-4: well-known group 'APPLICATION PACKAGE AUTHORITY\Your pictures library'
S-1-15-3-5: well-known group 'APPLICATION PACKAGE AUTHORITY\Your videos library'
S-1-15-3-6: well-known group 'APPLICATION PACKAGE AUTHORITY\Your music library'
S-1-15-3-7: well-known group 'APPLICATION PACKAGE AUTHORITY\Your documents library'
S-1-15-3-8: well-known group 'APPLICATION PACKAGE AUTHORITY\Your Windows credentials'
S-1-15-3-9: well-known group 'APPLICATION PACKAGE AUTHORITY\Software and hardware certificates or a smart card'
S-1-15-3-10: well-known group 'APPLICATION PACKAGE AUTHORITY\Removable storage'
S-1-15-3-11: well-known group 'APPLICATION PACKAGE AUTHORITY\Your Appointments'
S-1-15-3-12: well-known group 'APPLICATION PACKAGE AUTHORITY\Your Contacts'
S-1-16: domain 'Mandatory Label\Mandatory Label'
S-1-16-0: label 'Mandatory Label\Untrusted Mandatory Level'
S-1-16-4096: label 'Mandatory Label\Low Mandatory Level'
S-1-16-8192: label 'Mandatory Label\Medium Mandatory Level'
S-1-16-8448: label 'Mandatory Label\Medium Plus Mandatory Level'
S-1-16-12288: label 'Mandatory Label\High Mandatory Level'
S-1-16-16384: label 'Mandatory Label\System Mandatory Level'
S-1-16-20480: label 'Mandatory Label\Protected Process Mandatory Level'
S-1-18-1: well-known group 'Authentication authority asserted identity'
S-1-18-2: well-known group 'Service asserted identity'
S-1-18-3: well-known group 'Fresh public key identity'
S-1-18-4: well-known group 'Key trust identity'
S-1-18-5: well-known group 'Key property multi-factor authentication'
S-1-18-6: well-known group 'Key property attestation'
S-1-5-21-0-0-0-496: well-known group 'NT AUTHORITY\Compound Identity Present'
S-1-5-21-0-0-0-497: well-known group 'NT AUTHORITY\Claims Valid'
S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464: well-known group 'NT SERVICE\TrustedInstaller'
S-1-5-84-0-0-0-0-0: well-known group 'NT AUTHORITY\USER MODE DRIVERS'
S-1-5-21-820728443-44925810-1835867902: domain 'AMNESIAC'
S-1-5-21-820728443-44925810-1835867902-500: user 'AMNESIAC\Administrator'
S-1-5-21-820728443-44925810-1835867902-501: user 'AMNESIAC\Guest'
S-1-5-21-820728443-44925810-1835867902-503: user 'AMNESIAC\DefaultAccount'
S-1-5-21-820728443-44925810-1835867902-504: user 'AMNESIAC\WDAGUtilityAccount'
S-1-5-21-820728443-44925810-1835867902-513: group 'AMNESIAC\None'
S-1-5-21-820728443-44925810-1835867902-1000: user 'AMNESIAC\Stefan'

Downloads

The console application is available in two functional identical forms: SIDEREAL.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and SIDEREAL.COM, a small form without these extras.

Implementation and Build Details

Really Known SIDs Enumerator is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows XP and newer versions of Windows NT as well as Windows PE 1.5 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source, Build Instructions and Output

Perform the following two simple steps to build the console application Really Known SIDs Enumerator from the source presented hereafter.
  1. Create the text file SIDEREAL.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <sddl.h>
    #include <lmcons.h>
    
    #ifndef SECURITY_LOCAL_LOGON_RID
    #define SECURITY_LOCAL_LOGON_RID				1UL
    #endif
    
    #ifndef SECURITY_CREATOR_OWNER_RIGHTS_RID
    #define SECURITY_CREATOR_OWNER_RIGHTS_RID			4UL
    #endif
    
    #ifndef DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS
    #define DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS	498UL
    #endif
    
    #ifndef DOMAIN_GROUP_RID_READONLY_CONTROLLERS
    #define DOMAIN_GROUP_RID_READONLY_CONTROLLERS			521UL
    #endif
    
    #ifndef DOMAIN_GROUP_RID_CLONEABLE_CONTROLLERS
    #define DOMAIN_GROUP_RID_CLONEABLE_CONTROLLERS			522UL
    #endif
    
    #ifndef DOMAIN_GROUP_RID_PROTECTED_USERS
    #define DOMAIN_GROUP_RID_PROTECTED_USERS			525UL
    #endif
    
    #ifndef DOMAIN_GROUP_RID_KEY_ADMINS
    #define DOMAIN_GROUP_RID_KEY_ADMINS				526UL
    #endif
    
    #ifndef DOMAIN_GROUP_RID_ENTERPRISE_KEY_ADMINS
    #define DOMAIN_GROUP_RID_ENTERPRISE_KEY_ADMINS			527UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_IUSERS
    #define DOMAIN_ALIAS_RID_IUSERS					568UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_CRYPTO_OPERATORS
    #define DOMAIN_ALIAS_RID_CRYPTO_OPERATORS			569UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP
    #define DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP		571UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP
    #define DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP		572UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP
    #define DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP		573UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP
    #define DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP		574UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_RDS_REMOTE_ACCESS_SERVERS
    #define DOMAIN_ALIAS_RID_RDS_REMOTE_ACCESS_SERVERS		575UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_RDS_ENDPOINT_SERVERS
    #define DOMAIN_ALIAS_RID_RDS_ENDPOINT_SERVERS			576UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_RDS_MANAGEMENT_SERVERS
    #define DOMAIN_ALIAS_RID_RDS_MANAGEMENT_SERVERS			577UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_HYPER_V_ADMINS
    #define DOMAIN_ALIAS_RID_HYPER_V_ADMINS				578UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS
    #define DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS		579UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_REMOTE_MANAGEMENT_USERS
    #define DOMAIN_ALIAS_RID_REMOTE_MANAGEMENT_USERS		580UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_DEFAULT_ACCOUNT
    #define DOMAIN_ALIAS_RID_DEFAULT_ACCOUNT			581UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_STORAGE_REPLICA_ADMINS
    #define DOMAIN_ALIAS_RID_STORAGE_REPLICA_ADMINS			582UL
    #endif
    
    #ifndef DOMAIN_ALIAS_RID_DEVICE_OWNERS
    #define DOMAIN_ALIAS_RID_DEVICE_OWNERS				583UL
    #endif
    
    #ifndef SECURITY_IUSER_RID
    #define SECURITY_IUSER_RID					17UL
    #endif
    
    #ifndef SECURITY_ENTERPRISE_READONLY_CONTROLLERS_RID
    #define SECURITY_ENTERPRISE_READONLY_CONTROLLERS_RID		22UL
    #endif
    
    #ifndef SECURITY_WRITE_RESTRICTED_CODE_RID
    #define SECURITY_WRITE_RESTRICTED_CODE_RID			33UL
    #endif
    
    #ifndef SECURITY_CRED_TYPE_BASE_RID
    #define SECURITY_CRED_TYPE_BASE_RID				65UL
    #endif
    
    #ifndef SECURITY_CRED_TYPE_THIS_ORG_CERT_RID
    #define SECURITY_CRED_TYPE_THIS_ORG_CERT_RID			1UL
    #endif
    
    #ifndef SECURITY_SERVICE_ID_BASE_RID
    #define SECURITY_SERVICE_ID_BASE_RID				80UL
    #endif
    
    #ifndef SECURITY_TRUSTED_INSTALLER_RID1
    #define SECURITY_TRUSTED_INSTALLER_RID1				956008885UL
    #define SECURITY_TRUSTED_INSTALLER_RID2				3418522649UL
    #define SECURITY_TRUSTED_INSTALLER_RID3				1831038044UL
    #define SECURITY_TRUSTED_INSTALLER_RID4				1853292631UL
    #define SECURITY_TRUSTED_INSTALLER_RID5				2271478464UL
    #endif
    
    #ifndef SECURITY_RESERVED_ID_BASE_RID
    #define SECURITY_RESERVED_ID_BASE_RID				81UL
    #endif
    
    #ifndef SECURITY_APPPOOL_ID_BASE_RID
    #define SECURITY_APPPOOL_ID_BASE_RID				82UL
    #endif
    
    #ifndef SECURITY_VIRTUALSERVER_ID_BASE_RID
    #define SECURITY_VIRTUALSERVER_ID_BASE_RID			83UL
    #endif
    
    #ifndef SECURITY_USERMODEDRIVERHOST_ID_BASE_RID
    #define SECURITY_USERMODEDRIVERHOST_ID_BASE_RID			84UL
    #endif
    
    #ifndef SECURITY_CLOUD_INFRASTRUCTURE_SERVICES_ID_BASE_RID
    #define SECURITY_CLOUD_INFRASTRUCTURE_SERVICES_ID_BASE_RID	85UL
    #endif
    
    #ifndef SECURITY_WMIHOST_ID_BASE_RID
    #define SECURITY_WMIHOST_ID_BASE_RID				86UL
    #endif
    
    #ifndef SECURITY_TASK_ID_BASE_RID
    #define SECURITY_TASK_ID_BASE_RID				87UL
    #endif
    
    #ifndef SECURITY_NFS_ID_BASE_RID
    #define SECURITY_NFS_ID_BASE_RID				88UL
    #endif
    
    #ifndef SECURITY_COM_ID_BASE_RID
    #define SECURITY_COM_ID_BASE_RID				89UL
    #endif
    
    #ifndef SECURITY_WINDOW_MANAGER_BASE_RID
    #define SECURITY_WINDOW_MANAGER_BASE_RID			90UL
    #endif
    
    #ifndef SECURITY_RDV_GFX_BASE_RID
    #define SECURITY_RDV_GFX_BASE_RID				91UL
    #endif
    
    #ifndef SECURITY_DASHOST_ID_BASE_RID
    #define SECURITY_DASHOST_ID_BASE_RID				92UL
    #endif
    
    #ifndef SECURITY_USERMANAGER_ID_BASE_RID
    #define SECURITY_USERMANAGER_ID_BASE_RID			93UL
    #endif
    
    #ifndef SECURITY_WINRM_ID_BASE_RID
    #define SECURITY_WINRM_ID_BASE_RID				94UL
    #endif
    
    #ifndef SECURITY_WINDOWSMOBILE_ID_BASE_RID
    #define SECURITY_WINDOWSMOBILE_ID_BASE_RID			112UL
    #endif
    
    #ifndef SECURITY_LOCAL_ACCOUNT_RID
    #define SECURITY_LOCAL_ACCOUNT_RID				113UL
    #endif
    
    #ifndef SECURITY_LOCAL_ACCOUNT_AND_ADMIN_RID
    #define SECURITY_LOCAL_ACCOUNT_AND_ADMIN_RID			114UL
    #endif
    
    #ifndef SECURITY_SITESERVER_AUTHORITY
    #define SECURITY_SITESERVER_AUTHORITY		{0, 0, 0, 0, 0, 6}
    #endif
    
    #ifndef SECURITY_INTERNETSITE_AUTHORITY
    #define SECURITY_INTERNETSITE_AUTHORITY		{0, 0, 0, 0, 0, 7}
    #endif
    
    #ifndef SECURITY_EXCHANGE_AUTHORITY
    #define SECURITY_EXCHANGE_AUTHORITY		{0, 0, 0, 0, 0, 8}
    #endif
    
    #ifndef SECURITY_PASSPORT_AUTHORITY
    #define SECURITY_PASSPORT_AUTHORITY		{0, 0, 0, 0, 0, 10}
    #endif
    
    #define SECURITY_MICROSOFT_AUTHORITY		{0, 0, 0, 0, 0, 11}
    
    #ifndef SECURITY_APP_PACKAGE_AUTHORITY
    #define SECURITY_APP_PACKAGE_AUTHORITY		{0, 0, 0, 0, 0, 15}
    #define SECURITY_APP_PACKAGE_BASE_RID				2UL
    #define SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE			1UL
    
    #define SECURITY_CAPABILITY_BASE_RID				3UL
    #define SECURITY_CAPABILITY_INTERNET_CLIENT			1UL
    #define SECURITY_CAPABILITY_INTERNET_CLIENT_SERVER		2UL
    #define SECURITY_CAPABILITY_PRIVATE_NETWORK_CLIENT_SERVER	3UL
    #define SECURITY_CAPABILITY_PICTURES_LIBRARY			4UL
    #define SECURITY_CAPABILITY_VIDEOS_LIBRARY			5UL
    #define SECURITY_CAPABILITY_MUSIC_LIBRARY			6UL
    #define SECURITY_CAPABILITY_DOCUMENTS_LIBRARY			7UL
    #define SECURITY_CAPABILITY_ENTERPRISE_AUTHENTICATION		8UL
    #define SECURITY_CAPABILITY_SHARED_USER_CERTIFICATES		9UL
    #define SECURITY_CAPABILITY_REMOVABLE_STORAGE			10UL
    #define SECURITY_CAPABILITY_APPOINTMENTS			11UL
    #define SECURITY_CAPABILITY_CONTACTS				12UL
    
    #define SECURITY_CAPABILITY_APP_RID				1024UL
    
    #define SECURITY_CAPABILITY_INTERNET_EXPLORER			4096UL
    #endif
    
    #ifndef SECURITY_MANDATORY_LABEL_AUTHORITY
    #define SECURITY_MANDATORY_LABEL_AUTHORITY	{0, 0, 0, 0, 0, 16}
    #define SECURITY_MANDATORY_UNTRUSTED_RID			0UL
    #define SECURITY_MANDATORY_LOW_RID				4096UL
    #define SECURITY_MANDATORY_MEDIUM_RID				8192UL
    #define SECURITY_MANDATORY_MEDIUM_PLUS_RID			(SECURITY_MANDATORY_MEDIUM_RID + 256UL)
    #define SECURITY_MANDATORY_HIGH_RID				12288UL
    #define SECURITY_MANDATORY_SYSTEM_RID				16384UL
    #define SECURITY_MANDATORY_PROTECTED_PROCESS_RID		20480UL
    #endif
    
    #ifndef SECURITY_MANDATORY_SECURE_PROCESS_RID
    #define SECURITY_MANDATORY_SECURE_PROCESS_RID			28672UL
    #endif
    
    #ifndef SECURITY_SCOPED_POLICY_ID_AUTHORITY
    #define SECURITY_SCOPED_POLICY_ID_AUTHORITY	{0, 0, 0, 0, 0, 17}
    #endif
    
    #ifndef SECURITY_AUTHENTICATION_AUTHORITY
    #define SECURITY_AUTHENTICATION_AUTHORITY	{0, 0, 0, 0, 0, 18}
    #define SECURITY_AUTHENTICATION_AUTHORITY_ASSERTED_RID		1UL
    #define SECURITY_AUTHENTICATION_SERVICE_ASSERTED_RID		2UL
    #define SECURITY_AUTHENTICATION_FRESH_KEY_AUTH_RID		3UL
    #define SECURITY_AUTHENTICATION_KEY_TRUST_RID			4UL
    #define SECURITY_AUTHENTICATION_KEY_PROPERTY_MFA_RID		5UL
    #define SECURITY_AUTHENTICATION_KEY_PROPERTY_ATTESTATION_RID	6UL
    #endif
    
    #ifndef SECURITY_PROCESS_TRUST_AUTHORITY
    #define SECURITY_PROCESS_TRUST_AUTHORITY	{0, 0, 0, 0, 0, 19}
    #define SECURITY_PROCESS_PROTECTION_TYPE_NONE_RID		0UL
    #define SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID		512UL
    #define SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID		1024UL
    #define SECURITY_PROCESS_PROTECTION_LEVEL_NONE_RID		0UL
    #define SECURITY_PROCESS_PROTECTION_LEVEL_AUTHENTICODE_RID	1024UL
    #define SECURITY_PROCESS_PROTECTION_LEVEL_APP_RID		2048UL
    #define SECURITY_PROCESS_PROTECTION_LEVEL_WINDOWS_RID		4096UL
    #define SECURITY_PROCESS_PROTECTION_LEVEL_WINTCB_RID		8192UL
    #endif
    
    struct	_SID2
    {
    	BYTE				Revision;
    	BYTE				SubAuthorityCount;
    	SID_IDENTIFIER_AUTHORITY	IdentifierAuthority;
    	DWORD				SubAuthority[2];
    }
    const	sid2[] =
    {
    	// S-1-0 =
    	{SID_REVISION, 0, SECURITY_NULL_SID_AUTHORITY, {0, 0}},
    	// S-1-0-0 = 'NULL SID'
    	{SID_REVISION, 1, SECURITY_NULL_SID_AUTHORITY, {SECURITY_NULL_RID, 0}},
    
    	// S-1-1 =
    	{SID_REVISION, 0, SECURITY_WORLD_SID_AUTHORITY, {0, 0}},
    	// S-1-1-0 = 'Everyone'
    	{SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, {SECURITY_WORLD_RID, 0}},
    
    	// S-1-2 =
    	{SID_REVISION, 0, SECURITY_LOCAL_SID_AUTHORITY, {0, 0}},
    	// S-1-2-0 = 'LOCAL'
    	{SID_REVISION, 1, SECURITY_LOCAL_SID_AUTHORITY, {SECURITY_LOCAL_RID, 0}},
    	// S-1-2-1 = 'CONSOLE LOGON'
    	{SID_REVISION, 1, SECURITY_LOCAL_SID_AUTHORITY, {SECURITY_LOCAL_LOGON_RID, 0}},
    
    	// S-1-3 =
    	{SID_REVISION, 0, SECURITY_CREATOR_SID_AUTHORITY, {0, 0}},
    	// S-1-3-0 = 'CREATOR OWNER'
    	{SID_REVISION, 1, SECURITY_CREATOR_SID_AUTHORITY, {SECURITY_CREATOR_OWNER_RID, 0}},
    	// S-1-3-1 = 'CREATOR GROUP'
    	{SID_REVISION, 1, SECURITY_CREATOR_SID_AUTHORITY, {SECURITY_CREATOR_GROUP_RID, 0}},
    	// S-1-3-2 = 'CREATOR OWNER SERVER'
    	{SID_REVISION, 1, SECURITY_CREATOR_SID_AUTHORITY, {SECURITY_CREATOR_OWNER_SERVER_RID, 0}},
    	// S-1-3-3 = 'CREATOR GROUP SERVER'
    	{SID_REVISION, 1, SECURITY_CREATOR_SID_AUTHORITY, {SECURITY_CREATOR_GROUP_SERVER_RID, 0}},
    	// S-1-3-4 = 'OWNER RIGHTS'
    	{SID_REVISION, 1, SECURITY_CREATOR_SID_AUTHORITY, {SECURITY_CREATOR_OWNER_RIGHTS_RID, 0}},
    
    	// S-1-4 =
    	{SID_REVISION, 0, SECURITY_NON_UNIQUE_AUTHORITY, {0, 0}},
    	// S-1-4-0 =
    	{SID_REVISION, 1, SECURITY_NON_UNIQUE_AUTHORITY, {0, 0}},
    
    	// S-1-5 = 'NT Pseudo Domain\NT Pseudo Domain'
    	{SID_REVISION, 0, SECURITY_NT_AUTHORITY, {0, 0}},
    	// S-1-5-1 = 'NT AUTHORITY\DIALUP'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_DIALUP_RID, 0}},
    	// S-1-5-2 = 'NT AUTHORITY\NETWORK'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_NETWORK_RID, 0}},
    	// S-1-5-3 = 'NT AUTHORITY\BATCH'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_BATCH_RID, 0}},
    	// S-1-5-4 = 'NT AUTHORITY\INTERACTIVE'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_INTERACTIVE_RID, 0}},
    
    	// S-1-5-5 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_LOGON_IDS_RID, 0}},
    	// S-1-5-5-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_LOGON_IDS_RID, 0}},
    
    	// S-1-5-6 = 'NT AUTHORITY\SERVICE'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_SERVICE_RID, 0}},
    	// S-1-5-7 = 'NT AUTHORITY\ANONYMOUS LOGON'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_ANONYMOUS_LOGON_RID, 0}},
    	// S-1-5-8 = 'NT AUTHORITY\PROXY'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_PROXY_RID, 0}},
    	// S-1-5-9 = 'NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_ENTERPRISE_CONTROLLERS_RID, 0}},
    	// S-1-5-10 = 'NT AUTHORITY\SELF'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_PRINCIPAL_SELF_RID, 0}},
    	// S-1-5-11 = 'NT AUTHORITY\Authenticated Users'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_AUTHENTICATED_USER_RID, 0}},
    	// S-1-5-12 = 'NT AUTHORITY\RESTRICTED'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_RESTRICTED_CODE_RID, 0}},
    	// S-1-5-13 = 'NT AUTHORITY\TERMINAL SERVER USER'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_TERMINAL_SERVER_RID, 0}},
    	// S-1-5-14 = 'NT AUTHORITY\REMOTE INTERACTIVE LOGON'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_REMOTE_LOGON_RID, 0}},
    	// S-1-5-15 = 'NT AUTHORITY\This Organization'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_THIS_ORGANIZATION_RID, 0}},
    	// S-1-5-16 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {16, 0}},
    	// S-1-5-17 = 'NT AUTHORITY\IUSR'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_IUSER_RID, 0}},
    	// S-1-5-18 = 'NT AUTHORITY\SYSTEM'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_LOCAL_SYSTEM_RID, 0}},
    	// S-1-5-19 = 'NT AUTHORITY\LOCAL SERVICE'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_LOCAL_SERVICE_RID, 0}},
    	// S-1-5-20 = 'NT AUTHORITY\NETWORK SERVICE'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_NETWORK_SERVICE_RID, 0}},
    
    	// S-1-5-21 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_NT_NON_UNIQUE, 0}},
    	// S-1-5-21-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_NT_NON_UNIQUE, 0}},
    	// S-1-5-21-1 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_NT_NON_UNIQUE, 1}},
    
    	// S-1-5-22 = 'NT AUTHORITY\ENTERPRISE READ-ONLY DOMAIN CONTROLLERS BETA'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_ENTERPRISE_READONLY_CONTROLLERS_RID, 0}},
    
    	// S-1-5-32 = 'BUILTIN\BUILTIN'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, 0}},
    	// S-1-5-32-498 = 'BUILTIN\Enterprise Read-Only Domain Controllers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS}},
    	// S-1-5-32-500 = 'BUILTIN\Administrator'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_USER_RID_ADMIN}},
    	// S-1-5-32-501 = 'BUILTIN\User'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_USER_RID_GUEST}},
    	// S-1-5-32-502 = 'BUILTIN\Kerberos Ticket Granting Ticket'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_USER_RID_KRBTGT}},
    	// S-1-5-32-512 = 'BUILTIN\Domain Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_ADMINS}},
    	// S-1-5-32-513 = 'BUILTIN\Domain Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_USERS}},
    	// S-1-5-32-514 = 'BUILTIN\Domain Guests'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_GUESTS}},
    	// S-1-5-32-515 = 'BUILTIN\Domain Computers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_COMPUTERS}},
    	// S-1-5-32-516 = 'BUILTIN\Domain Controllers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_CONTROLLERS}},
    	// S-1-5-32-517 = 'BUILTIN\Certificate Server Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_CERT_ADMINS}},
    	// S-1-5-32-518 = 'BUILTIN\Schema Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_SCHEMA_ADMINS}},
    	// S-1-5-32-519 = 'BUILTIN\Enterprise Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS}},
    	// S-1-5-32-520 = 'BUILTIN\Group Policy Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_POLICY_ADMINS}},
    	// S-1-5-32-521 = 'BUILTIN\Read-Only Domain Controllers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_READONLY_CONTROLLERS}},
    	// S-1-5-32-522 = 'BUILTIN\Cloneable Controllers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_CLONEABLE_CONTROLLERS}},
    	// S-1-5-32-525 = 'BUILTIN\Protected Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_PROTECTED_USERS}},
    	// S-1-5-32-526 = 'BUILTIN\Key Admins'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_KEY_ADMINS}},
    	// S-1-5-32-527 = 'BUILTIN\Enterprise Key Admins'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_GROUP_RID_ENTERPRISE_KEY_ADMINS}},
    	// S-1-5-32-544 = 'BUILTIN\Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS}},
    	// S-1-5-32-545 = 'BUILTIN\Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS}},
    	// S-1-5-32-546 = 'BUILTIN\Guests'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS}},
    	// S-1-5-32-547 = 'BUILTIN\Power Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS}},
    	// S-1-5-32-548 = 'BUILTIN\Account Operators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS}},
    	// S-1-5-32-549 = 'BUILTIN\System Operators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS}},
    	// S-1-5-32-550 = 'BUILTIN\Print Operators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS}},
    	// S-1-5-32-551 = 'BUILTIN\Backup Operators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS}},
    	// S-1-5-32-552 = 'BUILTIN\Replicator'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR}},
    	// S-1-5-32-553 = 'BUILTIN\RAS Servers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_RAS_SERVERS}},
    	// S-1-5-32-554 = 'BUILTIN\Pre-Windows 2000 Compatible Access'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS}},
    	// S-1-5-32-555 = 'BUILTIN\Remote Desktop Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS}},
    	// S-1-5-32-556 = 'BUILTIN\Network Configuration Operators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS}},
    	// S-1-5-32-557 = 'BUILTIN\Incoming Forest Trust Builders'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS}},
    	// S-1-5-32-558 = 'BUILTIN\Performance Monitor Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS}},
    	// S-1-5-32-559 = 'BUILTIN\Performance Log Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS}},
    	// S-1-5-32-560 = 'BUILTIN\Windows Authorization Access Group'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS}},
    	// S-1-5-32-561 = 'BUILTIN\Terminal Server License Servers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS}},
    	// S-1-5-32-562 = 'BUILTIN\Distributed COM Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS}},
    	// S-1-5-32-568 = 'BUILTIN\IIS IUSRS'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_IUSERS}},
    	// S-1-5-32-569 = 'BUILTIN\Cryptographic Operators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_CRYPTO_OPERATORS}},
    	// S-1-5-32-571 = 'BUILTIN\Allowed RODC Password Replication Group'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP}},
    	// S-1-5-32-572 = 'BUILTIN\Denied RODC Password Replication Group'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP}},
    	// S-1-5-32-573 = 'BUILTIN\Event Log Readers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP}},
    	// S-1-5-32-574 = 'BUILTIN\Certificate Service DCOM Access'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP}},
    	// S-1-5-32-575 = 'BUILTIN\RDS Remote Access Servers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_RDS_REMOTE_ACCESS_SERVERS}},
    	// S-1-5-32-576 = 'BUILTIN\RDS Endpoint Servers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_RDS_ENDPOINT_SERVERS}},
    	// S-1-5-32-577 = 'BUILTIN\RDS Management Servers'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_RDS_MANAGEMENT_SERVERS}},
    	// S-1-5-32-578 = 'BUILTIN\Hyper-V Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_HYPER_V_ADMINS}},
    	// S-1-5-32-579 = 'BUILTIN\Access Control Assistance Operators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS}},
    	// S-1-5-32-580 = 'BUILTIN\Remote Management Users'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_MANAGEMENT_USERS}},
    	// S-1-5-32-581 = 'BUILTIN\System Managed Accounts Group'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DEFAULT_ACCOUNT}},
    	// S-1-5-32-582 = 'BUILTIN\Storage Replica Administrators'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_STORAGE_REPLICA_ADMINS}},
    	// S-1-5-32-583 = 'BUILTIN\Device Owners'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DEVICE_OWNERS}},
    
    	// S-1-5-33 = 'NT AUTHORITY\WRITE RESTRICTED'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_WRITE_RESTRICTED_CODE_RID, 0}},
    
    	// S-1-5-64 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_PACKAGE_BASE_RID, 0}},
    	// S-1-5-64-10 = 'NT AUTHORITY\NTLM Authentication'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID}},
    	// S-1-5-64-14 = 'NT AUTHORITY\SChannel Authentication'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID}},
    	// S-1-5-64-21 = 'NT AUTHORITY\Digest Authentication'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID}},
    	// S-1-5-64-32 = 'NT AUTHORITY\Microsoft Account Authentication'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_PACKAGE_BASE_RID, 32}},
    
    	// S-1-5-65 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_CRED_TYPE_BASE_RID, 0}},
    	// S-1-5-65-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_CRED_TYPE_BASE_RID, 0}},
    	// S-1-5-65-1 = 'NT AUTHORITY\This Organization Certificate'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_CRED_TYPE_BASE_RID, SECURITY_CRED_TYPE_THIS_ORG_CERT_RID}},
    
    	// S-1-5-80 = 'NT SERVICE\NT SERVICE'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_SERVICE_ID_BASE_RID, 0}},
    	// S-1-5-80-0 = 'NT SERVICE\ALL SERVICES'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_SERVICE_ID_BASE_RID, 0}},
    	// S-1-5-80-1 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_SERVICE_ID_BASE_RID, 1}},
    
    	// S-1-5-81 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_RESERVED_ID_BASE_RID, 0}},
    	// S-1-5-81-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_RESERVED_ID_BASE_RID, 0}},
    
    	// S-1-5-82 = 'IIS APPPOOL\IIS APPPOOL'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_APPPOOL_ID_BASE_RID, 0}},
    	// S-1-5-82-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_APPPOOL_ID_BASE_RID, 0}},
    
    	// S-1-5-83 = 'NT VIRTUAL MACHINE\NT VIRTUAL MACHINE'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_VIRTUALSERVER_ID_BASE_RID, 0}},
    	// S-1-5-83-0 = 'NT VIRTUAL MACHINE\Virtual Machines'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_VIRTUALSERVER_ID_BASE_RID, 0}},
    
    	// S-1-5-84 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_USERMODEDRIVERHOST_ID_BASE_RID, 0}},
    	// S-1-5-84-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_USERMODEDRIVERHOST_ID_BASE_RID, 0}},
    
    	// S-1-5-85 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_CLOUD_INFRASTRUCTURE_SERVICES_ID_BASE_RID, 0}},
    	// S-1-5-85-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_CLOUD_INFRASTRUCTURE_SERVICES_ID_BASE_RID, 0}},
    
    	// S-1-5-86 = 'WMI\WMI'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_WMIHOST_ID_BASE_RID, 0}},
    	// S-1-5-86-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_WMIHOST_ID_BASE_RID, 0}},
    
    	// S-1-5-87 = 'NT TASK\NT TASK'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_TASK_ID_BASE_RID, 0}},
    	// S-1-5-87-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_TASK_ID_BASE_RID, 0}},
    
    	// S-1-5-88 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_NFS_ID_BASE_RID, 0}},
    	// S-1-5-88-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_NFS_ID_BASE_RID, 0}},
    
    	// S-1-5-89 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_COM_ID_BASE_RID, 0}},
    	// S-1-5-89-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_COM_ID_BASE_RID, 0}},
    
    	// S-1-5-90 = 'Window Manager\Window Manager'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_WINDOW_MANAGER_BASE_RID, 0}},
    	// S-1-5-90-0 = 'Window Manager\Window Manager Group'
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_WINDOW_MANAGER_BASE_RID, 0}},
    
    	// S-1-5-91 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_RDV_GFX_BASE_RID, 0}},
    	// S-1-5-91-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_RDV_GFX_BASE_RID, 0}},
    
    	// S-1-5-92 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_DASHOST_ID_BASE_RID, 0}},
    	// S-1-5-92-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_DASHOST_ID_BASE_RID, 0}},
    
    	// S-1-5-93 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_USERMANAGER_ID_BASE_RID, 0}},
    	// S-1-5-93-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_USERMANAGER_ID_BASE_RID, 0}},
    
    	// S-1-5-94 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_WINRM_ID_BASE_RID, 0}},
    	// S-1-5-94-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_WINRM_ID_BASE_RID, 0}},
    
    	// S-1-5-95 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {95, 0}},
    	// S-1-5-95-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {95, 0}},
    
    	// S-1-5-96 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {96, 0}},
    	// S-1-5-96-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {96, 0}},
    
    	// S-1-5-112 =
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_WINDOWSMOBILE_ID_BASE_RID, 0}},
    	// S-1-5-112-0 =
    	{SID_REVISION, 2, SECURITY_NT_AUTHORITY, {SECURITY_WINDOWSMOBILE_ID_BASE_RID, 0}},
    
    	// S-1-5-113 = 'NT AUTHORITY\Local Account'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_LOCAL_ACCOUNT_RID, 0}},
    	// S-1-5-114 = 'NT AUTHORITY\Local Account and Member of Administrators Group'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_LOCAL_ACCOUNT_AND_ADMIN_RID, 0}},
    	// S-1-5-1000 = 'NT AUTHORITY\Other Organization'
    	{SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_OTHER_ORGANIZATION_RID, 0}},
    
    	// S-1-6 =
    	{SID_REVISION, 0, SECURITY_SITESERVER_AUTHORITY, {0, 0}},
    	// S-1-6-0 =
    	{SID_REVISION, 1, SECURITY_SITESERVER_AUTHORITY, {0, 0}},
    	// S-1-6-0-0 =
    	{SID_REVISION, 2, SECURITY_SITESERVER_AUTHORITY, {0, 0}},
    	// S-1-6-0-1 =
    	{SID_REVISION, 2, SECURITY_SITESERVER_AUTHORITY, {0, 1}},
    
    	// S-1-7 = 'Internet$\Internet$'
    	{SID_REVISION, 0, SECURITY_INTERNETSITE_AUTHORITY, {0, 0}},
    	// S-1-7-0 =
    	{SID_REVISION, 1, SECURITY_INTERNETSITE_AUTHORITY, {0, 0}},
    	// S-1-7-0-0 =
    	{SID_REVISION, 2, SECURITY_INTERNETSITE_AUTHORITY, {0, 0}},
    	// S-1-7-0-1 =
    	{SID_REVISION, 2, SECURITY_INTERNETSITE_AUTHORITY, {0, 1}},
    
    	// S-1-8 =
    	{SID_REVISION, 0, SECURITY_EXCHANGE_AUTHORITY, {0, 0}},
    	// S-1-8-0 =
    	{SID_REVISION, 1, SECURITY_EXCHANGE_AUTHORITY, {0, 0}},
    	// S-1-8-0-0 =
    	{SID_REVISION, 2, SECURITY_EXCHANGE_AUTHORITY, {0, 0}},
    	// S-1-8-0-1 =
    	{SID_REVISION, 2, SECURITY_EXCHANGE_AUTHORITY, {0, 1}},
    
    	// S-1-9 =
    	{SID_REVISION, 0, SECURITY_RESOURCE_MANAGER_AUTHORITY, {0, 0}},
    	// S-1-9-0 =
    	{SID_REVISION, 1, SECURITY_RESOURCE_MANAGER_AUTHORITY, {0, 0}},
    	// S-1-9-0-0 =
    	{SID_REVISION, 2, SECURITY_RESOURCE_MANAGER_AUTHORITY, {0, 0}},
    	// S-1-9-0-1 =
    	{SID_REVISION, 2, SECURITY_RESOURCE_MANAGER_AUTHORITY, {0, 1}},
    
    	// S-1-10 =
    	{SID_REVISION, 0, SECURITY_PASSPORT_AUTHORITY, {0, 0}},
    	// S-1-10-0 =
    	{SID_REVISION, 1, SECURITY_PASSPORT_AUTHORITY, {0, 0}},
    	// S-1-10-0-0 =
    	{SID_REVISION, 2, SECURITY_PASSPORT_AUTHORITY, {0, 0}},
    	// S-1-10-0-1 =
    	{SID_REVISION, 2, SECURITY_PASSPORT_AUTHORITY, {0, 1}},
    
    	// S-1-11 =
    	{SID_REVISION, 0, SECURITY_MICROSOFT_AUTHORITY, {0, 0}},
    	// S-1-11-96 =
    	{SID_REVISION, 1, SECURITY_MICROSOFT_AUTHORITY, {96, 0}},
    
    	// S-1-15 =
    	{SID_REVISION, 0, SECURITY_APP_PACKAGE_AUTHORITY, {0, 0}},
    	// S-1-15-0 =
    	{SID_REVISION, 1, SECURITY_APP_PACKAGE_AUTHORITY, {0, 0}},
    	// S-1-15-1 = 'APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES'
    	{SID_REVISION, 1, SECURITY_APP_PACKAGE_AUTHORITY, {1, 0}},
    	// S-1-15-2 =
    	{SID_REVISION, 1, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_APP_PACKAGE_BASE_RID, 0}},
    	// S-1-15-2-0 =
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_APP_PACKAGE_BASE_RID, 0}},
    	// S-1-15-2-1 =
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE}},
    	// S-1-15-3 =
    	{SID_REVISION, 1, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, 0}},
    	// S-1-15-3-0 =
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, 0}},
    	// S-1-15-3-1 = 'APPLICATION PACKAGE AUTHORITY\Your Internet connection'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_INTERNET_CLIENT}},
    	// S-1-15-3-2 = 'APPLICATION PACKAGE AUTHORITY\Your Internet connection, including incoming connections from the Internet'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_INTERNET_CLIENT_SERVER}},
    	// S-1-15-3-3 = 'APPLICATION PACKAGE AUTHORITY\Your home or work networks'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_PRIVATE_NETWORK_CLIENT_SERVER}},
    	// S-1-15-3-4 = 'APPLICATION PACKAGE AUTHORITY\Your pictures library'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_PICTURES_LIBRARY}},
    	// S-1-15-3-5 = 'APPLICATION PACKAGE AUTHORITY\Your videos library'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_VIDEOS_LIBRARY}},
    	// S-1-15-3-6 = 'APPLICATION PACKAGE AUTHORITY\Your music library'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_MUSIC_LIBRARY}},
    	// S-1-15-3-7 = 'APPLICATION PACKAGE AUTHORITY\Your documents library'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_DOCUMENTS_LIBRARY}},
    	// S-1-15-3-8 = 'APPLICATION PACKAGE AUTHORITY\Your Windows credentials'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_ENTERPRISE_AUTHENTICATION}},
    	// S-1-15-3-9 = 'APPLICATION PACKAGE AUTHORITY\Software and hardware certificates or a smart card'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_SHARED_USER_CERTIFICATES}},
    	// S-1-15-3-10 = 'APPLICATION PACKAGE AUTHORITY\Removable storage'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_REMOVABLE_STORAGE}},
    	// S-1-15-3-11 = 'APPLICATION PACKAGE AUTHORITY\Your Appointments'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_APPOINTMENTS}},
    	// S-1-15-3-12 = 'APPLICATION PACKAGE AUTHORITY\Your Contacts'
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_CONTACTS}},
    	// S-1-15-3-1024 =
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_APP_RID}},
    	// S-1-15-3-4096 =
    	{SID_REVISION, 2, SECURITY_APP_PACKAGE_AUTHORITY, {SECURITY_CAPABILITY_BASE_RID, SECURITY_CAPABILITY_INTERNET_EXPLORER}},
    
    	// S-1-16 = 'Mandatory Label\Mandatory Label'
    	{SID_REVISION, 0, SECURITY_MANDATORY_LABEL_AUTHORITY, {0, 0}},
    	// S-1-16-0 = 'Mandatory Label\Untrusted Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_UNTRUSTED_RID, 0}},
    	// S-1-16-4096 = 'Mandatory Label\Low Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_LOW_RID, 0}},
    	// S-1-16-8192 = 'Mandatory Label\Medium Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_MEDIUM_RID, 0}},
    	// S-1-16-8448 = 'Mandatory Label\Medium Plus Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_MEDIUM_PLUS_RID, 0}},
    	// S-1-16-12288 = 'Mandatory Label\High Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_HIGH_RID, 0}},
    	// S-1-16-16384 = 'Mandatory Label\System Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_SYSTEM_RID, 0}},
    	// S-1-16-20480 = 'Mandatory Label\Protected Process Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_PROTECTED_PROCESS_RID, 0}},
    	// S-1-16-24576 =
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {24576, 0}},
    	// S-1-16-28672 = 'Mandatory Label\Secure Process Mandatory Level'
    	{SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, {SECURITY_MANDATORY_SECURE_PROCESS_RID, 0}},
    
    	// S-1-17 =
    	{SID_REVISION, 0, SECURITY_SCOPED_POLICY_ID_AUTHORITY, {0, 0}},
    	// S-1-17-0 =
    	{SID_REVISION, 1, SECURITY_SCOPED_POLICY_ID_AUTHORITY, {0, 0}},
    
    	// S-1-18 =
    	{SID_REVISION, 0, SECURITY_AUTHENTICATION_AUTHORITY, {0, 0}},
    	// S-1-18-0 =
    	{SID_REVISION, 1, SECURITY_AUTHENTICATION_AUTHORITY, {0, 0}},
    	// S-1-18-1 = 'Authentication Authority Asserted Identity'
    	{SID_REVISION, 1, SECURITY_AUTHENTICATION_AUTHORITY, {SECURITY_AUTHENTICATION_AUTHORITY_ASSERTED_RID, 0}},
    	// S-1-18-2 = 'Service Asserted Identity'
    	{SID_REVISION, 1, SECURITY_AUTHENTICATION_AUTHORITY, {SECURITY_AUTHENTICATION_SERVICE_ASSERTED_RID, 0}},
    	// S-1-18-3 = 'Fresh Public Key Identity'
    	{SID_REVISION, 1, SECURITY_AUTHENTICATION_AUTHORITY, {SECURITY_AUTHENTICATION_FRESH_KEY_AUTH_RID, 0}},
    	// S-1-18-4 = 'Key Trust Identity'
    	{SID_REVISION, 1, SECURITY_AUTHENTICATION_AUTHORITY, {SECURITY_AUTHENTICATION_KEY_TRUST_RID, 0}},
    	// S-1-18-5 = 'Key Property Multi-factor Authentication'
    	{SID_REVISION, 1, SECURITY_AUTHENTICATION_AUTHORITY, {SECURITY_AUTHENTICATION_KEY_PROPERTY_MFA_RID, 0}},
    	// S-1-18-6 = 'Key Property Attestation'
    	{SID_REVISION, 1, SECURITY_AUTHENTICATION_AUTHORITY, {SECURITY_AUTHENTICATION_KEY_PROPERTY_ATTESTATION_RID, 0}},
    
    	// S-1-19 =
    	{SID_REVISION, 0, SECURITY_PROCESS_TRUST_AUTHORITY, {0, 0}},
    	// S-1-19-0 =
    	{SID_REVISION, 1, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_NONE_RID, 0}},
    	// S-1-19-0-0 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_NONE_RID, SECURITY_PROCESS_PROTECTION_LEVEL_NONE_RID}},
    	// S-1-19-512 =
    	{SID_REVISION, 1, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID, 0}},
    	// S-1-19-512-0 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID, SECURITY_PROCESS_PROTECTION_LEVEL_NONE_RID}},
    	// S-1-19-512-1024 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID, SECURITY_PROCESS_PROTECTION_LEVEL_AUTHENTICODE_RID}},
    	// S-1-19-512-2048 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID, SECURITY_PROCESS_PROTECTION_LEVEL_APP_RID}},
    	// S-1-19-512-4096 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID, SECURITY_PROCESS_PROTECTION_LEVEL_WINDOWS_RID}},
    	// S-1-19-512-8192 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID, SECURITY_PROCESS_PROTECTION_LEVEL_WINTCB_RID}},
    	// S-1-19-1024 =
    	{SID_REVISION, 1, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID, 0}},
    	// S-1-19-1024-0 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID, SECURITY_PROCESS_PROTECTION_LEVEL_NONE_RID}},
    	// S-1-19-1024-1024 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID, SECURITY_PROCESS_PROTECTION_LEVEL_AUTHENTICODE_RID}},
    	// S-1-19-1024-2048 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID, SECURITY_PROCESS_PROTECTION_LEVEL_APP_RID}},
    	// S-1-19-1024-4096 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID, SECURITY_PROCESS_PROTECTION_LEVEL_WINDOWS_RID}},
    	// S-1-19-1024-8192 =
    	{SID_REVISION, 2, SECURITY_PROCESS_TRUST_AUTHORITY, {SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID, SECURITY_PROCESS_PROTECTION_LEVEL_WINTCB_RID}}
    };
    
    struct	_SID6
    {
    	BYTE				Revision;
    	BYTE				SubAuthorityCount;
    	SID_IDENTIFIER_AUTHORITY	IdentifierAuthority;
    	DWORD				SubAuthority[6];
    }
    const	sid6[] =
    {
    	// S-1-5-21-0-0-0-496 =
    	{SID_REVISION, 5, SECURITY_NT_AUTHORITY, {SECURITY_NT_NON_UNIQUE, 0, 0, 0, 496, 0}},
    	// S-1-5-21-0-0-0-497 =
    	{SID_REVISION, 5, SECURITY_NT_AUTHORITY, {SECURITY_NT_NON_UNIQUE, 0, 0, 0, 497, 0}},
    
    	// S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464 = 'NT SERVICE\TrustedInstaller'
    	{SID_REVISION, 6, SECURITY_NT_AUTHORITY, {SECURITY_SERVICE_ID_BASE_RID, SECURITY_TRUSTED_INSTALLER_RID1, SECURITY_TRUSTED_INSTALLER_RID2, SECURITY_TRUSTED_INSTALLER_RID3, SECURITY_TRUSTED_INSTALLER_RID4, SECURITY_TRUSTED_INSTALLER_RID5}},
    	// S-1-5-84-0-0-0-0-0 = 'NT AUTHORITY\USER MODE DRIVERS'
    	{SID_REVISION, 6, SECURITY_NT_AUTHORITY, {SECURITY_USERMODEDRIVERHOST_ID_BASE_RID, 0, 0, 0, 0, 0}},
    	// S-1-5-86-615999462-62705297-2911207457-59056572-3668589837 = 'WMI\Network Service'
    	{SID_REVISION, 6, SECURITY_NT_AUTHORITY, {SECURITY_WMIHOST_ID_BASE_RID, 615999462, 62705297, 2911207457, 59056572, 3668589837}},
    	// S-1-5-86-1544737700-199408000-2549878335-3519669259-381336952 = 'WMI\Local Service'
    	{SID_REVISION, 6, SECURITY_NT_AUTHORITY, {SECURITY_WMIHOST_ID_BASE_RID, 1544737700, 199408000, 2549878335, 3519669259, 381336952}}
    };
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    const	LPCWSTR	szSNU[] = {NULL,
    		           L"user",
    		           L"group",
    		           L"domain",
    		           L"alias",
    		           L"well-known group",
    		           L"deleted account",
    		           L"invalid",
    		           L"unknown",
    		           L"computer",
    		           L"label",
    		           L"logon session"};
    
    __declspec(safebuffers)
    SID_NAME_USE	WINAPI	CheckSID(HANDLE hConsole, SID *sid)
    {
    	LPWSTR	lpStringSID;
    	DWORD	dwError = ERROR_SUCCESS;
    	WCHAR	szAccount[UNLEN + 1];
    	DWORD	dwAccount = sizeof(szAccount) / sizeof(*szAccount);
    	WCHAR	szDomain[GNLEN + 1];
    	DWORD	dwDomain = sizeof(szDomain) / sizeof(*szDomain);
    
    	SID_NAME_USE	snu = 0;
    
    	if (!ConvertSidToStringSid(sid, &lpStringSID))
    		PrintConsole(hConsole,
    		             L"ConvertSidToStringSid() returned error %lu\n",
    		             dwError = GetLastError());
    	else
    	{
    		if (!LookupAccountSid((LPCWSTR) NULL,
    		                      sid,
    		                      szAccount, &dwAccount,
    		                      szDomain, &dwDomain,
    		                      &snu))
    		{
    			dwError = GetLastError();
    
    			if (dwError != ERROR_NONE_MAPPED)
    				PrintConsole(hConsole,
    				             L"LookupAccountSid() returned error %lu for security identifier \'%ls\'\n",
    				             dwError, lpStringSID);
    		}
    		else
    			if (*szDomain == L'\0')
    				PrintConsole(hConsole,
    				             L"%ls: %ls \'%ls\'\n",
    				             lpStringSID, szSNU[snu], szAccount);
    			else if (*szAccount == L'\0')
    				PrintConsole(hConsole,
    				             L"%ls: %ls \'%ls\'\n",
    				             lpStringSID, szSNU[snu], szDomain);
    			else
    				PrintConsole(hConsole,
    				             L"%ls: %ls \'%ls\\%ls\'\n",
    				             lpStringSID, szSNU[snu], szDomain, szAccount);
    
    		if (LocalFree(lpStringSID) != NULL)
    			PrintConsole(hConsole,
    			             L"LocalFree() returned error %lu\n",
    			             GetLastError());
    	}
    
    //	SetLastError(dwError);
    
    	return snu;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	SID_NAME_USE	snu;
    
    	WCHAR	szAccount[UNLEN + 1];
    	DWORD	dwAccount = sizeof(szAccount) / sizeof(*szAccount);
    	WCHAR	szDomain[GNLEN + 1];
    	DWORD	dwDomain = sizeof(szDomain) / sizeof(*szDomain);
    	BYTE	sid[SECURITY_MAX_SID_SIZE];
    	BOOL	bSid;
    	DWORD	dwSid;
    	DWORD	dw;
    	DWORD	*lpRid;
    	DWORD	dwError = ERROR_SUCCESS;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		for (dw = 0; dw < sizeof(sid2) / sizeof(*sid2); dw++)
    			CheckSID(hConsole, (SID *) &sid2[dw]);
    
    		for (dw = 0; dw < sizeof(sid6) / sizeof(*sid6); dw++)
    			CheckSID(hConsole, (SID *) &sid6[dw]);
    
    		for (dw = 0; dw < 128; dw++)
    		{
    			dwSid = sizeof(sid);
    
    			if (!CreateWellKnownSid((WELL_KNOWN_SID_TYPE) dw,
    			                        (SID *) NULL,
    			                        (SID *) sid,
    			                        &dwSid))
    			{
    				dwError = GetLastError();
    
    				if (dwError != ERROR_INVALID_PARAMETER)
    					PrintConsole(hConsole,
    					             L"CreateWellKnownSid() returned error %lu\n",
    					             dwError);
    			}
    			else
    			{
    				bSid = FALSE;
    
    				if (dwSid <= sizeof(*sid2))
    				{
    					for (dwSid = 0; dwSid < sizeof(sid2) / sizeof(*sid2); dwSid++)
    						if (bSid = EqualSid((SID *) sid, (SID *) &sid2[dwSid]))
    							break;
    				}
    				else if (dwSid == sizeof(*sid6))
    				{
    					for (dwSid = 0; dwSid < sizeof(sid6) / sizeof(*sid6); dwSid++)
    						if (bSid = EqualSid((SID *) sid, (SID *) &sid6[dwSid]))
    							break;
    				}
    				else
    					continue;
    
    				if (!bSid)
    					CheckSID(hConsole, (SID *) sid);
    			}
    		}
    
    		if (!GetComputerName(szAccount, &dwAccount))
    			PrintConsole(hConsole,
    			             L"GetComputerName() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			dwSid = sizeof(sid);
    
    			if (!LookupAccountName((LPCWSTR) NULL,
    			                       szAccount,
    			                       (SID *) sid, &dwSid,
    			                       szDomain, &dwDomain,
    			                       &snu))
    				PrintConsole(hConsole,
    				             L"LookupAccountName() returned error %lu for \'%ls\'\n",
    				             dwError = GetLastError(), szAccount);
    			else
    			{
    				CheckSID(hConsole, (SID *) sid);
    
    				lpRid = GetSidSubAuthority((SID *) sid, GetSidSubAuthorityCount((SID *) sid)[0]++);
    
    				for (lpRid[0] = FOREST_USER_RID_MAX - 1; lpRid[0] <= DOMAIN_USER_RID_MAX + 1; lpRid[0]++)
    					CheckSID(hConsole, (SID *) sid);
    			}
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file SIDEREAL.C created in step 1., link the compiled object file SIDEREAL.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.1 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeSIDEREAL.COM SIDEREAL.C ADVAPI32.LIB KERNEL32.LIB USER32.LIB
    ERASE SIDEREAL.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    SIDEREAL.C
    SIDEREAL.C(966) : warning C4706: assignment within conditional expression
    SIDEREAL.C(972) : warning C4706: assignment within conditional expression
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

SLIC ACPI Table & XrML Digital License Decoder

Purpose
Background Information
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Decode a XrML (.xrm-ms) digital license file and match its base64 encoded certificate against an eventually present SLIC ACPI table in the machine’s BIOS.

Background Information

OEM (offline) activation of Windows Vista, Windows Server 2008 and Windows 7 is accomplished per SLIC ACPI table provided by an OEM in the BIOS, a matching 2731 byte XrML (.xrm-ms) digital license file in the directory %SystemRoot%\System32\OEM\, and an OEM:SLP product key for the installed version and edition of Windows.

Note: a single 2731 byte XrML (.xrm-ms) digital license file can also be installed by an administrator with the following command line:

SLMGR.VBS /ILC ‹XrML digital license file›

Synopsis

SLICHECK.COM ‹XrML digital license file›

Demonstration

SLICHECK.COM "%SystemRoot%\System32\OEM\FUJITSU_SIEMENS_COMPUTERS_GMBH.XRM-MS"
XrML digital license file 'C:\Windows\System32\OEM\FUJITSU_SIEMENS_COMPUTERS_GMBH.XRM-MS': size = 2731
	Application ID:		{55c92734-d682-4d71-983e-d6ec3f16059f}
	License ID:		{178676e3-4199-4a57-8312-abb0e10d6921}
	License Version:	2.0
	Date/Time of Issue:     2007-02-28T18:00:36Z
	Certificate: size = 146
		Length:		146
		Version:	2.0
		OEM ID:		"FSC   "
		Exponent:       65537
		Modulus: size = 128
                        Value:  0x6189C3AEC59A2E3E4C5360EF41A54CA4F2716C226674A4FEE1874FA75B58F6D661086DCE98A2BB8E9A973B01D6C227880F073BCED021303E53B902735AC617CD2D39D56923353E6593BC1D716CD1761766814B13357FAD13D284CDCFDCFEAA010A74FAEBABB20E4687E230EE83AFC38DBAA78A96D4AD8C298B41DB764CCEBDD7
	Digest: size = 20
		SHA-1 Hash:     0x1C48EA2A96492540B27CA7B290B123BBDEEC66B0
	Signature: size = 256
		Value:		0x9E445CA9DD2FED92C4DB977FAEBA28C9591517F70AA82ED443023F5137326897599820AE239DB2CD1560A93D373E66AF4B74A78D9F59427F2418B7863C27A61ED4C4294DE272BCB6AB7302A1831CD728C2DEE6171AEB45FD58F8A757D0B5FC299DEF3EFBCCB97DF4ABCCFAD6675F56594105744ED587D903FC9982B70D7C1EB7DDC67176EDDE33F785AEA998625ECCC631EF539C80847DACE836902980B2EF7C926F69E7014DE999CE0F5D4AFD273F7901118B4D3CE47AADE22E0AC1771C93E751192DF7D529EEA8DC683E93CD52687E35878BE340DF1B7F6159C52AADB2FAA008C5F282AEF78222D0F4FB62F88CEB546AAE80AE66552E71F56F0F6CF47AAA3E
	Modulus: size = 256
		Value:		0xB28B599FEC3D8EE28F7FB6CC3BDACD16B881FB5D2FFEDF5BA3F5D61BEAF3A036F0FEE17820D679AC64488AD8884D8FDB238AC0364BF8679846FFC57118C6EABEA71A5C9AA744575AED7023826D73F709205F547F776B572D451440FD09D57B926E0CD1F3D4FF9699DCE6AD8276FCBB1AFDA966F03349E2CEA689D773C277CCE16BD08517046A6B5CA9DE9959358890459F24069561B75284A976517489C8414303F1FCF8284DB719B00EC683AD811B03F1FEE0C0DD9830A30ACF951C1F2D500EEAA13DC4F26A45975115F3C76DD423A75600AB6EF073A713CF9B0F493075A49E0BF4C0FE369BC78F638C655E7E2C9F9BC596D3AA13DCAF30A9EDC924C83EC7CF
	Exponent: size = 3
		Value:		0x010001

'SLIC' 'ACPI' table: size = 374, checksum correct
	Signature:      "SLIC"
	Length:		374
	Revision:       0x01
	Checksum:       0xD2
	OEM ID:		"FSC   "
	OEM Table ID:   "PC      "
	OEM Revision:   0x06040000
	Creator ID:     " LTP"
	Creator Rev.:   0x00000000
CSP Name: Microsoft Enhanced RSA and AES Cryptographic Provider
RSA Public Key Algorithm: OID = 1.2.840.113549.1.1.1 (RSA)
RSA Public Key 'Magic Number': "RSA1"
RSA Public Key Bits: 1024
RSA Public Key Exponent: 65537
'Windows' Marker Hash Algorithm: OID = 
		Marker Check:   OK
		Marker String:  "WINDOWS "
		Marker Version: 2.1
		OEM Activation: 2.0
		OEM ID:		"FSC   "
		OEM Table ID:   "PC      "

'SLIC' 'ACPI' table matches 'Certificate' from XrML digital license 'C:\Windows\System32\OEM\FUJITSU_SIEMENS_COMPUTERS_GMBH.XRM-MS'

Downloads

The console application is available in two functional identical forms: SLICHECK.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and SLICHECK.COM, a small form without these extras.

Implementation and Build Details

SLIC ACPI Table & XrML Digital License Decoder is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows Server 2003 and newer versions of Windows NT as well as Windows PE 1.5 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application SLIC ACPI Table & XrML Digital License Decoder from the source presented hereafter.
  1. Create the text file SLICHECK.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <wincrypt.h>
    #include <shellapi.h>
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    typedef	struct	_slic		// 'Software License Internal Certificate' table
    {
    	DWORD	Signature;	// "SLIC" = 0x43494C53 = 'CILS'
    	DWORD	Length;		// size of entire SLIC table: 0x00000176
    	BYTE	Revision;
    	BYTE	Checksum;	// checksum of entire SLIC table
    	CHAR	OEMId[6];	// OEM identification
    	CHAR	OEMTableId[8];
    	DWORD	OEMRevision;
    	CHAR	CreatorId[4];	// creator identification
    	DWORD	CreatorRevision;
    
    	DWORD	RSAType;	// RSA public key substructure: 0x00000000
    	DWORD	RSALength;	// size of RSA public key substructure: 0x0000009C
    	// the 4 fields following next form a BLOBHEADER alias PUBLICKEYSTRUC structure
    	BYTE	RSAKeyType;	// RSA public key: 0x06 = PUBLICKEYBLOB
    	BYTE	RSABlobVersion;	// blob version: 0x02 = CUR_BLOB_VERSION
    	WORD	RSAReserved;	// 0x0000
    	ALG_ID	RSAAlgId;	// algorithm id: 0x00002400 = CALG_RSA_SIGN
    	// the 3 fields following next form a RSAPUBKEY structure
    	DWORD	RSAMagic;	// magic number: "RSA1" = 0x31415352 = '1ASR'
    	DWORD	RSABits;	// bits in modulus: 0x00000400 = sizeof(RSAModulus) * 8
    	DWORD	RSAExponent;	// exponent: 0x00010001 = 65537
    	BYTE	RSAModulus[128];// modulus (1024 bits)
    
    	DWORD	SLSType;	// marker substructure: 0x00000001
    	DWORD	SLSLength;	// size of marker substructure: 0x000000B6
    				// the 7 fields following next form the 'message';
    				//  its SHA-256 hash must be verified against
    				//   the 'signature' using the RSA public key!
    	DWORD	SLSActivation;	// OEM activation version: 0x00020000
    	CHAR	SLSOEMId[6];	// OEM identification
    	CHAR	SLSOEMTableId[8];
    	CHAR	SLSMarker[8];	// marker: "WINDOWS "
    	WORD	SLSMarkerLow;	// marker version, low word
    	WORD	SLSMarkerHigh;	// marker version, high word
    	BYTE	SLSReserved[16];
    	BYTE	SLSSignature[128];
    } SLIC;
    
    // XrML signature is valid if RSA-signed SHA-1 hash of canonicalized
    // content of node '<SignedInfo>' matches base64-decoded content
    // of node '<SignatureValue>'
    
    // XrML content is valid if SHA-1 hash of result of transforms
    // from node '<Signature/SignedInfo/Reference/Transforms>'
    // (licenseTransform and canonicalization) applied to entire XrML
    // content matches base64-decoded content of node
    // '<Signature/SignedInfo/Reference/DigestValue>'
    
    typedef	struct	_xrm_ms		// 'XrML digital license' (2731 bytes)
    {
    	CHAR	Node0[sizeof("<?xml version=\"1.0\" encoding=\"utf-8\"?>") - 1];
    	CHAR	Node1[sizeof("<r:license xmlns:r=\"urn:mpeg:mpeg21:2003:01-REL-R-NS\" licenseId=\"{18e64a2e-ab21-4b1b-9603-b7f25a436d2b}\" xmlns:sx=\"urn:mpeg:mpeg21:2003:01-REL-SX-NS\" xmlns:mx=\"urn:mpeg:mpeg21:2003:01-REL-MX-NS\" xmlns:sl=\"http://www.microsoft.com/DRM/XrML2/SL/v2\" xmlns:tm=\"http://www.microsoft.com/DRM/XrML2/TM/v2\">") - 1];
    	CHAR	Node2[sizeof("<r:title>") - 1];
    	CHAR	Title[sizeof("OEM Certificate") - 1];
    	CHAR	Node3[sizeof("</r:title>") - 1];
    	CHAR	Node4[sizeof("<r:grant>") - 1];
    	CHAR	Node5[sizeof("<sl:binding>") - 1];
    	CHAR	Node6[sizeof("<sl:data Algorithm=\"msft:rm/algorithm/bios/4.0\">") - 1];
    	CHAR	Certificate[sizeof("kgAAAAAAAgBGVUogICABAAEA66gIyLycU7jg4KrgkAjaWJaUhwzjNngUw7lB1kGft0SVrTilj7SCdA2t4PzYRfQqwsIP/sm3x07DeppgPIvW0c59I2YUpv7bwW0Vv+R72/GEKIyHB6oKdeViEdoi0Cot5fNZlU05WPDF97Il9UmQGXfER1Lp9y6pxMdbGlV7K8Q=") - 1];
    	CHAR	Node7[sizeof("</sl:data>") - 1];
    	CHAR	Node8[sizeof("</sl:binding>") - 1];
    	CHAR	Node9[sizeof("<r:possessProperty/>") - 1];
    	CHAR	Node10[sizeof("<sx:propertyUri definition=\"trustedOem\"/>") - 1];
    	CHAR	Node11[sizeof("</r:grant>") - 1];
    	CHAR	Node12[sizeof("<r:issuer>") - 1];
    	CHAR	Node13[sizeof("<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">") - 1];
    	CHAR	Node14[sizeof("<SignedInfo>") - 1];
    	CHAR	Node15[sizeof("<CanonicalizationMethod Algorithm=\"http://www.microsoft.com/xrml/lwc14n\"/>") - 1];
    	CHAR	Node16[sizeof("<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>") - 1];
    	CHAR	Node17[sizeof("<Reference>") - 1];
    	CHAR	Node18[sizeof("<Transforms>") - 1];
    	CHAR	Node19[sizeof("<Transform Algorithm=\"urn:mpeg:mpeg21:2003:01-REL-R-NS:licenseTransform\"/>") - 1];
    	CHAR	Node20[sizeof("<Transform Algorithm=\"http://www.microsoft.com/xrml/lwc14n\"/>") - 1];
    	CHAR	Node21[sizeof("</Transforms>") - 1];
    	CHAR	Node22[sizeof("<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>") - 1];
    	CHAR	Node23[sizeof("<DigestValue>") - 1];
    	CHAR	Digest[sizeof("jvrnrEHqfem3NAqRDvCSGr7fz2U=") - 1];
    	CHAR	Node24[sizeof("</DigestValue>") - 1];
    	CHAR	Node25[sizeof("</Reference>") - 1];
    	CHAR	Node26[sizeof("</SignedInfo>") - 1];
    	CHAR	Node27[sizeof("<SignatureValue>") - 1];
    	CHAR	Signature[sizeof("KI3JpD6J+cKzPye4OCf0azsorDt4a269v9r9K6HTM3lLwWzhclyskr/1j1nf25ELXmqthBR050lAQ1/RD+e+i+rWFoELDlYnnGgChnR//O45T/PpHHh6Sg4SBrteHPT6rasHD73KDihI04UyZj+Xq8pNduqPrJBHJfjvWfSq2nAA5GWTt7ke2jCmVFSshW3Ax5R5SGmXAeBWujhXBBUfkJ+txOMdPYRbdGRR1WWKxOmhVH9dovWB1OzuH8TadpkTDUKD2LLfw4fsBZRx3lgWw9yuB36LOJLYHzeda9sQSbZTHEDIgXQkkUTXI6cYQevhM/asKkR1SU9bHQp3Y0MKiA==") - 1];
    	CHAR	Node28[sizeof("</SignatureValue>") - 1];
    	CHAR	Node29[sizeof("<KeyInfo>") - 1];
    	CHAR	Node30[sizeof("<KeyValue>") - 1];
    	CHAR	Node31[sizeof("<RSAKeyValue>") - 1];
    	CHAR	Node32[sizeof("<Modulus>") - 1];
    	CHAR	Modulus[sizeof("sotZn+w9juKPf7bMO9rNFriB+10v/t9bo/XWG+rzoDbw/uF4INZ5rGRIitiITY/bI4rANkv4Z5hG/8VxGMbqvqcaXJqnRFda7XAjgm1z9wkgX1R/d2tXLUUUQP0J1XuSbgzR89T/lpnc5q2Cdvy7Gv2pZvAzSeLOponXc8J3zOFr0IUXBGprXKnemVk1iJBFnyQGlWG3UoSpdlF0ichBQwPx/PgoTbcZsA7Gg62BGwPx/uDA3ZgwowrPlRwfLVAO6qE9xPJqRZdRFfPHbdQjp1YAq27wc6cTz5sPSTB1pJ4L9MD+NpvHj2OMZV5+LJ+bxZbTqhPcrzCp7ckkyD7Hzw==") - 1];
    	CHAR	Node33[sizeof("</Modulus>") - 1];
    	CHAR	Node34[sizeof("<Exponent>") - 1];
    	CHAR	Exponent[sizeof("AQAB") - 1];
    	CHAR	Node35[sizeof("</Exponent>") - 1];
    	CHAR	Node36[sizeof("</RSAKeyValue>") - 1];
    	CHAR	Node37[sizeof("</KeyValue>") - 1];
    	CHAR	Node38[sizeof("</KeyInfo>") - 1];
    	CHAR	Node39[sizeof("</Signature>") - 1];
    	CHAR	Node40[sizeof("<r:details>") - 1];
    	CHAR	Node41[sizeof("<r:timeOfIssue>") - 1];
    	CHAR	TimeOfIssue[sizeof("2006-06-17T18:21:10Z") - 1];
    	CHAR	Node42[sizeof("</r:timeOfIssue>") - 1];
    	CHAR	Node43[sizeof("</r:details>") - 1];
    	CHAR	Node44[sizeof("</r:issuer>") - 1];
    	CHAR	Node45[sizeof("<r:otherInfo xmlns:r=\"urn:mpeg:mpeg21:2003:01-REL-R-NS\">") - 1];
    	CHAR	Node46[sizeof("<tm:infoTables xmlns:tm=\"http://www.microsoft.com/DRM/XrML2/TM/v2\">") - 1];
    	CHAR	Node47[sizeof("<tm:infoList tag=\"#global\">") - 1];
    	CHAR	Node48[sizeof("<tm:infoStr name=\"applicationId\">") - 1];
    	CHAR	ApplicationId[sizeof("{55c92734-d682-4d71-983e-d6ec3f16059f}") - 1];
    	CHAR	Node49[sizeof("</tm:infoStr>") - 1];
    	CHAR	Node50[sizeof("<tm:infoStr name=\"licenseCategory\">") - 1];
    	CHAR	LicenseCategory[sizeof("msft:sl/PPD") - 1];
    	CHAR	Node51[sizeof("</tm:infoStr>") - 1];
    	CHAR	Node52[sizeof("<tm:infoStr name=\"licenseType\">") - 1];
    	CHAR	LicenseType[sizeof("msft:sl/OEMCERT") - 1];
    	CHAR	Node53[sizeof("</tm:infoStr>") - 1];
    	CHAR	Node54[sizeof("<tm:infoStr name=\"licenseVersion\">") - 1];
    	CHAR	LicenseVersion[sizeof("2.0") - 1];
    	CHAR	Node55[sizeof("</tm:infoStr>") - 1];
    	CHAR	Node56[sizeof("<tm:infoStr name=\"licensorUrl\">") - 1];
    	CHAR	LicensorUrl[sizeof("http://licensing.microsoft.com") - 1];
    	CHAR	Node57[sizeof("</tm:infoStr>") - 1];
    	CHAR	Node58[sizeof("</tm:infoList>") - 1];
    	CHAR	Node59[sizeof("</tm:infoTables>") - 1];
    	CHAR	Node60[sizeof("</r:otherInfo>") - 1];
    	CHAR	Node61[sizeof("</r:license>") - 1];
    } XRM_MS;
    
    #pragma pack(push, 1)
    
    typedef	struct	_certificate	// decoded 'Certificate'
    {
    	DWORD	length;		// length of entire structure: 0x00000092
    	DWORD	version;	// windows marker version: 0x00020000
    	CHAR	oemid[6];	// OEM identification
    	DWORD	exponent;	// RSA public key exponent: 0x00010001
    	BYTE	modulus[128];	// RSA public key modulus
    } CERTIFICATE;
    
    #pragma pack(pop)
    
    const	ALG_ID	aiHash = CALG_SHA_256;
    
    __declspec(noreturn)
    __declspec(safebuffers)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    #ifdef VERBOSE
    	CCRYPT_OID_INFO	*lpOIDInfo;
    
    	BYTE	cbProvider[128];
    	DWORD	dwProvider = sizeof(cbProvider);
    #endif
    	HCRYPTPROV	hProvider;
    	HCRYPTKEY	hPublicKey;
    	HCRYPTHASH	hHash;
    	CERTIFICATE	cbCertificate;
    
    	DWORD	dwCertificate = sizeof(cbCertificate);
    	BYTE	cbDigest[20];	// SHA-1
    	DWORD	dwDigest = sizeof(cbDigest);
    	BYTE	cbSignature[256];
    	DWORD	dwSignature = sizeof(cbSignature);
    	BYTE	cbModulus[256];
    	DWORD	dwModulus = sizeof(cbModulus);
    	BYTE	cbExponent[3];
    	DWORD	dwExponent = sizeof(cbExponent);
    	SLIC	cbSLIC;
    	DWORD	dwSLIC;
    	BYTE	cbTemp;
    	DWORD	dwTemp;
    	DWORD	dwLeft;
    	DWORD	dwRight;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	BOOL	bMatch = FALSE;
    
    	FILETIME	ftXrML;
    	SYSTEMTIME	stXrML;
    
    	XRM_MS	cbXrML;
    	CHAR	szXrML[sizeof("2006-06-17T18:21:10Z")];
    	DWORD	dwXrML;
    	HANDLE	hXrML;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments != 2)
    				PrintConsole(hConsole,
    				             L"No argument: a single (absolute or relative) path name of an XrML (*.xrm-ms)\n"
    				             L"             digital license file must be given!\n");
    			else
    			{
    				hXrML = CreateFile(lpArguments[1],
    				                   FILE_READ_DATA,
    				                   FILE_SHARE_READ,
    				                   (LPSECURITY_ATTRIBUTES) NULL,
    				                   OPEN_EXISTING,
    				                   FILE_ATTRIBUTE_NORMAL,
    				                   (HANDLE) NULL);
    
    				if (hXrML == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"CreateFile() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					if (!ReadFile(hXrML,
    					              &cbXrML,
    					              sizeof(cbXrML) + 1,
    					              &dwXrML,
    					              (LPOVERLAPPED) NULL))
    						PrintConsole(hConsole,
    						             L"ReadFile() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    						if ((dwXrML != sizeof(cbXrML))
    						 || memcmp("<?xml version=\"1.0\" encoding=\"utf-8\"?>", cbXrML.Node0, sizeof(cbXrML.Node0))
    						 || memcmp("<sx:propertyUri definition=\"trustedOem\"/>", cbXrML.Node10, sizeof(cbXrML.Node10))
    						 || memcmp("OEM Certificate", cbXrML.Title, sizeof(cbXrML.Title))
    						 || memcmp("msft:sl/PPD", cbXrML.LicenseCategory, sizeof(cbXrML.LicenseCategory))
    						 || memcmp("msft:sl/OEMCERT", cbXrML.LicenseType, sizeof(cbXrML.LicenseType))
    						 || memcmp("2.0", cbXrML.LicenseVersion, sizeof(cbXrML.LicenseVersion))
    						 || memcmp("http://licensing.microsoft.com", cbXrML.LicensorUrl, sizeof(cbXrML.LicensorUrl)))
    							PrintConsole(hConsole,
    							             L"File \'%ls\' contains no XrML digital license!\n",
    							             lpArguments[1]);
    						else
    						{
    							dwError = ERROR_SUCCESS;
    
    							if (!GetFileTime(hXrML,
    							                 (LPFILETIME) NULL,
    							                 (LPFILETIME) NULL,
    							                 &ftXrML))
    								PrintConsole(hConsole,
    								             L"GetFileTime() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    								if (!FileTimeToSystemTime(&ftXrML,
    								                          &stXrML))
    									PrintConsole(hConsole,
    									             L"FileTimeToSystemTime() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    									if (wsprintfA(szXrML,
    									              "%04hu-%02hu-%02huT%02hu:%02hu:%02huZ",
    									              stXrML.wYear,
    									              stXrML.wMonth,
    									              stXrML.wDay,
    									              stXrML.wHour,
    									              stXrML.wMinute,
    									              stXrML.wSecond) != sizeof(cbXrML.TimeOfIssue))
    										PrintConsole(hConsole,
    									                     L"wsprintf() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    										if (memcmp(szXrML, cbXrML.TimeOfIssue, sizeof(cbXrML.TimeOfIssue)))
    											PrintConsole(hConsole,
    											             L"Timestamp \'%hs\' of XrML digital license file \'%ls\' differs from time of issue \'%.20hs\'!\n",
    											             szXrML, lpArguments[1], cbXrML.TimeOfIssue);
    
    							PrintConsole(hConsole,
    							             L"XrML digital license file \'%ls\': size = %lu\n"
    							             L"\tApplication ID:\t\t%.38hs\n"
    							             L"\tLicense ID:\t\t%.38hs\n"
    							             L"\tLicense Version:\t%.3hs\n"
    							             L"\tDate/Time of Issue:\t%.20hs\n",
    							             lpArguments[1], dwXrML,
    							             cbXrML.ApplicationId,
    							             cbXrML.Node1 + 65,
    							             cbXrML.LicenseVersion,
    							             cbXrML.TimeOfIssue);
    
    							if (!CryptStringToBinaryA(cbXrML.Certificate,
    							                          sizeof(cbXrML.Certificate),
    							                          CRYPT_STRING_BASE64,
    							                          (LPBYTE) &cbCertificate,
    							                          &dwCertificate,
    							                          (LPDWORD) NULL,
    							                          (LPDWORD) NULL))
    								PrintConsole(hConsole,
    								             L"CryptStringToBinary() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								PrintConsole(hConsole,
    								             L"\tCertificate: size = %lu\n"
    								             L"\t\tLength:\t\t%lu\n"
    								             L"\t\tVersion:\t%hu.%hu\n"
    								             L"\t\tOEM ID:\t\t\"%.6hs\"\n"
    								             L"\t\tExponent:\t%lu\n"
    								             L"\t\tModulus: size = %lu"
    								             L"\t\t\tValue:\t0x",
    								             dwCertificate,
    								             cbCertificate.length,
    								             HIWORD(cbCertificate.version), LOWORD(cbCertificate.version),
    								             cbCertificate.oemid,
    								             cbCertificate.exponent,
    								             sizeof(cbCertificate.modulus));
    
    								for (dwTemp = 0; dwTemp < sizeof(cbCertificate.modulus); dwTemp++)
    									PrintConsole(hConsole,
    									             L"%02X",
    									             cbCertificate.modulus[dwTemp]);
    
    								PrintConsole(hConsole,
    								             L"\n");
    							}
    
    							if (!CryptStringToBinaryA(cbXrML.Digest,
    							                         sizeof(cbXrML.Digest),
    							                         CRYPT_STRING_BASE64,
    							                         cbDigest,
    							                         &dwDigest,
    							                         (LPDWORD) NULL,
    							                         (LPDWORD) NULL))
    								PrintConsole(hConsole,
    								             L"CryptStringToBinary() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								PrintConsole(hConsole,
    								             L"\tDigest: size = %lu\n"
    								             L"\t\tSHA-1 Hash:\t0x",
    								             dwDigest);
    
    								for (dwTemp = 0; dwTemp < dwDigest; dwTemp++)
    									PrintConsole(hConsole,
    									             L"%02X",
    									             cbDigest[dwTemp]);
    
    								PrintConsole(hConsole,
    								             L"\n");
    							}
    
    							if (!CryptStringToBinaryA(cbXrML.Signature,
    							                          sizeof(cbXrML.Signature),
    							                          CRYPT_STRING_BASE64,
    							                          cbSignature,
    							                          &dwSignature,
    							                          (LPDWORD) NULL,
    							                          (LPDWORD) NULL))
    								PrintConsole(hConsole,
    								             L"CryptStringToBinary() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								PrintConsole(hConsole,
    								             L"\tSignature: size = %lu\n"
    								             L"\t\tValue:\t\t0x",
    								             dwSignature);
    
    								for (dwTemp = 0; dwTemp < dwSignature; dwTemp++)
    									PrintConsole(hConsole,
    									             L"%02X",
    									             cbSignature[dwTemp]);
    
    								PrintConsole(hConsole,
    								             L"\n");
    							}
    
    							if (!CryptStringToBinaryA(cbXrML.Modulus,
    							                          sizeof(cbXrML.Modulus),
    							                          CRYPT_STRING_BASE64,
    							                          cbModulus,
    							                          &dwModulus,
    							                          (LPDWORD) NULL,
    							                          (LPDWORD) NULL))
    								PrintConsole(hConsole,
    								             L"CryptStringToBinary() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								PrintConsole(hConsole,
    								             L"\tModulus: size = %lu\n"
    								             L"\t\tValue:\t\t0x",
    								             dwModulus);
    
    								for (dwTemp = 0; dwTemp < dwModulus; dwTemp++)
    									PrintConsole(hConsole,
    									             L"%02X",
    									             cbModulus[dwTemp]);
    
    								PrintConsole(hConsole,
    								             L"\n");
    							}
    
    							if (!CryptStringToBinaryA(cbXrML.Exponent,
    							                          sizeof(cbXrML.Exponent),
    							                          CRYPT_STRING_BASE64,
    							                          cbExponent,
    							                          &dwExponent,
    							                          (LPDWORD) NULL,
    							                          (LPDWORD) NULL))
    								PrintConsole(hConsole,
    								             L"CryptStringToBinary() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								PrintConsole(hConsole,
    								             L"\tExponent: size = %lu\n"
    								             L"\t\tValue:\t\t0x\n",
    								             dwExponent);
    
    								for (dwTemp = 0; dwTemp < dwExponent; dwTemp++)
    									PrintConsole(hConsole,
    									             L"%02X",
    									             cbExponent[dwTemp]);
    
    								PrintConsole(hConsole,
    								             L"\n");
    							}
    
    							dwSLIC = GetSystemFirmwareTable('ACPI', 'CILS', &cbSLIC, sizeof(cbSLIC));
    
    							if (dwSLIC == 0)
    							{
    								dwError = GetLastError();
    
    								if (dwError != ERROR_NOT_FOUND)
    									PrintConsole(hConsole,
    									             L"GetSystemFirmwareTable() returned error %lu\n",
    									             dwError);
    								else
    									PrintConsole(hConsole,
    									             L"\'SLIC\' \'ACPI\' table not present!\n");
    							}
    							else
    							{
    								for (cbTemp = 0, dwTemp = cbSLIC.Length; dwTemp != 0; cbTemp += ((LPBYTE) &cbSLIC)[--dwTemp])
    									continue;
    
    								PrintConsole(hConsole,
    								             L"\n"
    								             L"\'SLIC\' \'ACPI\' table: size = %lu, checksum %ls\n"
    								             L"\tSignature:\t\"%.4hs\"\n"
    								             L"\tLength:\t\t%lu\n"
    								             L"\tRevision:\t0x%02X\n"
    								             L"\tChecksum:\t0x%02X\n"
    								             L"\tOEM ID:\t\t\"%.6hs\"\n"
    								             L"\tOEM Table ID:\t\"%.8hs\"\n"
    								             L"\tOEM Revision:\t0x%08X\n"
    								             L"\tCreator ID:\t\"%.4hs\"\n"
    								             L"\tCreator Rev.:\t0x%08X\n",
    								             dwSLIC, cbTemp ? L"wrong" : L"correct",
    								             &cbSLIC.Signature,
    								             cbSLIC.Length,
    								             cbSLIC.Revision,
    								             cbSLIC.Checksum,
    								             cbSLIC.OEMId,
    								             cbSLIC.OEMTableId,
    								             cbSLIC.OEMRevision,
    								             cbSLIC.CreatorId,
    								             cbSLIC.CreatorRevision);
    
    								if ((cbSLIC.RSAType != 0)
    								 || (cbSLIC.RSALength != 156)
    								 || (cbSLIC.SLSType != 1)
    								 || (cbSLIC.SLSLength != 182))
    									PrintConsole(hConsole,
    									             L"\'SLIC\' \'ACPI\' table has unknown layout!\n");
    								else
    								{	// Transpose signature from 'big endian' to 'little endian' form
    
    									dwLeft = ~0UL;
    									dwRight = sizeof(cbSLIC.SLSSignature);
    
    									while (++dwLeft < --dwRight)
    									{
    										cbTemp = cbSLIC.SLSSignature[dwLeft];
    										cbSLIC.SLSSignature[dwLeft] = cbSLIC.SLSSignature[dwRight];
    										cbSLIC.SLSSignature[dwRight] = cbTemp;
    									}
    
    									if (!CryptAcquireContext(&hProvider,
    									                         (LPCWSTR) NULL,
    									                         (LPCWSTR) NULL,
    									                         PROV_RSA_AES,
    									                         CRYPT_VERIFYCONTEXT))
    										PrintConsole(hConsole,
    										             L"CryptAcquireContext() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    										if (!CryptImportKey(hProvider,
    										                    &cbSLIC.RSAKeyType,
    										                    cbSLIC.RSAModulus + sizeof(cbSLIC.RSAModulus) - &cbSLIC.RSAKeyType,
    										                    0,
    										                    0,
    										                    &hPublicKey))
    											PrintConsole(hConsole,
    											             L"CryptImportKey() returned error %lu\n",
    											             dwError = GetLastError());
    										else
    										{
    #ifdef VERBOSE
    											if (!CryptGetProvParam(hProvider,
    											                       PP_NAME,
    											                       cbProvider,
    											                       &dwProvider,
    											                       0))
    												PrintConsole(hConsole,
    												             L"CryptGetProvParam() returned error %lu\n",
    												             dwError = GetLastError());
    											else
    												PrintConsole(hConsole,
    												             L"CSP Name: %hs\n",
    												             cbProvider);
    
    											lpOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
    											                             &cbSLIC.RSAAlgId,
    											                             0);
    
    											if (lpOIDInfo != NULL)
    												PrintConsole(hConsole,
    												             L"RSA Public Key Algorithm: OID = %hs (%ls)\n",
    												             lpOIDInfo->pszOID, lpOIDInfo->pwszName);
    											else
    												PrintConsole(hConsole,
    												             L"RSA Public Key Algorithm: OID = %hs\n",
    												             CertAlgIdToOID(cbSLIC.RSAAlgId));
    
    											PrintConsole(hConsole,
    											             L"RSA Public Key \'Magic Number\': \"%.4hs\"\n"
    											             L"RSA Public Key Bits: %lu\n"
    											             L"RSA Public Key Exponent: %lu\n",
    											             &cbSLIC.RSAMagic,
    											             cbSLIC.RSABits,
    											             cbSLIC.RSAExponent);
    
    											lpOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
    											                             &aiHash,
    											                             0);
    
    											if (lpOIDInfo != NULL)
    												PrintConsole(hConsole,
    												             L"\'Windows\' Marker Signature Hash Algorithm: OID = %hs (%ls)\n",
    												             lpOIDInfo->pszOID, lpOIDInfo->pwszName);
    											else
    												PrintConsole(hConsole,
    												             L"\'Windows\' Marker Hash Algorithm: OID = %hs\n",
    												             CertAlgIdToOID(aiHash));
    #endif
    											if (!CryptCreateHash(hProvider,
    											                     aiHash,
    											                     0,
    											                     0,
    											                     &hHash))
    												PrintConsole(hConsole,
    												             L"CryptCreateHash() returned error %lu\n",
    												             dwError = GetLastError());
    											else
    											{
    												if (!CryptHashData(hHash,
    												                   (LPBYTE) &cbSLIC.SLSActivation,
    												                   cbSLIC.SLSSignature - (LPBYTE) &cbSLIC.SLSActivation,
    												                   0))
    													PrintConsole(hConsole,
    													             L"CryptHashData() returned error %lu\n",
    													             dwError = GetLastError());
    												else
    													if (!CryptVerifySignature(hHash,
    													                          cbSLIC.SLSSignature,
    													                          sizeof(cbSLIC.SLSSignature),
    													                          hPublicKey,
    													                          (LPCWSTR) NULL,
    													                          0))
    														PrintConsole(hConsole,
    														             L"CryptVerifySignature() returned error %lu\n",
    														             dwError = GetLastError());
    													else
    														bMatch = TRUE;
    
    												if (!CryptDestroyHash(hHash))
    													PrintConsole(hConsole,
    													             L"CryptDestroyHash() returned error %lu\n",
    												                     GetLastError());
    											}
    
    											if (!CryptDestroyKey(hPublicKey))
    												PrintConsole(hConsole,
    												             L"CryptDestroyKey() returned error %lu\n",
    												             GetLastError());
    										}
    
    										if (!CryptReleaseContext(hProvider, 0))
    											PrintConsole(hConsole,
    											             L"CryptReleaseContext() returned error %lu\n",
    											             GetLastError());
    									}
    
    									PrintConsole(hConsole,
    									             L"\t\tMarker Check:\t%ls\n"
    									             L"\t\tMarker String:\t\"%.8hs\"\n"
    									             L"\t\tMarker Version:\t%hu.%hu\n"
    									             L"\t\tOEM Activation:\t%hu.%hu\n"
    									             L"\t\tOEM ID:\t\t\"%.6hs\"\n"
    									             L"\t\tOEM Table ID:\t\"%.8hs\"\n",
    									             bMatch ? L"OK" : L"ERROR",
    									             cbSLIC.SLSMarker,
    									             cbSLIC.SLSMarkerHigh, cbSLIC.SLSMarkerLow,
    									             HIWORD(cbSLIC.SLSActivation), LOWORD(cbSLIC.SLSActivation),
    									             cbSLIC.SLSOEMId,
    									             cbSLIC.SLSOEMTableId);
    								}
    
    								bMatch = (memcmp(cbSLIC.OEMId, cbCertificate.oemid, sizeof(cbCertificate.oemid)) == 0)
    								      && (cbSLIC.RSAExponent == cbCertificate.exponent)
    								      && (memcmp(cbSLIC.RSAModulus, cbCertificate.modulus, sizeof(cbCertificate.modulus)) == 0);
    
    								PrintConsole(hConsole,
    								             L"\n"
    								             L"\'SLIC\' \'ACPI\' table %ls \'Certificate\' from XrML digital license \'%ls\'\n",
    								             bMatch ? L"matches" : L"does not match", lpArguments[1]);
    							}
    						}
    
    					if (!CloseHandle(hXrML))
    						PrintConsole(hConsole,
    					                     L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file SLICHECK.C created in step 1., link the compiled object file SLICHECK.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.2 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /DVERBOSE /FeSLICHECK.COM SLICHECK.C ADVAPI32.LIB CRYPT32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE SLICHECK.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    SLICHECK.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Interactive SYSTEM Process Launcher

Purpose
Background Information
Synopsis
Demonstration
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Launch arbitrary applications under the NT AUTHORITY\SYSTEM alias LocalSystem account on the input desktop of the interactive window station of the current logon session.

Background Information

Windows’ initial user-mode process SMSS.exe, the Session Manager Subsystem, is started by the kernel as the only child of the (virtual) System Process with process identifier 4 and runs in Session 0 under the NT AUTHORITY\SYSTEM alias LocalSystem account with all privileges assigned. Its Access Token is protected by the Security Descriptor O:BAG:SYD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPRC;;;BA)S:AI(ML;;NW;;;SI) which allows members of the BUILTIN\Administrators group to assign it as primary token of a process, to duplicate it, to impersonate it in a thread and to query it.

Note: the BUILTIN\Administrators group has the privilege SeImpersonatePrivilege enabled by default!

Note: due to the mandatory integrity label, members of the BUILTIN\Administrators group can’t exercise their (implicit) Owner Right Write DAC from processes running with an Integrity Level lower than Mandatory Label\System Mandatory Level!

Synopsis

SYSIPHOS.COM [ ‹application› ] ‹quoted command line›
Note: the optional first argument is the absolute or relative path name of the application; when omitted, the first token of the then first and only argument, a properly quoted command line, is used as file name of the application and searched in the PATH.

Note: Interactive SYSTEM Process Launcher must be run elevated!

Note: Sysiphos should not be confused with the legendary Sisyphos (Ancient Greek: Σίσυφος) from Greek mythology!

Demonstration

SYSIPHOS.COM "CMD /D /K DIR /A \"%SystemDrive%\System Volume Information\""
SYSIPHOS.COM "%COMSPEC%" "CMD /D /K WHOAMI.EXE /ALL"
SYSIPHOS.COM "%SystemRoot%\REGEDIT.EXE /M"

Downloads

The console application is available in two functional identical forms: SYSIPHOS.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and SYSIPHOS.COM, a small form without these extras.

Implementation and Build Details

Interactive SYSTEM Process Launcher is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows Vista and newer versions of Windows NT as well as Windows PE 2.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Interactive SYSTEM Process Launcher from the source presented hereafter.
  1. Create the text file SYSIPHOS.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <userenv.h>
    #include <tlhelp32.h>
    #include <shellapi.h>
    
    #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE	3UL	// "SeAssignPrimaryTokenPrivilege"
    
    typedef	struct	_token_sid
    {
    	union
    	{
    		TOKEN_OWNER		Owner;
    		TOKEN_PRIMARY_GROUP	Group;
    	};
    
    	union
    	{
    		SID	Sid;
    		BYTE	Dummy[SECURITY_MAX_SID_SIZE];
    	};
    } TOKEN_SID;
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    const	TOKEN_PRIVILEGES	tpToken = {1, {SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0, SE_PRIVILEGE_ENABLED}};
    
    const	STARTUPINFO	si = {sizeof(si)};
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	TOKEN_SID	ts;
    	PROCESSENTRY32	pe /* = {sizeof(pe)} */;
    
    	PROCESS_INFORMATION	pi;
    
    	INT	nArguments;
    	LPWSTR	*lpArguments;
    	LPWSTR	lpBlock;
    	DWORD	dwToken;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwProcessId = 0;
    	DWORD	dwSessionId;
    	HANDLE	hSnapshot;
    	HANDLE	hToken;
    	HANDLE	hThread = GetCurrentThread();
    	HANDLE	hProcess = GetCurrentProcess();
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if ((nArguments < 2)
    			 || (*lpArguments[1] == L'\0')
    			 || (nArguments > 3))
    				PrintConsole(hConsole,
    				             L"Bad arguments: either a (properly quoted) command line\n"
    				             L"               or the (absolute or relative) path name of an application\n"
    				             L"               followed by a (properly quoted) command line must be given!\n");
    			else
    			{
    				hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    
    				if (hSnapshot == INVALID_HANDLE_VALUE)
    					PrintConsole(hConsole,
    					             L"CreateToolhelp32Snapshot() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					pe.dwSize = sizeof(pe);
    
    					if (!Process32First(hSnapshot, &pe))
    						PrintConsole(hConsole,
    						             L"Process32First() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    					{
    						do
    							if ((pe.th32ParentProcessID == 4)
    #if 0
    							 && (wcscmp(pe.szExeFile, L"smss.exe") == 0))
    #elif 0
    							 && (wmemcmp(pe.szExeFile, L"smss.exe", sizeof("smss.exe")) == 0))
    #else
    							 && (memcmp(pe.szExeFile, L"smss.exe", sizeof(L"smss.exe")) == 0))
    #endif
    								dwProcessId = pe.th32ProcessID;
    
    						while (Process32Next(hSnapshot, &pe));
    
    						dwError = GetLastError();
    
    						if (dwError != ERROR_NO_MORE_FILES)
    							PrintConsole(hConsole,
    							             L"Process32Next() returned error %lu\n",
    							             dwError);
    					}
    
    					if (!CloseHandle(hSnapshot))
    						PrintConsole(hConsole,
    						             L"CloseHandle() returned error %lu\n",
    						             GetLastError());
    				}
    
    				if (dwProcessId == 0)
    				{
    					PrintConsole(hConsole,
    					             L"Process \'SMSS.exe\' not found!\n");
    
    					dwError = ERROR_NOT_FOUND;
    				}
    				else
    				{
    					if (!OpenProcessToken(hProcess,
    					                      TOKEN_QUERY,
    					                      &hToken))
    						PrintConsole(hConsole,
    						             L"OpenProcessToken() returned error %lu\n",
    						             dwError = GetLastError());
    					else
    					{
    						if (!GetTokenInformation(hToken,
    						                         TokenSessionId,
    						                         &dwSessionId,
    						                         sizeof(dwSessionId),
    						                         &dwToken))
    							PrintConsole(hConsole,
    							             L"GetTokenInformation() returned error %lu\n",
    							             GetLastError());
    
    						if (!CloseHandle(hToken))
    							PrintConsole(hConsole,
    							             L"CloseHandle() returned error %lu\n",
    							             GetLastError());
    
    						hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
    						                       FALSE,
    						                       dwProcessId);
    
    						if (hProcess == NULL)
    							PrintConsole(hConsole,
    							             L"OpenProcess() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							if (!OpenProcessToken(hProcess,
    							                      TOKEN_DUPLICATE | TOKEN_QUERY,
    							                      &hToken))
    								PrintConsole(hConsole,
    								             L"OpenProcessToken() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								if (!ImpersonateLoggedOnUser(hToken))
    									PrintConsole(hConsole,
    									             L"ImpersonateLoggedOnUser() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    								{
    									if (!CloseHandle(hToken))
    										PrintConsole(hConsole,
    										             L"CloseHandle() returned error %lu\n",
    										             GetLastError());
    
    									if (!OpenThreadToken(hThread,
    #if 0 // BUG: SetTokenInformation() for TokenSessionId fails with
          //      ERROR_ACCESS_DENIED despite TOKEN_ADJUST_SESSIONID!
    									                     TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY,
    #else
    									                     TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY,
    #endif
    									                     FALSE,
    									                     &hToken))
    										PrintConsole(hConsole,
    										             L"OpenThreadToken() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    										if (!GetTokenInformation(hToken,
    										                         TokenPrimaryGroup,
    										                         &ts,
    										                         sizeof(ts),
    										                         &dwToken))
    											PrintConsole(hConsole,
    											             L"GetTokenInformation() returned error %lu\n",
    											             GetLastError());
    										else
    											if (!SetTokenInformation(hToken,
    											                         TokenOwner,
    											                         &ts,
    											                         dwToken))
    												PrintConsole(hConsole,
    												             L"SetTokenInformation() returned error %lu\n",
    												             GetLastError());
    
    										if (!SetTokenInformation(hToken,
    										                         TokenSessionId,
    										                         &dwSessionId,
    										                         sizeof(dwSessionId)))
    											PrintConsole(hConsole,
    											             L"SetTokenInformation() returned error %lu\n",
    											             GetLastError());
    
    										AdjustTokenPrivileges(hToken,
    										                      FALSE,
    										                      &tpToken,
    										                      sizeof(tpToken),
    										                      (TOKEN_PRIVILEGES *) NULL,
    										                      (LPDWORD) NULL);
    
    										dwError = GetLastError();
    
    										if (dwError != ERROR_SUCCESS)
    											PrintConsole(hConsole,
    											             L"AdjustTokenPrivileges() returned error %lu\n",
    											             dwError);
    										else
    											if (!CreateEnvironmentBlock(&lpBlock, hToken, FALSE))
    												PrintConsole(hConsole,
    												             L"CreateEnvironmentBlock() returned error %lu\n",
    												             dwError = GetLastError());
    											else
    											{
    												if (!CreateProcessAsUser(hToken,
    												                         lpArguments[4 - nArguments],
    												                         lpArguments[nArguments - 1],
    												                         (LPSECURITY_ATTRIBUTES) NULL,
    												                         (LPSECURITY_ATTRIBUTES) NULL,
    												                         FALSE,
    												                         CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
    												                         lpBlock,
    												                         (LPCWSTR) NULL,
    												                         &si,
    												                         &pi))
    													PrintConsole(hConsole,
    													             L"CreateProcessAsUser() returned error %lu\n",
    													             dwError = GetLastError());
    												else
    												{
    #ifdef SYNCHRONOUS
    													if (WaitForSingleObject(pi.hThread, INFINITE) == WAIT_FAILED)
    														PrintConsole(hConsole,
    														             L"WaitForSingleObject() returned error %lu\n",
    														             dwError = GetLastError());
    #endif
    													if (!CloseHandle(pi.hThread))
    														PrintConsole(hConsole,
    														             L"CloseHandle() returned error %lu\n",
    														             GetLastError());
    #ifdef SYNCHRONOUS
    													if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED)
    														PrintConsole(hConsole,
    														             L"WaitForSingleObject() returned error %lu\n",
    														             dwError = GetLastError());
    #endif
    													if (!CloseHandle(pi.hProcess))
    														PrintConsole(hConsole,
    														             L"CloseHandle() returned error %lu\n",
    														             GetLastError());
    												}
    
    												if (!DestroyEnvironmentBlock(lpBlock))
    													PrintConsole(hConsole,
    													             L"DestroyEnvironmentBlock() returned error %lu\n",
    													             GetLastError());
    											}
    									}
    
    									if (!RevertToSelf())
    										PrintConsole(hConsole,
    										             L"RevertToSelf() returned error %lu\n",
    										             dwError = GetLastError());
    								}
    
    								if (!CloseHandle(hToken))
    									PrintConsole(hConsole,
    									             L"CloseHandle() returned error %lu\n",
    									             GetLastError());
    							}
    
    							if (!CloseHandle(hProcess))
    								PrintConsole(hConsole,
    								             L"CloseHandle() returned error %lu\n",
    								             GetLastError());
    						}
    					}
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file SYSIPHOS.C created in step 1., link the compiled object file SYSIPHOS.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:6.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeSYSIPHOS.COM SYSIPHOS.C ADVAPI32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE SYSIPHOS.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    SYSIPHOS.C
    SYSIPHOS.C(36) : warning C4201: nonstandard extension used : nameless struct/union
    SYSIPHOS.C(42) : warning C4201: nonstandard extension used : nameless struct/union
    SYSIPHOS.C(258) : warning C4706: warning C4090: 'function' : different 'const' qualifiers
    SYSIPHOS.C(285) : warning C4706: warning C4090: 'function' : different 'const' qualifiers
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Privilege Twiddler

Purpose
Background Information
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Enable, disable or remove privileges of the calling process.

Background Information

The TechNet articles User Rights and Configuring User Rights as well as the MSDN article Privileges provide background information.

Synopsis

TWIDDLER.COM { /ENABLE:‹privilege name› | /DISABLE:‹privilege name› | /REMOVE:‹privilege name› } …

Downloads

The console application is available in two functional identical forms: TWIDDLER.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and TWIDDLER.COM, a small form without these extras.

Implementation and Build Details

Privilege Twiddler is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application Privilege Twiddler from the source presented hereafter.
  1. Create the text file TWIDDLER.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <tlhelp32.h>
    #include <shellapi.h>
    
    #define SE_PRIVILEGE_DISABLED	0UL
    
    #define SE_MIN_WELL_KNOWN_PRIVILEGE			2UL
    #define SE_CREATE_TOKEN_PRIVILEGE			2UL	// "SeCreateTokenPrivilege"
    #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE			3UL	// "SeAssignPrimaryTokenPrivilege"
    #define SE_LOCK_MEMORY_PRIVILEGE			4UL	// "SeLockMemoryPrivilege"
    #define SE_INCREASE_QUOTA_PRIVILEGE			5UL	// "SeIncreaseQuotaPrivilege"
    //      SE_UNSOLICITED_INPUT_PRIVILEGE			6UL	// "SeUnsolicitedInputPrivilege"
    #define SE_MACHINE_ACCOUNT_PRIVILEGE			6UL	// "SeMachineAccountPrivilege"
    #define SE_TCB_PRIVILEGE				7UL	// "SeTcbPrivilege"
    #define SE_SECURITY_PRIVILEGE				8UL	// "SeSecurityPrivilege"
    #define SE_TAKE_OWNERSHIP_PRIVILEGE			9UL	// "SeTakeOwnershipPrivilege"
    #define SE_LOAD_DRIVER_PRIVILEGE			10UL	// "SeLoadDriverPrivilege"
    #define SE_SYSTEM_PROFILE_PRIVILEGE			11UL	// "SeSystemProfilePrivilege"
    #define SE_SYSTEMTIME_PRIVILEGE				12UL	// "SeSystemtimePrivilege"
    #define SE_PROF_SINGLE_PROCESS_PRIVILEGE		13UL	// "SeProfileSingleProcessPrivilege"
    #define SE_INC_BASE_PRIORITY_PRIVILEGE			14UL	// "SeIncreaseBasePriorityPrivilege"
    #define SE_CREATE_PAGEFILE_PRIVILEGE			15UL	// "SeCreatePagefilePrivilege"
    #define SE_CREATE_PERMANENT_PRIVILEGE			16UL	// "SeCreatePermanentPrivilege"
    #define SE_BACKUP_PRIVILEGE				17UL	// "SeBackupPrivilege"
    #define SE_RESTORE_PRIVILEGE				18UL	// "SeRestorePrivilege"
    #define SE_SHUTDOWN_PRIVILEGE				19UL	// "SeShutdownPrivilege"
    #define SE_DEBUG_PRIVILEGE				20UL	// "SeDebugPrivilege"
    #define SE_AUDIT_PRIVILEGE				21UL	// "SeAuditPrivilege"
    #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE			22UL	// "SeSystemEnvironmentPrivilege"
    #define SE_CHANGE_NOTIFY_PRIVILEGE			23UL	// "SeChangeNotifyPrivilege"
    #define SE_REMOTE_SHUTDOWN_PRIVILEGE			24UL	// "SeRemoteShutdownPrivilege"
    #define SE_UNDOCK_PRIVILEGE				25UL	// "SeUndockPrivilege"
    #define SE_SYNC_AGENT_PRIVILEGE				26UL	// "SeSyncAgentPrivilege"
    #define SE_ENABLE_DELEGATION_PRIVILEGE			27UL	// "SeEnableDelegationPrivilege"
    #define SE_MANAGE_VOLUME_PRIVILEGE			28UL	// "SeManageVolumePrivilege"
    #define SE_IMPERSONATE_PRIVILEGE			29UL	// "SeImpersonatePrivilege"
    #define SE_CREATE_GLOBAL_PRIVILEGE			30UL	// "SeCreateGlobalPrivilege"
    #define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE		31UL	// "SeTrustedCredManAccessPrivilege"
    #define SE_RELABEL_PRIVILEGE				32UL	// "SeRelabelPrivilege"
    #define SE_INCREASE_WORKING_SET_PRIVILEGE		33UL	// "SeIncreaseWorkingSetPrivilege"
    #define SE_TIME_ZONE_PRIVILEGE				34UL	// "SeTimeZonePrivilege"
    #define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE		35UL	// "SeCreateSymbolicLinkPrivilege"
    #define SE_DELEGATE_SESSION_USER_IMPERSONATE_PRIVILEGE	36UL	// "SeDelegateSessionUserImpersonatePrivilege"
    #define SE_MAX_WELL_KNOWN_PRIVILEGE			36UL
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	INT	nArgument = 1;
    	INT	nArguments;
    	LPWSTR	*lpArguments;
    	LPCWSTR	lpPrivilege;
    	WCHAR	szPrivilege[sizeof("SeDelegateSessionUserImpersonatePrivilege")];
    	DWORD	dwPrivilege;
    	DWORD	dwCurrentProcessId = GetCurrentProcessId();
    	DWORD	dwParentProcessId = 0;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwTP;
    
    	TOKEN_PRIVILEGES *lpTP;
    
    	PROCESSENTRY32	pe /* = {sizeof(pe)} */;
    
    	HANDLE	hSnapshot;
    	HANDLE	hParent;
    	HANDLE	hToken;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"At least one privilege to enable, disable or remove must be given by its name!\n");
    			else
    			{
    				dwTP = sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES) * (nArguments - 1 - ANYSIZE_ARRAY);
    				lpTP = (TOKEN_PRIVILEGES *) LocalAlloc(LPTR, dwTP);
    
    				if (lpTP == NULL)
    					PrintConsole(hConsole,
    					             L"LocalAlloc() returned error %lu\n",
    					             dwError = GetLastError());
    				else
    				{
    					lpTP->PrivilegeCount = nArguments - 1;
    
    					do
    					{
    						lpPrivilege = NULL;
    
    						if (wcslen(lpArguments[nArgument]) > sizeof("/DISABLE:Se*Privilege"))
    							if (memcmp(lpArguments[nArgument], L"/DISABLE:", sizeof(L"/DISABLE:") - sizeof(L"")) == 0)
    							{
    								lpPrivilege = lpArguments[nArgument] + sizeof("/DISABLE");
    							//	lpTP->Privileges[nArgument - 1].Attributes = SE_PRIVILEGE_DISABLED;
    							}
    							else if (memcmp(lpArguments[nArgument], L"/ENABLE:", sizeof(L"/ENABLE:") - sizeof(L"")) == 0)
    							{
    								lpPrivilege = lpArguments[nArgument] + sizeof("/ENABLE");
    								lpTP->Privileges[nArgument - 1].Attributes = SE_PRIVILEGE_ENABLED;
    							}
    							else if (memcmp(lpArguments[nArgument], L"/REMOVE:", sizeof(L"/REMOVE:") - sizeof(L"")) == 0)
    							{
    								lpPrivilege = lpArguments[nArgument] + sizeof("/REMOVE");
    								lpTP->Privileges[nArgument - 1].Attributes = SE_PRIVILEGE_REMOVED;
    							}
    
    						if (lpPrivilege == NULL)
    						{
    							PrintConsole(hConsole,
    							             L"Invalid argument \'%ls\'!\n",
    							             lpArguments[nArgument]);
    
    							lpTP->PrivilegeCount = 0;
    						}
    						else
    							if (!LookupPrivilegeValue((LPCWSTR) NULL,
    							                          lpPrivilege,
    							                          &lpTP->Privileges[nArgument - 1].Luid))
    							{
    								PrintConsole(hConsole,
    								             L"LookupPrivilegeValue() returned error %lu for \'%ls\'\n",
    								             dwError = GetLastError(), lpPrivilege);
    
    								lpTP->PrivilegeCount = 0;
    							}
    					} while (++nArgument < nArguments);
    
    					if (lpTP->PrivilegeCount > 0)
    					{
    						hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    
    						if (hSnapshot == INVALID_HANDLE_VALUE)
    							PrintConsole(hConsole,
    							             L"CreateToolhelp32Snapshot() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							pe.dwSize = sizeof(pe);
    
    							if (!Process32First(hSnapshot, &pe))
    								PrintConsole(hConsole,
    								             L"Process32First() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								do
    									if (pe.th32ProcessID == dwCurrentProcessId)
    										dwParentProcessId = pe.th32ParentProcessID;
    								while (Process32Next(hSnapshot, &pe));
    
    								dwError = GetLastError();
    
    								if (dwError != ERROR_NO_MORE_FILES)
    									PrintConsole(hConsole,
    									             L"Process32Next() returned error %lu\n",
    									             dwError);
    							}
    
    							if (!CloseHandle(hSnapshot))
    								PrintConsole(hConsole,
    								             L"CloseHandle() returned error %lu\n",
    								             GetLastError());
    
    							if (dwParentProcessId == 0)
    							{
    								PrintConsole(hConsole,
    								             L"Parent process of process %lu not found!\n",
    								             dwCurrentProcessId);
    
    								dwError = ERROR_NOT_FOUND;
    							}
    							else
    							{
    								hParent = OpenProcess(PROCESS_QUERY_INFORMATION,
    								                      FALSE,
    								                      dwParentProcessId);
    
    								if (hParent == NULL)
    									PrintConsole(hConsole,
    									             L"OpenProcess() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    								{
    									if (!OpenProcessToken(hParent,
    									                      TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
    									                      &hToken))
    										PrintConsole(hConsole,
    										             L"OpenProcessToken() returned error %lu\n",
    										             dwError = GetLastError());
    									else
    									{
    										if (!AdjustTokenPrivileges(hToken,
    										                           FALSE,
    										                           lpTP,
    										                           dwTP,
    										                           lpTP,
    										                           &dwTP))
    											PrintConsole(hConsole,
    											             L"AdjustTokenPrivileges() returned error %lu\n",
    											             dwError = GetLastError());
    										else
    										{
    											dwError = GetLastError();
    
    											if (lpTP->PrivilegeCount == 0)
    												if (dwError == ERROR_NOT_ALL_ASSIGNED)
    													PrintConsole(hConsole,
    													             L"Not all privileges assigned, no privilege toggled in parent process %lu\n",
    													             dwParentProcessId);
    												else
    													PrintConsole(hConsole,
    													             L"No privilege toggled in parent process %lu\n",
    													             dwParentProcessId);
    											else
    											{
    												if (dwError == ERROR_NOT_ALL_ASSIGNED)
    													PrintConsole(hConsole,
    													             L"Not all privileges assigned, %lu privilege(s) toggled in parent process %lu:\n",
    													             lpTP->PrivilegeCount, dwParentProcessId);
    												else
    													PrintConsole(hConsole,
    													             L"%lu privilege(s) toggled in parent process %lu:\n",
    													             lpTP->PrivilegeCount, dwParentProcessId);
    												dwTP = 0;
    
    												do
    												{
    													dwPrivilege = sizeof(szPrivilege) / sizeof(*szPrivilege);
    
    													if (!LookupPrivilegeName((LPCWSTR) NULL,
    													                         &lpTP->Privileges[dwTP].Luid,
    													                         szPrivilege,
    													                         &dwPrivilege))
    														PrintConsole(hConsole,
    														             L"LookupPrivilegeName() returned error %lu\n",
    														             dwError = GetLastError());
    													else
    														PrintConsole(hConsole,
    														             L"\'%ls\'%lc",
    														             szPrivilege, dwTP != lpTP->PrivilegeCount ? L' ' : L'\n');
    												}
    												while (++dwTP < lpTP->PrivilegeCount);
    											}
    										}
    
    										if (!CloseHandle(hToken))
    											PrintConsole(hConsole,
    											             L"CloseHandle() returned error %lu\n",
    											             GetLastError());
    									}
    
    									if (!CloseHandle(hParent))
    										PrintConsole(hConsole,
    										             L"CloseHandle() returned error %lu\n",
    										             GetLastError());
    								}
    							}
    						}
    					}
    
    					if (LocalFree(lpTP) != NULL)
    						PrintConsole(hConsole,
    						             L"LocalFree() returned error %lu\n",
    						             GetLastError());
    				}
    			}
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file TWIDDLER.C created in step 1., link the compiled object file TWIDDLER.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeTWIDDLER.COM TWIDDLER.C ADVAPI32.LIB KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE TWIDDLER.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    TWIDDLER.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

8.3 File and Directory Name Changer

Purpose
Background Information
Synopsis
Downloads
Alternative
Implementation and Build Details
Source and Build Instructions

Purpose

Remove superfluous long names of files and directories on VFAT filesystems and superfluous short (8.3) names of files and directories on NTFS filesystems, i.e. long respectively short (8.3) names which differ only in case from their corresponding short (8.3) or long name.

Background Information

Since Windows is insensitive to the case of file and directory names, long names which differ only in case from their corresponding short (8.3) name can generally be renamed to that short (8.3) name and the superfluous long or short (8.3) name thereby (implicitly) removed.

The TechNet article The FAT File System documents the format of directory entries and the layout of directories: while a (mandatory) short (8.3) name occupies just a single directory entry, a(n optional) long name occupies at least 1 and up to 14 additional directory entries.

The TechNet article The NTFS File System documents that short (8.3) names are needed only for legacy DOS applications.

Note: 64-bit editions of Windows NT don’t support DOS applications, thus short (8.3) names can be removed completely there.

For additional information see the MSKB articles How to Disable the 8.3 Name Creation on NTFS Partitions, How Windows Generates 8.3 File Names from Long File Names and Short (8.3) File Names May Change When Copied.

Synopsis

UPPERCUT.COM { ‹directory name› | ‹file name› } …

Downloads

The console application is available in two functional identical forms: UPPERCUT.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and UPPERCUT.COM, a small form without these extras.

Alternative

Except for hidden files and subdirectories, which are ignored, and reparse points, i.e. junctions and symbolic links, which are traversed, the following two command lines perform the same operation:
FOR /R "‹directory name›" %? IN (*) DO @IF NOT "%~nx?" == "%~snx?" IF /I "%~nx?" == "%~snx?" RENAME "%~f?" "%~snx?"
FOR /D /R "‹directory name›" %? IN (*) DO @IF NOT "%~nx?" == "%~snx?" IF /I "%~nx?" == "%~snx?" RENAME "%~f?" "%~snx?"

Implementation and Build Details

8.3 File and Directory Name Changer is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Source and Build Instructions

Perform the following two simple steps to build the console application 8.3 File and Directory Name Changer from the source presented hereafter.
  1. Create the text file UPPERCUT.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define _CRT_SECURE_NO_WARNINGS
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #define memcpy	__movsb
    #define wmemcpy	__movsw
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    __declspec(safebuffers)
    DWORD	WINAPI	Traverse(HANDLE hConsole, WCHAR szPathName[32768], WCHAR sz8Dot3Name[32768])
    {
    	WIN32_FIND_DATA	wfd;
    
    	DWORD	dwError;
    	DWORD	dwPathName = wcslen(szPathName);
    	HANDLE	hPathName;
    #if 0
    	wcscat(szPathName, L"\\*");
    #elif 0
    	wmemcpy(szPathName + dwPathName, L"\\*", sizeof("\\*"));
    #elif 0
    	memcpy(szPathName + dwPathName, L"\\*", sizeof(L"\\*"));
    #else
    	szPathName[dwPathName + 0] = L'\\';
    	szPathName[dwPathName + 1] = L'*';
    	szPathName[dwPathName + 2] = L'\0';
    #endif
    	hPathName = FindFirstFile(szPathName, &wfd);
    
    	if (hPathName != INVALID_HANDLE_VALUE)
    	{
    		wmemcpy(sz8Dot3Name, szPathName, dwPathName + 1);
    
    		do
    		{
    			wcscpy(szPathName + dwPathName + 1, wfd.cFileName);
    
    			if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
    			{
    #if 0
    				if ((wcscmp(wfd.cFileName, L".") == 0)
    				 || (wcscmp(wfd.cFileName, L"..") == 0))
    					continue;
    #elif 0
    				if ((wmemcmp(wfd.cFileName, L".", sizeof(".")) == 0)
    				 || (wmemcmp(wfd.cFileName, L"..", sizeof("..")) == 0))
    					continue;
    #elif 0
    				if ((memcmp(wfd.cFileName, L".", sizeof(L".")) == 0)
    				 || (memcmp(wfd.cFileName, L"..", sizeof(L"..")) == 0))
    					continue;
    #else
    				if ((wfd.cFileName[0] == L'.')
    				 && (wfd.cFileName[1] == L'\0'))
    					continue;
    
    				if ((wfd.cFileName[0] == L'.')
    				 && (wfd.cFileName[1] == L'.')
    				 && (wfd.cFileName[2] == L'\0'))
    					continue;
    #endif
    				if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
    					dwError = Traverse(hConsole, szPathName, sz8Dot3Name);
    			}
    
    			if ((wcscmp(wfd.cFileName, wfd.cAlternateFileName) == 0)
    			 || (lstrcmpi(wfd.cFileName, wfd.cAlternateFileName) != 0))
    				continue;
    
    			wcscpy(sz8Dot3Name + dwPathName + 1, wfd.cAlternateFileName);
    
    			if (!MoveFile(szPathName, sz8Dot3Name))
    				PrintConsole(hConsole,
    				             L"MoveFile(\"%ls\", \"%ls\") returned error %lu\n",
    				             szPathName, sz8Dot3Name, dwError = GetLastError());
    #if 0
    			else
    				if (!MoveFile(sz8Dot3Name, szPathName))
    					PrintConsole(hConsole,
    					             L"MoveFile(\"%ls\", \"%ls\") returned error %lu\n",
    					             sz8Dot3Name, szPathName, dwError = GetLastError());
    #endif
    		}
    		while (FindNextFile(hPathName, &wfd));
    
    		dwError = GetLastError();
    
    		if (dwError == ERROR_NO_MORE_FILES)
    			dwError = ERROR_SUCCESS;
    		else
    			PrintConsole(hConsole,
    			             L"FindNextFile() returned error %lu for path \'%ls\'\n",
    			             dwError, szPathName);
    
    		if (!FindClose(hPathName))
    			PrintConsole(hConsole,
    			             L"FindClose() returned error %lu for path \'%ls\'\n",
    			             GetLastError(), szPathName);
    	}
    	else
    	{
    		dwError = GetLastError();
    
    		if (dwError == ERROR_FILE_NOT_FOUND)
    			dwError = ERROR_SUCCESS;
    		else
    			PrintConsole(hConsole,
    			             L"FindFirstFile() returned error %lu for path \'%ls\'\n",
    			             dwError, szPathName);
    	}
    
    //	szPathName[dwPathName] = L'\0';
    
    	return dwError;
    }
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	WIN32_FIND_DATA	wfd;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 1;
    	WCHAR	sz8Dot3Name[32768];
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwArgument;
    	WCHAR	szArgument[32768];
    	LPWSTR	lpArgument;
    	HANDLE	hArgument;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"No arguments: at least one (wildcard) directory or file name must be given!\n");
    			else
    				do
    				{
    					hArgument = FindFirstFile(lpArguments[nArgument], &wfd);
    
    					if (hArgument == INVALID_HANDLE_VALUE)
    						PrintConsole(hConsole,
    						             L"FindFirstFile() returned error %lu for argument \'%ls\'\n",
    						             dwError = GetLastError(), lpArguments[nArgument]);
    					else
    					{
    						dwArgument = 0;
    						lpArgument = NULL;
    
    						do
    						{
    							sz8Dot3Name[dwArgument] = szArgument[dwArgument] = lpArguments[nArgument][dwArgument];
    
    							if (szArgument[dwArgument] == L'\\')
    								lpArgument = szArgument + dwArgument;
    						}
    						while (szArgument[dwArgument++] != L'\0');
    
    						if (dwArgument > MAX_PATH)
    							PrintConsole(hConsole,
    							             L"Argument \'%ls\' exceeds MAX_PATH!\n",
    							             szArgument);
    
    						if (lpArgument != NULL)
    							lpArgument++;
    						else
    							lpArgument = szArgument + 2 * (szArgument[1] == L':');
    
    						dwArgument = 0;
    
    						do
    						{
    							wcscpy(lpArgument, wfd.cFileName);
    
    							if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
    							{
    #if 0
    								if ((wcscmp(wfd.cFileName, L".") == 0)
    								 || (wcscmp(wfd.cFileName, L"..") == 0))
    									continue;
    #elif 0
    								if ((wmemcmp(wfd.cFileName, L".", sizeof(".")) == 0)
    								 || (wmemcmp(wfd.cFileName, L"..", sizeof("..")) == 0))
    									continue;
    #elif 0
    								if ((memcmp(wfd.cFileName, L".", sizeof(L".")) == 0)
    								 || (memcmp(wfd.cFileName, L"..", sizeof(L"..")) == 0))
    									continue;
    #else
    								if ((wfd.cFileName[0] == L'.')
    								 && (wfd.cFileName[1] == L'\0'))
    									continue;
    
    								if ((wfd.cFileName[0] == L'.')
    								 && (wfd.cFileName[1] == L'.')
    								 && (wfd.cFileName[2] == L'\0'))
    									continue;
    #endif
    								if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
    									dwError = Traverse(hConsole, szArgument, sz8Dot3Name);
    							}
    
    							dwArgument++;
    
    							if ((wcscmp(wfd.cFileName, wfd.cAlternateFileName) == 0)
    							 || (lstrcmpi(wfd.cFileName, wfd.cAlternateFileName) != 0))
    								continue;
    
    							wcscpy(lpArgument - szArgument + sz8Dot3Name, wfd.cAlternateFileName);
    
    							if (!MoveFile(szArgument, sz8Dot3Name))
    								PrintConsole(hConsole,
    								             L"MoveFile(\"%ls\", \"%ls\") returned error %lu\n",
    								             szArgument, sz8Dot3Name, dwError = GetLastError());
    #if 0
    							else
    								if (!MoveFile(sz8Dot3Name, szArgument))
    									PrintConsole(hConsole,
    									             L"MoveFile(\"%ls\", \"%ls\") returned error %lu\n",
    									             sz8Dot3Name, szArgument, dwError = GetLastError());
    #endif
    						}
    						while (FindNextFile(hArgument, &wfd));
    
    						dwError = GetLastError();
    
    						if (dwError == ERROR_NO_MORE_FILES)
    							dwError = ERROR_SUCCESS;
    						else
    							PrintConsole(hConsole,
    							             L"FindNextFile() returned error %lu for argument \'%ls\'\n",
    							             dwError, lpArguments[nArgument]);
    
    						if (dwArgument == 0)
    							PrintConsole(hConsole,
    							             L"No wildcard match for argument \'%ls\'!\n",
    							             lpArguments[nArgument]);
    
    						if (!FindClose(hArgument))
    							PrintConsole(hConsole,
    							             L"FindClose() returned error %lu for argument \'%ls\'\n",
    							             GetLastError(), lpArguments[nArgument]);
    					}
    				} while (++nArgument < nArguments);
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file UPPERCUT.C created in step 1., link the compiled object file UPPERCUT.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gs135168 /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /STACK:1048576,131072 /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeUPPERCUT.COM UPPERCUT.C KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE UPPERCUT.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    UPPERCUT.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Version Information Reader

Purpose
Background Information
Synopsis
Downloads
Implementation and Build Details
Variant 1
Variant 2
Source and Build Instructions – Variant 1
Source and Build Instructions – Variant 2
Demonstration

Purpose

Display the Version Information embedded in portable executable image files, i.e. applications and DLLs.

Background Information

The MSDN article Version Information provides an overview; the articles VERSIONINFO resource, VS_VERSIONINFO structure, VS_FIXEDFILEINFO structure, StringFileInfo structure, StringTable structure, String structure, VarFileInfo structure and Var structure provide the details (but are riddled with errors).

A VERSIONINFO resource contains a series of double-word aligned chunks, each identified by a key string, starting with a root chunk for the fix(-siz)ed binary file information, optionally followed by (empty) branch plus (non-empty) leaf chunks for variable-sized binary or textual file information.

Synopsis

VERSION.COM ‹module file name› …
Note: the image files are located via DLL search order!

Downloads

The console application is available in two functional identical forms: VERSION.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and VERSION.COM, a small form without these extras.

Implementation and Build Details

Version Information Reader is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: due to the design and implementation of Windows’ (classic alias legacy) console, the Win32 function WriteConsole() can only write to a console, not to a file nor a pipe, i.e. redirection of standard error or standard output is not supported!

The MSDN article Console Handles provides background information.

Variant 1

The first, canonical variant uses the Win32 functions GetFileVersionInfoSize(), GetFileVersionInfoSizeEx(), GetFileVersionInfo(), GetFileVersionInfoEx() and VerQueryValue() provided by Version.dll, which have but several drawbacks: each call of one of the GetFileVersionInfo*() functions loads (and unloads) the portable executable module in question, and each call of the VerQueryValue() function parses the VERSIONINFO resource anew.

Additionally the paths of the information to query have to be known, i.e. enumeration of arbitrary or custom version information is generally not possible or fails completely!

Variant 2

The second, custom variant uses the Win32 functions LoadLibraryEx() and FreeLibrary() to load (and finally unload) the portable executable module just once, the Win32 functions FindResourceEx(), LoadResource() and LockResource() to locate the VS_VERSIONINFO structure and obtain its memory address, plus the custom (recursive) function Version() to enumerate all parts of (arbitrary) VERSIONINFO resources.

Source and Build Instructions – Variant 1

Perform the following two simple steps to build the first variant of the console application Version Information Reader from the source presented hereafter.
  1. Create the text file VERSION.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #define memcpy	__movsb
    #define wmemcpy	__movsw
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    const	LPCWSTR	szDayOfWeek[7] = {L"Sunday",
    		                  L"Monday",
    		                  L"Tuesday",
    		                  L"Wednesday",
    		                  L"Thursday",
    		                  L"Friday",
    		                  L"Saturday"};
    
    const	LPCWSTR	szFileOSHigh[] = {L"Unknown",				// VOS_UNKNOWN
    		                  L"MS-DOS",				// VOS_DOS
    		                  L"OS/2 (16-bit)",			// VOS_OS216
    		                  L"OS/2 (32-bit)",			// VOS_OS232
    		                  L"Windows NT",			// VOS_NT
    		                  L"Windows CE"};			// VOS_WINCE
    
    const	LPCWSTR	szFileOSLow[] = {L"Base",				// VOS__BASE
    		                 L"Windows (16-bit)",			// VOS__WINDOWS16
    		                 L"Presentation Manager (16-bit)",	// VOS__PM16
    		                 L"Presentation Manager (32-bit)",	// VOS__PM32
    		                 L"Windows (32-bit)"};			// VOS__WINDOWS32
    
    const	LPCWSTR	szFileType[] = {L"Unknown",				// VFT_UNKNOWN
    		                L"Application",				// VFT_APP
    		                L"DLL",					// VFT_DLL
    		                L"Driver",				// VFT_DRV
    		                L"Font",				// VFT_FONT
    		                L"Virtual Device",			// VFT_VXD
    		                L"Undefined",
    		                L"Static Library"};			// VFT_STATIC_LIB
    
    const	LPCWSTR	szFileDriverType[] = {L"Unknown",			// VFT2_UNKNOWN
    		                      L"Printer",			// VFT2_DRV_PRINTER
    		                      L"Keyboard",			// VFT2_DRV_KEYBOARD
    		                      L"Language",			// VFT2_DRV_LANGUAGE
    		                      L"Display",			// VFT2_DRV_DISPLAY
    		                      L"Mouse",				// VFT2_DRV_MOUSE
    		                      L"Network",			// VFT2_DRV_NETWORK
    		                      L"System",			// VFT2_DRV_SYSTEM
    		                      L"Installable",			// VFT2_DRV_INSTALLABLE
    		                      L"Sound",				// VFT2_DRV_SOUND
    		                      L"Communications",		// VFT2_DRV_COMM
    		                      L"Input Method",			// VFT2_DRV_INPUTMETHOD
    		                      L"Versioned Printer"};		// VFT2_DRV_VERSIONED_PRINTER
    
    const	LPCWSTR	szFileFontType[] = {L"Unknown",				// VFT2_UNKNOWN
    		                    L"Raster",				// VFT2_FONT_RASTER
    		                    L"Vector",				// VFT2_FONT_VECTOR
    		                    L"TrueType"};			// VFT2_FONT_TRUETYPE
    
    const	LPCWSTR	szStandard[] = {L"Comments",
    		                L"CompanyName",
    		                L"FileDescription",
    		                L"FileVersion",
    		                L"InternalName",
    		                L"LegalCopyright",
    		                L"LegalTrademarks",
    		                L"OleSelfRegister",
    		                L"OriginalFilename",
    		                L"PrivateBuild",
    		                L"ProductName",
    		                L"ProductVersion",
    		                L"SpecialBuild"};
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	VS_FIXEDFILEINFO	*lpFFI;
    
    	SYSTEMTIME	st;
    	FILETIME	ft;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 1;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	DWORD	dwHandle;
    	DWORD	dwVersion;
    	LPBYTE	lpVersion;
    	WCHAR	szFileFlags[sizeof(", Debug, Inferred, Patched, Pre-Release, Private Build, Special Build")];
    	LPWSTR	lpFileFlags;
    	LPCWSTR	lpFileOSLow, lpFileOSHigh;
    	LPCWSTR	lpFileType, lpFileSubtype;
    	UINT	uiFFI, uiSFI, uiVFI;
    	DWORD	*lpVFI;
    	WCHAR	szSFI[sizeof("\\StringFileInfo\\00000000\\OriginalFilename")];
    	LPWSTR	lpSFI;
    	WCHAR	szLanguage[256];
    	DWORD	dwLanguage;
    	DWORD	dwStandard;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"No arguments: at least one (absolute or relative) path name of a binary module\n"
    				             L"              (eventually located per DLL search order) must be given!\n");
    			else
    				do
    				{
    #ifdef NEUTRAL
    					dwVersion = GetFileVersionInfoSizeEx(FILE_VER_GET_NEUTRAL,
    					                                     lpArguments[nArgument],
    					                                     &dwHandle);
    
    					if (dwVersion == 0)
    						PrintConsole(hConsole,
    						             L"GetFileVersionInfoSizeEx() returned error %lu for file \'%ls\'\n",
    						             dwError = GetLastError(), lpArguments[nArgument]);
    #else
    					dwVersion = GetFileVersionInfoSize(lpArguments[nArgument],
    					                                   &dwHandle);
    
    					if (dwVersion == 0)
    						PrintConsole(hConsole,
    						             L"GetFileVersionInfoSize() returned error %lu for file \'%ls\'\n",
    						             dwError = GetLastError(), lpArguments[nArgument]);
    #endif
    					else
    					{
    						lpVersion = LocalAlloc(LPTR, dwVersion);
    
    						if (lpVersion == NULL)
    							PrintConsole(hConsole,
    							             L"LocalAlloc() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    #ifdef NEUTRAL
    							if (!GetFileVersionInfoEx(FILE_VER_GET_NEUTRAL,
    							                          lpArguments[nArgument],
    							                          dwHandle,
    							                          dwVersion,
    							                          lpVersion))
    								PrintConsole(hConsole,
    								             L"GetFileVersionInfoSizeEx() returned error %lu for file \'%ls\'\n",
    								             dwError = GetLastError(), lpArguments[nArgument]);
    #else
    							if (!GetFileVersionInfo(lpArguments[nArgument],
    							                        dwHandle,
    							                        dwVersion,
    							                        lpVersion))
    								PrintConsole(hConsole,
    								             L"GetFileVersionInfoSize() returned error %lu for file \'%ls\'\n",
    								             dwError = GetLastError(), lpArguments[nArgument]);
    #endif
    							else
    							{
    								if (!VerQueryValue(lpVersion,
    								                   L"\\",
    								                   &lpFFI,
    								                   &uiFFI))
    									PrintConsole(hConsole,
    									             L"VerQueryValue() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    								{
    									if ((lpFFI->dwFileFlags & lpFFI->dwFileFlagsMask) == 0)
    #ifdef _CRT_SECURE_NO_WARNINGS
    										wcscpy(szFileFlags, L", None");
    #elif 0
    										wmemcpy(szFileFlags, L", None", sizeof(", None"));
    #else
    										memcpy(szFileFlags, L", None", sizeof(L", None"));
    #endif
    									else
    									{
    #ifdef _CRT_SECURE_NO_WARNINGS
    										*szFileFlags = L'\0';
    
    										if ((lpFFI->dwFileFlags & VS_FF_DEBUG) == VS_FF_DEBUG)
    											wcscat(szFileFlags, L", Debug");
    
    										if ((lpFFI->dwFileFlags & VS_FF_INFOINFERRED) == VS_FF_INFOINFERRED)
    											wcscat(szFileFlags, L", Inferred");
    
    										if ((lpFFI->dwFileFlags & VS_FF_PATCHED) == VS_FF_PATCHED)
    											wcscat(szFileFlags, L", Patched");
    
    										if ((lpFFI->dwFileFlags & VS_FF_PRERELEASE) == VS_FF_PRERELEASE)
    											wcscat(szFileFlags, L", Pre-Release");
    
    										if ((lpFFI->dwFileFlags & VS_FF_PRIVATEBUILD) == VS_FF_PRIVATEBUILD)
    											wcscat(szFileFlags, L", Private Build");
    
    										if ((lpFFI->dwFileFlags & VS_FF_SPECIALBUILD) == VS_FF_SPECIALBUILD)
    											wcscat(szFileFlags, L", Special Build");
    #else // _CRT_SECURE_NO_WARNINGS
    										lpFileFlags = szFileFlags;
    
    										if ((lpFFI->dwFileFlags & VS_FF_DEBUG) == VS_FF_DEBUG)
    										{
    											memcpy(lpFileFlags, L", Debug", sizeof(L", Debug"));
    
    											lpFileFlags += sizeof(" Debug");
    										}
    
    										if ((lpFFI->dwFileFlags & VS_FF_INFOINFERRED) == VS_FF_INFOINFERRED)
    										{
    											memcpy(lpFileFlags, L", Inferred", sizeof(L", Inferred"));
    
    											lpFileFlags += sizeof(" Inferred");
    										}
    
    										if ((lpFFI->dwFileFlags & VS_FF_PATCHED) == VS_FF_PATCHED)
    										{
    											memcpy(lpFileFlags, L", Patched", sizeof(L", Patched"));
    
    											lpFileFlags += sizeof(" Patched");
    										}
    
    										if ((lpFFI->dwFileFlags & VS_FF_PRERELEASE) == VS_FF_PRERELEASE)
    										{
    											memcpy(lpFileFlags, L", Pre-Release", sizeof(L", Pre-Release"));
    
    											lpFileFlags += sizeof(" Pre-Release");
    										}
    
    										if ((lpFFI->dwFileFlags & VS_FF_PRIVATEBUILD) == VS_FF_PRIVATEBUILD)
    										{
    											memcpy(lpFileFlags, L", Private Build", sizeof(L", Private Build"));
    
    											lpFileFlags += sizeof(" Private Build");
    										}
    
    										if ((lpFFI->dwFileFlags & VS_FF_SPECIALBUILD) == VS_FF_SPECIALBUILD)
    										{
    											memcpy(lpFileFlags, L", Special Build", sizeof(L", Special Build"));
    
    											lpFileFlags += sizeof(" Special Build");
    										}
    #endif // _CRT_SECURE_NO_WARNINGS
    									}
    
    									if (lpFFI->dwFileType < sizeof(szFileType) / sizeof(*szFileType))
    										lpFileType = szFileType[lpFFI->dwFileType];
    									else
    										lpFileType = L"Undefined";
    
    									if ((lpFFI->dwFileType == VFT_DRV)
    									 && (lpFFI->dwFileSubtype < sizeof(szFileDriverType) / sizeof(*szFileDriverType)))
    										lpFileSubtype = szFileDriverType[lpFFI->dwFileSubtype];
    									else if ((lpFFI->dwFileType == VFT_FONT)
    									      && (lpFFI->dwFileSubtype < sizeof(szFileFontType) / sizeof(*szFileFontType)))
    										lpFileSubtype = szFileFontType[lpFFI->dwFileSubtype];
    									else
    										lpFileSubtype = L"Undefined";
    
    									if (HIWORD(lpFFI->dwFileOS) < sizeof(szFileOSHigh) / sizeof(*szFileOSHigh))
    										lpFileOSHigh = szFileOSHigh[HIWORD(lpFFI->dwFileOS)];
    									else
    										lpFileOSHigh = L"Undefined";
    
    									if (LOWORD(lpFFI->dwFileOS) < sizeof(szFileOSLow) / sizeof(*szFileOSLow))
    										lpFileOSLow = szFileOSLow[LOWORD(lpFFI->dwFileOS)];
    									else
    										lpFileOSLow = L"Undefined";
    
    									PrintConsole(hConsole,
    									             L"\n"
    									             L"Product Version:\t%hu.%hu:%hu.%hu\n"
    									             L"Module Version:\t\t%hu.%hu:%hu.%hu\n"
    									             L"Module Flags:\t\t%ls\n"
    									             L"Module Type:\t\t%ls\n"
    									             L"Module Subtype:\t\t%ls\n",
    									             HIWORD(lpFFI->dwProductVersionMS), LOWORD(lpFFI->dwProductVersionMS),
    									             HIWORD(lpFFI->dwProductVersionLS), LOWORD(lpFFI->dwProductVersionLS),
    									             HIWORD(lpFFI->dwFileVersionMS), LOWORD(lpFFI->dwFileVersionMS),
    									             HIWORD(lpFFI->dwFileVersionLS), LOWORD(lpFFI->dwFileVersionLS),
    									             szFileFlags + 2,
    									             lpFileType,
    									             lpFileSubtype);
    
    									if ((lpFFI->dwFileDateMS == 0)
    									 && (lpFFI->dwFileDateLS == 0))
    										PrintConsole(hConsole,
    										             L"Module Date/Time Stamp:\tNone\n");
    									else
    									{
    										ft.dwHighDateTime = lpFFI->dwFileDateMS;
    										ft.dwLowDateTime = lpFFI->dwFileDateLS;
    
    										if (!FileTimeToSystemTime(&ft, &st))
    											PrintConsole(hConsole,
    											             L"FileTimeToSystemTime() returned error %lu\n",
    											             dwError = GetLastError());
    										else
    											PrintConsole(hConsole,
    											             L"Module Date/Time Stamp:\t%ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu.%03hu UTC\n",
    											             szDayOfWeek[st.wDayOfWeek],
    											             st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    									}
    
    									PrintConsole(hConsole,
    									             L"Target OS:\t\t%ls, %ls\n",
    									             lpFileOSHigh, lpFileOSLow);
    								}
    
    								if (!VerQueryValue(lpVersion,
    								                   L"\\VarFileInfo\\Translation",
    								                   &lpVFI,
    								                   &uiVFI))
    									PrintConsole(hConsole,
    									             L"VerQueryValue() returned error %lu\n",
    									             dwError = GetLastError());
    								else
    									for (dwLanguage = 0; dwLanguage < uiVFI / sizeof(*lpVFI); dwLanguage++)
    									{
    										if (VerLanguageName(LOWORD(lpVFI[dwLanguage]),
    										                    szLanguage,
    										                    sizeof(szLanguage) / sizeof(*szLanguage)) == 0)
    											PrintConsole(hConsole,
    											             L"\n"
    											             L"Language:\t0x%04hX\n"
    											             L"Codepage:\t0x%04hX = %hu\n",
    											             LOWORD(lpVFI[dwLanguage]),
    											             HIWORD(lpVFI[dwLanguage]), HIWORD(lpVFI[dwLanguage]));
    										else
    											PrintConsole(hConsole,
    											             L"\n"
    											             L"Language:\t0x%04hX = %ls\n"
    											             L"Codepage:\t0x%04hX = %hu\n",
    											             LOWORD(lpVFI[dwLanguage]), szLanguage,
    											             HIWORD(lpVFI[dwLanguage]), HIWORD(lpVFI[dwLanguage]));
    
    										for (dwStandard = 0; dwStandard < sizeof(szStandard) / sizeof(*szStandard); dwStandard++)
    										{
    											uiSFI = wsprintf(szSFI,
    											                 L"\\StringFileInfo\\%04hX%04hX\\%ls",
    											                 LOWORD(lpVFI[dwLanguage]), HIWORD(lpVFI[dwLanguage]), szStandard[dwStandard]);
    #if 0
    											if (uiSFI != wcslen(L"\\StringFileInfo\\00000000\\") + wcslen(szStandard[dwStandard]))
    #else
    											if (uiSFI != sizeof("\\StringFileInfo\\00000000\\") - 1 + wcslen(szStandard[dwStandard]))
    #endif
    												PrintConsole(hConsole,
    												             L"wsprintf() returned error %lu\n",
    												             dwError = GetLastError());
    											else
    												if (VerQueryValue(lpVersion,
    												                  szSFI,
    												                  &lpSFI,
    												                  &uiSFI))
    													PrintConsole(hConsole,
    													             wcslen(szStandard[dwStandard]) < 15 ? L"\t%ls:\t\t%ls\n" : L"\t%ls:\t%ls\n",
    													             szStandard[dwStandard], lpSFI);
    												else
    												{
    													dwError = GetLastError();
    
    													if (dwError == ERROR_RESOURCE_TYPE_NOT_FOUND)
    														continue;
    
    													PrintConsole(hConsole,
    													             L"VerQueryValue() returned error %lu\n",
    													             dwError);
    												}
    										}
    									}
    							}
    
    							if (LocalFree(lpVersion) != NULL)
    								PrintConsole(hConsole,
    								             L"LocalFree() returned error %lu\n",
    								             GetLastError());
    						}
    					}
    				} while (++nArgument < nArguments);
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file VERSION.C created in step 1., link the compiled object file VERSION.OBJ and cleanup afterwards:

    SET CL=/DNEUTRAL /GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:6.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeVERSION.COM VERSION.C KERNEL32.LIB SHELL32.LIB USER32.LIB VERSION.LIB
    ERASE VERSION.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    VERSION.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Source and Build Instructions – Variant 2

Perform the following two simple steps to build the second variant of the console application Version Information Reader from the source presented hereafter.
  1. Overwrite the text file VERSION.C with the following content:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <shellapi.h>
    
    #define VS_BINARY	0U
    #define VS_TEXT		1U
    
    #pragma pack(push, 4)
    
    typedef	struct	_VS_CHUNK
    {
    	WORD	wSize;				// size of current chunk (tree, branch or leaf),
    						//  including all subordinate chunks
    	WORD	wCount;				// = sizeof(dwValue) or sizeof(szValue) / sizeof(*szValue)
    						//   (number of bytes in binary value or
    						//    number of characters in string value,
    						//    including the terminating NUL character,
    						//    for root and leaf chunks; 0 for branch chunks)
    	WORD	wType;				// = VS_BINARY or VS_TEXT
    #if 0
    						// leaf chunk (VS_VAR)
    	WCHAR	szKey[sizeof("Translation")];	// = L"Translation"
    	WORD	wPadding;			// = 0 (alignment to DWORD)
    	DWORD	dwValue[ANYSIZE_ARRAY];		// = {0x04B00409, ...}
    						//   (pairs of codepage and language ids)
    #elif 0
    						// branch chunk (VS_VARFILEINFO)
    	WCHAR	szKey[sizeof("VarFileInfo")];	// = L"VarFileInfo"
    	WORD	wPadding;			// = 0 (alignment to DWORD)
    //	WCHAR	szValue[0];			// NO value!
    #elif 0
    						// leaf chunk (VS_STRING)
    	WCHAR	szKey[sizeof("Comments")];	// = L"Comments"
    						//   (mandatory key names are L"CompanyName",
    						//    L"FileDescription", L"FileVersion",
    						//    L"InternalName", L"OriginalFilename",
    						//    L"ProductName", L"ProductVersion";
    						//    optional key names are L"Comments",
    						//    L"LegalCopyright", L"LegalTrademarks",
    						//    L"OleSelfRegister", L"PrivateBuild"
    						//    L"SpecialBuild", ...)
    						// (alignment to DWORD not necessary here)
    	WCHAR	szValue[ANYSIZE_ARRAY];		// = L""
    	WORD	wPadding;			// = 0 (alignment to DWORD)
    #elif 0
    						// lower branch chunk (VS_STRINGTABLE)
    	WCHAR	szKey[sizeof("040904B0")];	// = L"040904B0"
    						// (alignment to DWORD not necessary here)
    //	WCHAR	szValue[0];			// NO value!
    #elif 0
    						// upper branch chunk (VS_STRINGFILEINFO)
    	WCHAR	szKey[sizeof("StringFileInfo")];// = L"StringFileInfo"
    						// (alignment to DWORD not necessary here)
    //	WCHAR	szValue[0];			// NO value!
    #else
    						// root chunk (VS_VERSIONINFO)
    	WCHAR	szKey[sizeof("VS_VERSION_INFO")];
    	WORD	wPadding;			// = 0 (alignment to DWORD)
    #if 0
    	DWORD	dwValue[13];
    #else
    	VS_FIXEDFILEINFO	vsFFI;
    #endif
    #endif
    } VS_CHUNK;
    
    #pragma pack(pop)
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintConsole(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCWSTR lpFormat, ...)
    {
    	WCHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwConsole;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteConsole(hConsole, szOutput, dwOutput, &dwConsole, NULL))
    		return FALSE;
    
    	return dwConsole == dwOutput;
    }
    
    VOID	WINAPI	Version(HANDLE hConsole, VS_CHUNK *lpChunk, VS_CHUNK *lpLimit, DWORD dwLevel)
    {
    	DWORD	dwKey;
    	DWORD	dwValue;
    	LPCWSTR	lpValue;
    
    	while (lpChunk < lpLimit)
    	{
    		dwKey = wcslen(lpChunk->szKey);
    		lpValue = lpChunk->szKey + (dwKey + dwKey % 2 + 1);
    
    		if ((lpChunk->wCount == 0)
    	//	 && (lpChunk->wType == VS_TEXT)
    		 && (lpChunk->wSize + (BYTE *) lpChunk > (BYTE *) lpValue))
    		{
    			PrintConsole(hConsole,
    			             L"\t\t\t%ls:\n" + 3 - dwLevel,
    			             lpChunk->szKey);
    
    			Version(hConsole,
    			        (VS_CHUNK *) lpValue,
    			        (VS_CHUNK *) ((BYTE *) lpChunk + lpChunk->wSize),
    			        dwLevel + 1);
    		}
    		else if (lpChunk->wType == VS_BINARY)
    		{
    			PrintConsole(hConsole,
    			             L"\t\t\t%ls =" + 3 - dwLevel,
    			             lpChunk->szKey);
    
    			for (dwValue = 0; dwValue < lpChunk->wCount / sizeof(WORD); dwValue++)
    				PrintConsole(hConsole,
    				             dwValue % sizeof(WORD) ? L":%hu" : L" 0x%04hX",
    				             lpValue[dwValue]);
    
    			PrintConsole(hConsole, L"\n");
    		}
    		else
    			PrintConsole(hConsole,
    			             L"\t\t\t%-16ls = %ls\n" + 3 - dwLevel,
    			             lpChunk->szKey, lpChunk->wCount != 0 ? lpValue : L"");
    
    		lpChunk = (VS_CHUNK *) ((BYTE *) lpChunk + lpChunk->wSize + lpChunk->wSize % sizeof(DWORD));
    	}
    }
    
    const	LPCWSTR	szDayOfWeek[7] = {L"Sunday",
    		                  L"Monday",
    		                  L"Tuesday",
    		                  L"Wednesday",
    		                  L"Thursday",
    		                  L"Friday",
    		                  L"Saturday"};
    
    const	LPCWSTR	szFileOSHigh[] = {L"Unknown",				// VOS_UNKNOWN
    		                  L"MS-DOS",				// VOS_DOS
    		                  L"OS/2 (16-bit)",			// VOS_OS216
    		                  L"OS/2 (32-bit)",			// VOS_OS232
    		                  L"Windows NT",			// VOS_NT
    		                  L"Windows CE",			// VOS_WINCE
    		                  L"Undefined"};
    
    const	LPCWSTR	szFileOSLow[] = {L"Base",				// VOS__BASE
    		                 L"Windows (16-bit)",			// VOS__WINDOWS16
    		                 L"Presentation Manager (16-bit)",	// VOS__PM16
    		                 L"Presentation Manager (32-bit)",	// VOS__PM32
    		                 L"Windows (32-bit)"};			// VOS__WINDOWS32
    
    const	LPCWSTR	szFileType[] = {L"Unknown",				// VFT_UNKNOWN
    		                L"Application",				// VFT_APP
    		                L"DLL",					// VFT_DLL
    		                L"Driver",				// VFT_DRV
    		                L"Font",				// VFT_FONT
    		                L"Virtual Device",			// VFT_VXD
    		                L"Undefined",
    		                L"Static Library"};			// VFT_STATIC_LIB
    
    const	LPCWSTR	szFileDriverType[] = {L"Unknown",			// VFT2_UNKNOWN
    		                      L"Printer",			// VFT2_DRV_PRINTER
    		                      L"Keyboard",			// VFT2_DRV_KEYBOARD
    		                      L"Language",			// VFT2_DRV_LANGUAGE
    		                      L"Display",			// VFT2_DRV_DISPLAY
    		                      L"Mouse",				// VFT2_DRV_MOUSE
    		                      L"Network",			// VFT2_DRV_NETWORK
    		                      L"System",			// VFT2_DRV_SYSTEM
    		                      L"Installable",			// VFT2_DRV_INSTALLABLE
    		                      L"Sound",				// VFT2_DRV_SOUND
    		                      L"Communications",		// VFT2_DRV_COMM
    		                      L"Input Method",			// VFT2_DRV_INPUTMETHOD
    		                      L"Versioned Printer"};		// VFT2_DRV_VERSIONED_PRINTER
    
    const	LPCWSTR	szFileFontType[] = {L"Unknown",				// VFT2_UNKNOWN
    		                    L"Raster",				// VFT2_FONT_RASTER
    		                    L"Vector",				// VFT2_FONT_VECTOR
    		                    L"TrueType"};			// VFT2_FONT_TRUETYPE
    
    __declspec(noreturn)
    VOID	CDECL	wmainCRTStartup(VOID)
    {
    	VS_CHUNK	*lpVersion;
    	FILETIME	ft;
    	SYSTEMTIME	st;
    
    	LPWSTR	*lpArguments;
    	INT	nArguments;
    	INT	nArgument = 1;
    	DWORD	dwError = ERROR_BAD_ARGUMENTS;
    	HMODULE	hModule;
    	HRSRC	hResInfo;
    	HGLOBAL	hResData;
    	WCHAR	szFileFlags[sizeof(", Debug, Inferred, Patched, Pre-Release, Private Build, Special Build")];
    	LPWSTR	lpFileFlags;
    	LPCWSTR	lpFileOSLow, lpFileOSHigh;
    	LPCWSTR	lpFileType, lpFileSubtype;
    	HANDLE	hConsole = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hConsole == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		lpArguments = CommandLineToArgvW(GetCommandLine(), &nArguments);
    
    		if (lpArguments == NULL)
    			PrintConsole(hConsole,
    			             L"CommandLineToArgv() returned error %lu\n",
    			             dwError = GetLastError());
    		else
    		{
    			if (nArguments < 2)
    				PrintConsole(hConsole,
    				             L"No argument: at least one (absolute or relative) path name of a binary module\n"
    				             L"             (eventually located per DLL search order) must be given!\n");
    			else
    				do
    				{
    					hModule = LoadLibraryEx(lpArguments[nArgument],
    					                        (HANDLE) NULL,
    					                        LOAD_LIBRARY_AS_DATAFILE);
    
    					if (hModule == NULL)
    						PrintConsole(hConsole,
    						             L"LoadLibraryEx() returned error %lu for module \'%ls\'\n",
    						             dwError = GetLastError(), lpArguments[nArgument]);
    					else
    					{
    						PrintConsole(hConsole,
    						             L"Module \'%ls\' loaded at address 0x%p\n",
    						             lpArguments[nArgument], hModule);
    
    						hResInfo = FindResource(hModule, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
    
    						if (hResInfo == NULL)
    							PrintConsole(hConsole,
    							             L"FindResource() returned error %lu\n",
    							             dwError = GetLastError());
    						else
    						{
    							hResData = LoadResource(hModule, hResInfo);
    
    							if (hResData == NULL)
    								PrintConsole(hConsole,
    								             L"LoadResource() returned error %lu\n",
    								             dwError = GetLastError());
    							else
    							{
    								lpVersion = LockResource(hResData);
    
    								if (lpVersion == NULL)
    									PrintConsole(hConsole,
    									             L"LockResource() returned NULL\n");
    								else
    								{
    									if ((lpVersion->vsFFI.dwFileFlags & lpVersion->vsFFI.dwFileFlagsMask) == 0)
    #ifdef _CRT_SECURE_NO_WARNINGS
    										wcscpy(szFileFlags, L", None");
    #elif 0
    										wmemcpy(szFileFlags, L", None", sizeof(", None"));
    #else
    										memcpy(szFileFlags, L", None", sizeof(L", None"));
    #endif
    									else
    									{
    #ifdef _CRT_SECURE_NO_WARNINGS
    										*szFileFlags = L'\0';
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_DEBUG) == VS_FF_DEBUG)
    											wcscat(szFileFlags, L", Debug");
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_INFOINFERRED) == VS_FF_INFOINFERRED)
    											wcscat(szFileFlags, L", Inferred");
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_PATCHED) == VS_FF_PATCHED)
    											wcscat(szFileFlags, L", Patched");
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_PRERELEASE) == VS_FF_PRERELEASE)
    											wcscat(szFileFlags, L", Pre-Release");
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_PRIVATEBUILD) == VS_FF_PRIVATEBUILD)
    											wcscat(szFileFlags, L", Private Build");
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_SPECIALBUILD) == VS_FF_SPECIALBUILD)
    											wcscat(szFileFlags, L", Special Build");
    #else // _CRT_SECURE_NO_WARNINGS
    										lpFileFlags = szFileFlags;
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_DEBUG) == VS_FF_DEBUG)
    										{
    											memcpy(lpFileFlags, L", Debug", sizeof(L", Debug"));
    
    											lpFileFlags += sizeof(" Debug");
    										}
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_INFOINFERRED) == VS_FF_INFOINFERRED)
    										{
    											memcpy(lpFileFlags, L", Inferred", sizeof(L", Inferred"));
    
    											lpFileFlags += sizeof(" Inferred");
    										}
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_PATCHED) == VS_FF_PATCHED)
    										{
    											memcpy(lpFileFlags, L", Patched", sizeof(L", Patched"));
    
    											lpFileFlags += sizeof(" Patched");
    										}
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_PRERELEASE) == VS_FF_PRERELEASE)
    										{
    											memcpy(lpFileFlags, L", Pre-Release", sizeof(L", Pre-Release"));
    
    											lpFileFlags += sizeof(" Pre-Release");
    										}
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_PRIVATEBUILD) == VS_FF_PRIVATEBUILD)
    										{
    											memcpy(lpFileFlags, L", Private Build", sizeof(L", Private Build"));
    
    											lpFileFlags += sizeof(" Private Build");
    										}
    
    										if ((lpVersion->vsFFI.dwFileFlags & VS_FF_SPECIALBUILD) == VS_FF_SPECIALBUILD)
    										{
    											memcpy(lpFileFlags, L", Special Build", sizeof(L", Special Build"));
    
    											lpFileFlags += sizeof(" Special Build");
    										}
    #endif // _CRT_SECURE_NO_WARNINGS
    									}
    
    									if (lpVersion->vsFFI.dwFileType < sizeof(szFileType) / sizeof(*szFileType))
    										lpFileType = szFileType[lpVersion->vsFFI.dwFileType];
    									else
    										lpFileType = L"Undefined";
    
    									if ((lpVersion->vsFFI.dwFileType == VFT_DRV)
    									 && (lpVersion->vsFFI.dwFileSubtype < sizeof(szFileDriverType) / sizeof(*szFileDriverType)))
    										lpFileSubtype = szFileDriverType[lpVersion->vsFFI.dwFileSubtype];
    									else if ((lpVersion->vsFFI.dwFileType == VFT_FONT)
    									      && (lpVersion->vsFFI.dwFileSubtype < sizeof(szFileFontType) / sizeof(*szFileFontType)))
    										lpFileSubtype = szFileFontType[lpVersion->vsFFI.dwFileSubtype];
    									else
    										lpFileSubtype = L"Undefined";
    
    									if (HIWORD(lpVersion->vsFFI.dwFileOS) < sizeof(szFileOSHigh) / sizeof(*szFileOSHigh))
    										lpFileOSHigh = szFileOSHigh[HIWORD(lpVersion->vsFFI.dwFileOS)];
    									else
    										lpFileOSHigh = L"Undefined";
    
    									if (LOWORD(lpVersion->vsFFI.dwFileOS) < sizeof(szFileOSLow) / sizeof(*szFileOSLow))
    										lpFileOSLow = szFileOSLow[LOWORD(lpVersion->vsFFI.dwFileOS)];
    									else
    										lpFileOSLow = L"Undefined";
    
    									PrintConsole(hConsole,
    									             L"FixedFileInfo:\n"
    									             L"\tProduct Version   = %hu.%hu:%hu.%hu\n"
    									             L"\tModule Version    = %hu.%hu:%hu.%hu\n"
    									             L"\tModule Flags      = %ls\n"
    									             L"\tModule Type       = %ls\n"
    									             L"\tModule Subtype    = %ls\n",
    									             HIWORD(lpVersion->vsFFI.dwProductVersionMS), LOWORD(lpVersion->vsFFI.dwProductVersionMS),
    									             HIWORD(lpVersion->vsFFI.dwProductVersionLS), LOWORD(lpVersion->vsFFI.dwProductVersionLS),
    									             HIWORD(lpVersion->vsFFI.dwFileVersionMS), LOWORD(lpVersion->vsFFI.dwFileVersionMS),
    									             HIWORD(lpVersion->vsFFI.dwFileVersionLS), LOWORD(lpVersion->vsFFI.dwFileVersionLS),
    									             szFileFlags + 2,
    									             lpFileType,
    									             lpFileSubtype);
    
    									if ((lpVersion->vsFFI.dwFileDateMS == 0)
    									 && (lpVersion->vsFFI.dwFileDateLS == 0))
    										PrintConsole(hConsole,
    										             L"Module Time Stamp = None\n");
    									else
    									{
    										ft.dwHighDateTime = lpVersion->vsFFI.dwFileDateMS;
    										ft.dwLowDateTime = lpVersion->vsFFI.dwFileDateLS;
    
    										if (!FileTimeToSystemTime(&ft, &st))
    											PrintConsole(hConsole,
    											             L"FileTimeToSystemTime() returned error %lu\n",
    											             dwError = GetLastError());
    										else
    											PrintConsole(hConsole,
    											             L"\tModule Time Stamp = %ls, %04hu-%02hu-%02hu %02hu:%02hu:%02hu.%03hu UTC\n",
    											             szDayOfWeek[st.wDayOfWeek],
    											             st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    									}
    
    									PrintConsole(hConsole,
    									             L"\tTarget OS         = %ls, %ls\n",
    									             lpFileOSHigh, lpFileOSLow);
    
    									Version(hConsole,
    									        lpVersion + 1,
    									        (VS_CHUNK *) ((BYTE *) lpVersion + lpVersion->wSize),
    									        0);
    								}
    							}
    						}
    
    						if (!FreeLibrary(hModule))
    							PrintConsole(hConsole,
    							             L"FreeLibrary() returned error %lu\n",
    							             GetLastError());
    						else
    							PrintConsole(hConsole,
    							             L"Module \'%ls\' unloaded\n",
    							             lpArguments[nArgument]);
    					}
    				} while (++nArgument < nArguments);
    
    			if (LocalFree(lpArguments) != NULL)
    				PrintConsole(hConsole,
    				             L"LocalFree() returned error %lu\n",
    				             GetLastError());
    		}
    
    		if (!CloseHandle(hConsole))
    			PrintConsole(hConsole,
    			             L"CloseHandle() returned error %lu\n",
    			             GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file VERSION.C created in step 1., link the compiled object file VERSION.OBJ and cleanup afterwards:

    SET CL=/DNEUTRAL /GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:wmainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeVERSION.COM VERSION.C KERNEL32.LIB SHELL32.LIB USER32.LIB
    ERASE VERSION.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    VERSION.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Demonstration

Perform the following two simple steps to build the DLL VERSION.DLL with a custom VERSIONINFO resource from the resource script presented hereafter.
  1. Create the text file VERSION.RC with the following content in the directory where you built VERSION.COM:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #include <winnt.h>
    #include <winver.h>
    
    VS_VERSION_INFO VERSIONINFO
    FILEFLAGS       VS_FF_PRIVATEBUILD | VS_FF_SPECIALBUILD
    FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK
    FILEOS          VOS_NT_WINDOWS32
    FILETYPE        VFT_DLL
    FILESUBTYPE     VFT2_UNKNOWN
    FILEVERSION     0,8,1,5
    PRODUCTVERSION  0,8,1,5
    BEGIN
        BLOCK "CustomFileInfo"
        BEGIN
            VALUE "", "Empty Key"
            BLOCK "Empty Block"
            BEGIN
            END
            VALUE "Empty Value"
            BLOCK ""
            BEGIN
                VALUE "Custom", "Supercalifragilisticexpialidocious"
            END
        END
        BLOCK "StringFileInfo"
        BEGIN
            BLOCK "040904B0"
            BEGIN
                VALUE "Comments",         "https://skanthak.hier-im-netz.de/tidbits.html"
                VALUE "CompanyName",      "eSKamation"
                VALUE "FileDescription",  "Version Information Reader Resource"
                VALUE "FileVersion",      "0.8.1.5"
                VALUE "InternalName",     "VERSION"
                VALUE "LegalCopyright",   "Copyright © 2004-2024, Stefan Kanthak"
                VALUE "LegalTrademarks",  ""
                VALUE "OLESelfRegister",  "Disabled"
                VALUE "OriginalFilename", "VERSION.DLL"
                VALUE "PrivateBuild",     "NOMSVCRT"
                VALUE "ProductName",      "Version Information Reader"
                VALUE "ProductVersion",   "0.8.1.5"
                VALUE "SpecialBuild",     "Release"
                VALUE "String",           "String"
            END
        END
        BLOCK "VarFileInfo"
        BEGIN
            VALUE "Translation", 0x0409, 0x04B0
            VALUE "Variable",    0, 8, 1, 5
        END
    END
    For details and reference see the MSDN articles Resource Compiler and Resource-Definition Statements plus VERSIONINFO resource, StringFileInfo BLOCK statement and VarFileInfo BLOCK statement.
  2. Run the following four command lines to compile the resource script VERSION.RC created in step 1., link the compiled resource file VERSION.RES and cleanup afterwards:

    RC.EXE /L 0 VERSION.RC
    LINK.EXE /LINK /DLL /MACHINE:I386 /NODEFAULTLIB /NOENTRY VERSION.RES
    ERASE VERSION.OBJ VERSION.RES
    For details and reference see the MSDN articles Using RC (The RC Command Line) and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) Windows (R) Resource Compiler Version 6.1.7600.16385
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …
  3. Finally execute the console application VERSION.COM built before to enumerate and display the custom version information embedded in VERSION.DLL:

    .\VERSION.COM .\VERSION.DLL
    Module 'VERSION.DLL' loaded at address 0x00250001
    FixedFileInfo:
    	Product Version   = 0.8:1.5
    	Module Version    = 0.8:1.5
    	Module Flags	  = Private Build, Special Build
    	Module Type       = DLL
    	Module Subtype    = Undefined
    	Module Time Stamp = None
    	Target OS         = Windows NT, Windows (32-bit)
    CustomFileInfo:
    	                 = Empty Key
    	Empty Block      = 
    	Empty Value      = 
    	:
    		Custom           = Supercalifragilisticexpialidocious
    StringFileInfo:
    	040904B0:
    		Comments         = https://skanthak.hier-im-netz.de/tidbits.html
    		CompanyName      = eSKamation
    		FileDescription  = Version Information Reader Resource
    		FileVersion      = 0.8.1.5
    		InternalName     = VERSION
    		LegalCopyright   = Copyright © 2004-2024, Stefan Kanthak
    		LegalTrademarks  = 
    		OLESelfRegister  = Disabled
    		OriginalFilename = VERSION.DLL
    		PrivateBuild     = NOMSVCRT
    		ProductName      = Version Information Reader
    		ProductVersion   = 0.8.1.5
    		SpecialBuild     = Release
    		String           = String
    VarFileInfo:
    	Translation = 0x0409:1252
    	Variable = 0x0000:8 0x0001:5
    Module 'VERSION.DLL' unloaded
    Note: empty blocks and empty values have identical layout and can’t be distinguished!

UU Encoder

Purpose
Background Information
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

UU encode (binary) files for transmission via electronic mail.

Background Information

The MSDN article UUENCODE Attachment Format documents the message format.

Synopsis

UUENCODE.COM <‹input file name› >‹output file name›
ECHO ‹string› | UUENCODE.COM | MORE.COM

Downloads

The console application is available in two functional identical forms: UUENCODE.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and UUENCODE.COM, a small form without these extras.

Implementation and Build Details

UU Encoder is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: UU Encoder is a so-called filter, it reads from standard input, writes to standard output and prints error messages on standard error.

Source and Build Instructions

Perform the following two simple steps to build the console application UU Encoder from the source presented hereafter.
  1. Create the text file UUENCODE.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    #define memcpy	__movsb
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCSTR lpFormat, ...)
    {
    	CHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteFile(hFile, szOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    		return FALSE;
    
    	return dwFile == dwOutput;
    }
    
    const	CHAR	szU2U[64] = "`!\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
    
    __declspec(noreturn)
    VOID	CDECL	mainCRTStartup(VOID)
    {
    	DWORD	dwError = ERROR_SUCCESS;
    	DWORD	dwCount;
    	DWORD	dwInOut;
    	DWORD	dwInput;
    	BYTE	cbInput[45];
    	BYTE	cbOutput[sizeof(cbInput) / 3 * 4 + sizeof("\r\n")];
    	DWORD	dwOutput;
    	HANDLE	hOutput;
    	HANDLE	hInput;
    	HANDLE	hError = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hError == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    		if (hOutput == INVALID_HANDLE_VALUE)
    			PrintFormat(hError,
    			            "GetStdHandle(%ld) returned error %lu\r\n",
    			            STD_OUTPUT_HANDLE, dwError = GetLastError());
    		else
    		{
    			hInput = GetStdHandle(STD_INPUT_HANDLE);
    
    			if (hInput == INVALID_HANDLE_VALUE)
    				PrintFormat(hError,
    				            "GetStdHandle(%ld) returned error %lu\r\n",
    				            STD_INPUT_HANDLE, dwError = GetLastError());
    			else
    			{
    				memcpy(cbOutput, "\r\nbegin 644 -\r\n", dwOutput = sizeof("\r\nbegin 644 -\r\n") - 1);
    
    				for (;;)
    				{
    					if (!WriteFile(hOutput, cbOutput, dwOutput, &dwCount, (LPOVERLAPPED) NULL))
    						PrintFormat(hError,
    						            "WriteFile() returned error %lu\r\n",
    						            dwError = GetLastError());
    					else if (dwCount != dwOutput)
    						PrintFormat(hError,
    						            "WriteFile() failed, %lu of %lu characters written\r\n",
    						            dwCount, dwOutput, dwError = ERROR_WRITE_FAULT);
    					else
    						if (!ReadFile(hInput, cbInput, sizeof(cbInput), &dwInput, (LPOVERLAPPED) NULL)
    						 && (GetLastError() != ERROR_BROKEN_PIPE))
    							PrintFormat(hError,
    							            "ReadFile() returned error %lu\r\n",
    							            dwError = GetLastError());
    						else if (dwInput == 0)
    						{
    							memcpy(cbOutput, "`\r\nend\r\n", dwOutput = sizeof("`\r\nend\r\n") - 1);
    
    							if (!WriteFile(hOutput, cbOutput, dwOutput, &dwCount, (LPOVERLAPPED) NULL))
    								PrintFormat(hError,
    								            "WriteFile() returned error %lu\r\n",
    								            dwError = GetLastError());
    							else if (dwCount != dwOutput)
    								PrintFormat(hError,
    								            "WriteFile() failed, %lu of %lu characters written\r\n",
    								            dwCount, dwOutput, dwError = ERROR_WRITE_FAULT);
    						//	else
    						//		dwError = ERROR_SUCCESS;
    						}
    						else
    						{
    							dwOutput = 0;
    #if 0
    							cbOutput[dwOutput++] = szU2U[dwInput];
    #else
    							cbOutput[dwOutput++] = (BYTE) (' ' + dwInput);
    #endif
    #if 0
    							while (dwInput % 3 != 0)
    								cbInput[dwInput++] = '\0';
    #else
    							switch (dwInput % 3)
    							{
    							case 1:
    								cbInput[dwInput++] = '\0';
    							case 2:
    								cbInput[dwInput++] = '\0';
    							}
    #endif
    							dwCount = dwInput;
    							dwInput = 0;
    
    							do
    							{
    #if 0
    								dwInOut = cbInput[dwInput++];
    								dwInOut <<= 8;
    								dwInOut |= cbInput[dwInput++];
    								dwInOut <<= 8;
    								dwInOut |= cbInput[dwInput++];
    
    								cbOutput[dwOutput++] = szU2U[(dwInOut >> 18) & 63];
    								cbOutput[dwOutput++] = szU2U[(dwInOut >> 12) & 63];
    								cbOutput[dwOutput++] = szU2U[(dwInOut >> 6) & 63];
    								cbOutput[dwOutput++] = szU2U[dwInOut & 63];
    #else
    								dwInOut = _byteswap_ulong(*(DWORD *) (cbInput + dwInput));
    								dwInput += 3;
    
    								*(DWORD *) (cbOutput + dwOutput) = szU2U[dwInOut >> 26]
    								                                 | szU2U[(dwInOut >> 20) & 63] * 256
    								                                 | szU2U[(dwInOut >> 14) & 63] * 65536
    								                                 | szU2U[(dwInOut >> 8) & 63] * 16777216;
    								dwOutput += 4;
    #endif
    							} while (dwInput < dwCount);
    
    							cbOutput[dwOutput++] = '\r';
    							cbOutput[dwOutput++] = '\n';
    							continue;
    						}
    
    					break;
    				}
    
    				if (!CloseHandle(hInput))
    					PrintFormat(hError,
    					            "CloseHandle() returned error %lu\r\n",
    					            GetLastError());
    			}
    
    			if (!CloseHandle(hOutput))
    				PrintFormat(hError,
    				            "CloseHandle() returned error %lu\r\n",
    				            GetLastError());
    		}
    
    		if (!CloseHandle(hError))
    			PrintFormat(hError,
    			            "CloseHandle() returned error %lu\r\n",
    			            GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file UUENCODE.C created in step 1., link the compiled object file UUENCODE.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:mainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /FeUUENCODE.COM UUENCODE.C KERNEL32.LIB USER32.LIB
    ERASE UUENCODE.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    UUENCODE.C
    UUENCODE.C(49) : warning C4295: 'szU2U' : array is too small to include a terminating null character
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Base64 Encoder

Purpose
Background Information
Synopsis
Downloads
Implementation and Build Details
Source and Build Instructions

Purpose

Encode (binary) files for transmission via electronic mail.

Background Information

Base64 encoding is specified in RFC 3548 4648 titled The Base16, Base32, and Base64 Data Encodings.

MIME is specified in RFCs 1341, 1342, 1521 and 1522 2045, 2046, 2047, 2048 and 2049, all titled Multipurpose Internet Mail Extensions (MIME).

Synopsis

64ENCODE.COM <‹input file name› >‹output file name›
ECHO ‹string› | 64ENCODE.COM | MORE.COM

Downloads

The console application is available in two functional identical forms: 64ENCODE.EXE, a big form with embedded application manifest, version information, icon plus time-stamped digital signature, and 64ENCODE.COM, a small form without these extras.

Implementation and Build Details

Base64 Encoder is a pure Win32 console application, written in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows 2000 and newer versions of Windows NT as well as Windows PE 1.0 and newer versions.

Note: Base64 Encoder is a so-called filter, it reads from standard input, writes to standard output and prints error messages on standard error.

Source and Build Instructions

Perform the following two simple steps to build the console application Base64 Encoder from the source presented hereafter.
  1. Create the text file 64ENCODE.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    __declspec(safebuffers)
    BOOL	CDECL	PrintFormat(HANDLE hFile, [SA_FormatString(Style="printf")] LPCSTR lpFormat, ...)
    {
    	CHAR	szOutput[1024];
    	DWORD	dwOutput;
    	DWORD	dwFile;
    
    	va_list	vaInput;
    	va_start(vaInput, lpFormat);
    
    	dwOutput = wvsprintf(szOutput, lpFormat, vaInput);
    
    	va_end(vaInput);
    
    	if (dwOutput == 0)
    		return FALSE;
    
    	if (!WriteFile(hFile, szOutput, dwOutput, &dwFile, (LPOVERLAPPED) NULL))
    		return FALSE;
    
    	return dwFile == dwOutput;
    }
    
    const	CHAR	szBase64[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    		               "abcdefghijklmnopqrstuvwxyz"
    		               "0123456789+/";
    
    __declspec(noreturn)
    VOID	CDECL	mainCRTStartup(VOID)
    {
    	DWORD	dwError = ERROR_SUCCESS;
    	DWORD	dwCount;
    	DWORD	dwInOut;
    	DWORD	dwInput;
    	BYTE	cbInput[57];
    	BYTE	cbOutput[sizeof(cbInput) / 3 * 4 + sizeof("\r\n") - 1];
    	DWORD	dwOutput;
    	HANDLE	hOutput;
    	HANDLE	hInput;
    	HANDLE	hError = GetStdHandle(STD_ERROR_HANDLE);
    
    	if (hError == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    		hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    		if (hOutput == INVALID_HANDLE_VALUE)
    			PrintFormat(hError,
    			            "GetStdHandle(%s) returned error %lu\r\n",
    			            "STD_OUTPUT_HANDLE", dwError = GetLastError());
    		else
    		{
    			hInput = GetStdHandle(STD_INPUT_HANDLE);
    
    			if (hInput == INVALID_HANDLE_VALUE)
    				PrintFormat(hError,
    				            "GetStdHandle(%s) returned error %lu\r\n",
    				            "STD_INPUT_HANDLE", dwError = GetLastError());
    			else
    			{
    				for (;;)
    				{
    					if (!ReadFile(hInput, cbInput, sizeof(cbInput), &dwInput, (LPOVERLAPPED) NULL)
    					 && (GetLastError() != ERROR_BROKEN_PIPE))
    						PrintFormat(hError,
    						            "ReadFile() returned error %lu\r\n",
    						            dwError = GetLastError());
    					else if (dwInput != 0)
    					{
    						if (dwInput < sizeof(cbInput))
    							cbInput[dwInput] = '\0';
    
    						dwCount = dwInput;
    						dwInput = 0;
    						dwOutput = 0;
    
    						do
    						{
    							dwInOut = _byteswap_ulong(*(DWORD *) (cbInput + dwInput));
    							dwInput += 3;
    
    							cbOutput[dwOutput++] = szBase64[dwInOut >> 26];
    							cbOutput[dwOutput++] = szBase64[(dwInOut >> 20) & 63];
    							cbOutput[dwOutput++] = szBase64[(dwInOut >> 14) & 63];
    							cbOutput[dwOutput++] = szBase64[(dwInOut >> 8) & 63];
    						}
    						while (dwInput < dwCount);
    
    						for (dwInOut = dwOutput; dwInput > dwCount; dwCount++)
    							cbOutput[--dwInOut] = '=';
    
    						cbOutput[dwOutput++] = '\r';
    						cbOutput[dwOutput++] = '\n';
    
    						if (!WriteFile(hOutput, cbOutput, dwOutput, &dwCount, (LPOVERLAPPED) NULL))
    							PrintFormat(hError,
    							            "WriteFile() returned error %lu\r\n",
    							            dwError = GetLastError());
    						else if (dwCount != dwOutput)
    							PrintFormat(hError,
    							            "WriteFile() failed, %lu of %lu characters written\r\n",
    							            dwCount, dwOutput, dwError = ERROR_WRITE_FAULT);
    						else
    							continue;
    					}
    				//	else
    				//		dwError = ERROR_SUCCESS;
    					break;
    				}
    
    				if (!CloseHandle(hInput))
    					PrintFormat(hError,
    					            "CloseHandle() returned error %lu\r\n",
    					            GetLastError());
    			}
    
    			if (!CloseHandle(hOutput))
    				PrintFormat(hError,
    				            "CloseHandle() returned error %lu\r\n",
    				            GetLastError());
    		}
    
    		if (!CloseHandle(hError))
    			PrintFormat(hError,
    			            "CloseHandle() returned error %lu\r\n",
    			            GetLastError());
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file 64ENCODE.C created in step 1., link the compiled object file 64ENCODE.OBJ and cleanup afterwards:

    SET CL=/GAFS /Gy /O2isy /W4 /Zl
    SET LINK=/ENTRY:mainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /OSVERSION:5.0 /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE /Fe64ENCODE.COM 64ENCODE.C KERNEL32.LIB USER32.LIB
    ERASE 64ENCODE.OBJ
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    64ENCODE.C
    64ENCODE.C(49) : warning C4295: 'szBase64' : array is too small to include a terminating null character
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Import Library for 32-bit Helper Functions of Microsoft® Visual C Compiler

Purpose
Build Instructions
Usage Instructions

Purpose

For code running on the i386 processor architecture, the Microsoft Visual C compiler generates calls to the helper routines _alloca() amd _chkstk() for memory allocations on the stack, to the functions memcpy() and memset() for assignment and initialisation of arrays and structures, to the (almost) undocumented helper routines _alldiv(), _alldvrm(), _allmul(), _allrem(), _allshl() and _allshr() for signed 64-bit integer arithmetic and shift operations, to the also (almost) undocumented helper routines _aulldiv(), _aulldvrm(), _aullrem() and _aullshr() for unsigned 64-bit integer arithmetic and shift operations, and to the helper routines _CIacos(), _CIasin(), _CIatan(), _CIatan2(), _CIcos(), _CIcosh(), _CIexp(), _CIfmod(), _CIlog(), _CIlog10(), _CIpow(), _CIsin(), _CIsinh(), _CIsqrt(), _CItan(), _CItanh() and _ftol() for floating-point arithmetic.

Additionally ... memchr(), memcmp(), memcpy(), memmove(), memset(), ... strcat(), strcat_s(), strchr(), strcmp(), strcpy(), strcpy_s(), strcspn(), strlen(), strncat(), strncat_s(), strncmp(), strncpy(), strncpy_s(), strnlen(), strpbrk(), strrchr(), strspn(), strstr(), strtok_s(), strtol(), strtoul(), ... wcscat(), wcscat_s(), wcschr(), wcscmp(), wcscpy(), wcscpy_s(), wcscspn(), wcslen(), wcsncat(), wcsncat_s(), wcsncmp(), wcsncpy(), wcsncpy_s(), wcsnlen(), wcspbrk(), wcsrchr(), wcsspn(), wcsstr(), wcstol(), wcstoul(), ... available from ... on MSDN. ...

Shipped in the MSVCRT libraries, for static linkage. ...

Exported from NTDLL.dll, ... ...

Caveat: the routines for 64-bit integer arithmetic are but SLOW, and the trigonometric floating-point routines are MUCH less accurate than claimed by Intel in their Software Developer’s Manuals.

My article Fast(est) Double-Word Integer Division presents division routines that are 4 to 6 times faster and a (branch-free) multiplication routine that is 3 to 9 times faster!

Build Instructions

Run the following command lines to create the import library MSC_I386.LIB and cleanup afterwards:
LINK.EXE /LIB /DEF /EXPORT:_CIcos /EXPORT:_CIlog /EXPORT:_CIpow /EXPORT:_CIsin /EXPORT:_CIsqrt /EXPORT:_alldiv /EXPORT:_alldvrm /EXPORT:_allmul /EXPORT:_alloca_probe /EXPORT:_alloca_probe_8 /EXPORT:_alloca_probe_16 /EXPORT:_allrem /EXPORT:_allshl /EXPORT:_allshr /EXPORT:_aulldiv /EXPORT:_aulldvrm /EXPORT:_aullrem /EXPORT:_aullshr /EXPORT:_chkstk /EXPORT:_fltused /EXPORT:_ftol /EXPORT:memchr /EXPORT:memcmp /EXPORT:memcpy /EXPORT:memmove /EXPORT:memset /MACHINE:I386 /NAME:NTDLL /NODEFAULTLIB /OUT:MSC_I386.LIB
ERASE MSC_I386.EXP
Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.
Microsoft (R) Library Manager Version 10.00.40219.386
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library msc_i386.lib and object msc_i386.exp

Usage Instructions

Link the import library MSC_I386.LIB instead of or before the MSVCRT libraries.

Authenticity and Integrity

Use my (self-signed) X.509 root certificate and the (self-issued) leaf certificate to validate and verify the digital certificate and the time-stamped digital signateres of all downloaded applications.

Contact and Feedback

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‍>