Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Gimmick of the Day (or Week, Month, Year, …)

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

Directory Identifiers MSDM Product Key Reader WPBT Command Line Reader Environment Viewer Easter Date Calculator  • 

Context Menu ...

Purpose
Installation
Operation

Purpose

Demonstrate ...

Installation

Right-click the downloaded registry script CONTEXT.REG to display its context menu and click Merge to import it into the registry of your user account.

Operation

Right-click ...

Dirids

Purpose
Operation

Purpose

The setup scripts DIRID.INF and LDID.INF create the file DIRID.INI or LDID.INI respectively on the user’s desktop with all known Dirids and the pathnames they resolve to, then opens it in Windows’® text editor NotePad.exe.

Operation

Right-click the downloaded setup script DIRID.INF or LDID.INF respectively to display its context menu and click Install to run it.

MSDM Product Key Reader

Purpose
Background Information
Implementation and Build Details
Source and Build Instructions

Purpose

[Screen shot of 'MSDM Product Key Reader' running on Windows 7] The Windows® application MSDM Product Key Reader.exe displays the device-specific individual product key embedded by (big) OEMs in the MSDM table of the ACPI BIOS.
This product key is used for automatic selection of the product edition and the activation of Windows 8 and Windows 8.1 during their installation, and can since version 1511 alias Threshold 2 be used for (manual) product activation of Windows 10 too.

Background Information

The MSDM table of the ACPI BIOS is specified in a white paper available from Microsoft Software Licensing Tables (SLIC and MSDM) on MSDN.

Implementation and Build Details

MSDM Product Key Reader.exe is a pure Win32 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 2.0 and newer versions.

Source and Build Instructions

Optionally perform the following 2 simple steps to build the application MSDM Product Key Reader.exe from the source presented below.
  1. Create the text file MSDM.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2012-2022, 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
    #undef UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    typedef	struct	_msdm		// 'Microsoft Data Management' table
    {
    	DWORD	Signature;	// "MSDM" = 0x4D44534D = 'MDSM'
    	DWORD	Length;		// size of entire MSDM table: 0x00000055
    	BYTE	Revision;
    	BYTE	Checksum;	// checksum of entire MSDM table
    	CHAR	OEMId[6];	// OEM identification
    	CHAR	OEMTableId[8];
    	DWORD	OEMRevision;
    	CHAR	CreatorId[4];	// creator identification
    	DWORD	CreatorRevision;
    
    	DWORD	Version;	// 0x00000001
    	DWORD	Reserved;	// 0x00000000
    	DWORD	DataType;	// 0x00000001
    	DWORD	DataReserved;	// 0x00000000
    	DWORD	DataLength;	// 0x0000001D
    	CHAR	Data[29];	// product key: "23467-89BCD-FGHJK-MNPQR-TVWXY"
    } MSDM;
    
    __declspec(noreturn)
    __declspec(safebuffers)
    VOID	WINAPI	WinMainCRTStartup(VOID)
    {
    	MSDM	msdm;
    	UINT	size = GetSystemFirmwareTable('ACPI', 'MDSM', &msdm, sizeof(msdm));
    	DWORD	length;
    	BYTE	checksum;
    
    	if (size == 0)
    		MessageBoxEx(HWND_DESKTOP,
    		             "No \'MSDM\' table found!",
    		             "\'MSDM\' Product Key Reader",
    		             MB_OK | MB_ICONQUESTION,
    		             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    	else if (size > sizeof(msdm))
    		MessageBoxEx(HWND_DESKTOP,
    		             "Error reading \'MSDM\' table!",
    		             "\'MSDM\' Product Key Reader",
    		             MB_OK | MB_ICONERROR,
    		             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    	else
    	{
    		for (length = msdm.Length, checksum = 0;
    		     length > 0;
    		     checksum += ((BYTE *) &msdm)[--length])
    			continue;
    
    		if ((checksum != 0)
    		 || (msdm.Version != 1)
    		 || (msdm.Reserved != 0)
    		 || (msdm.DataType != 1)
    		 || (msdm.DataReserved != 0)
    		 || (msdm.DataLength != sizeof(msdm.Data)))
    			MessageBoxEx(HWND_DESKTOP,
    			             "Invalid or unknown \'MSDM\' table found!",
    			             "\'MSDM\' Product Key Reader",
    			             MB_OK | MB_ICONWARNING,
    			             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    		else
    		{
    			msdm.Data[sizeof(msdm.Data)] = '\0';
    
    			MessageBoxEx(HWND_DESKTOP,
    			             msdm.Data,
    			             "\'MSDM\' Product Key Reader",
    			             MB_OK | MB_ICONINFORMATION,
    			             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    		}
    	}
    
    	ExitProcess(GetLastError());
    }
  2. Run the following four command lines to compile the source file MSDM.C created in step 1., link the compiled object file MSDM.OBJ and cleanup afterwards:

    SET CL=/GA /GF /GS /Gy /O1 /Os /Oy /W4 /Zl
    SET LINK=/DEFAULTLIB:KERNEL32.LIB /DEFAULTLIB:USER32.LIB /DYNAMICBASE /ENTRY:WinMainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OSVERSION:5.2 /OUT:"MSDM Product Key Reader.exe" /RELEASE /SUBSYSTEM:WINDOWS,5.2 /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE MSDM.C
    ERASE MSDM.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.
    
    MSDM.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

WPBT Command Line Reader

Purpose
Background Information
Implementation and Build Details
Source and Build Instructions

Purpose

The Windows® application WPBT Command Line Reader.exe displays the command line embedded in the WPDT table of the ACPI BIOS.

Background Information

The WPBT table of the ACPI BIOS is specified in a white paper available from Windows Hardware Dev Center Archive on MSDN.

Implementation and Build Details

WPBT Command Line Reader.exe is a pure Win32 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 2.0 and newer versions.

Source and Build Instructions

Optionally perform the following 2 simple steps to build the application WPBT Command Line Reader.exe from the source presented below.
  1. Create the text file WPBT.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2017-2022, 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>
    
    #pragma pack(push, 1)
    typedef	struct	_wpbt		// Windows Platform Binary Table
    {
    	DWORD	Signature;	// "WPBT" = 0x54445057 = 'TBPW'
    	DWORD	Length;		// size of entire WPBT
    	BYTE	Revision;
    	BYTE	Checksum;	// checksum of entire WPBT
    	CHAR	OEMId[6];	// OEM identification
    	CHAR	OEMTableId[8];
    	DWORD	OEMRevision;
    	CHAR	CreatorId[4];	// creator identification
    	DWORD	CreatorRevision;
    
    	DWORD	HandoffMemorySize;
    	DWORD64	HandoffMemoryLocation;
    	BYTE	ContentLayout;
    	BYTE	ContentType;
    	WORD	CommandLineLength;
    	WCHAR	CommandLine[32768];
    } WPBT;
    #pragma pack(pop)
    
    __declspec(noreturn)
    __declspec(safebuffers)
    VOID	WINAPI	wWinMainCRTStartup(VOID)
    {
    	WPBT	wpbt;
    	UINT	size = GetSystemFirmwareTable('ACPI', 'TBPW', &wpbt, sizeof(wpbt));
    	DWORD	length;
    	BYTE	checksum;
    
    	if (size == 0)
    		MessageBoxEx(HWND_DESKTOP,
    		             L"No \'WPBT\' found!",
    		             L"\'WPBT\' Command Line Reader",
    		             MB_OK | MB_ICONQUESTION,
    		             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    	else if (size > sizeof(wpbt))
    		MessageBoxEx(HWND_DESKTOP,
    		             L"Error reading \'WPBT\'!",
    		             L"\'WPBT\' Command Line Reader",
    		             MB_OK | MB_ICONERROR,
    		             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    	else
    	{
    		for (length = wpbt.Length, checksum = 0;
    		     length > 0;
    		     checksum += ((BYTE *) &wpbt)[--length])
    			continue;
    
    		if ((checksum != 0)
    		 || (wpbt.Signature != 'TBPW')
    		 || (wpbt.Length < sizeof(wpbt) - sizeof(wpbt.CommandLine))
    		 || (wpbt.ContentLayout != 0x01)
    		 || (wpbt.ContentType != 0x01))
    			MessageBoxEx(HWND_DESKTOP,
    			             L"Invalid or unknown \'WPBT\' found!",
    			             L"\'WPBT\' Command Line Reader",
    			             MB_OK | MB_ICONWARNING,
    			             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    		else
    		{
    			wpbt.CommandLine[wpbt.CommandLineLength / sizeof(*wpbt.CommandLine)] = L'\0';
    
    			MessageBoxEx(HWND_DESKTOP,
    			             wpbt.CommandLine,
    			             L"\'WPBT\' Command Line Reader",
    			             MB_OK | MB_ICONINFORMATION,
    			             MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
    		}
    	}
    
    	ExitProcess(GetLastError());
    }
  2. Run the following four command lines to compile the source file WPBT.C created in step 1., link the compiled object file WPBT.OBJ and cleanup afterwards:

    SET CL=/GA /GF /GS /Gs69632 /Gy /O1 /Os /Oy /W4 /Zl
    SET LINK=/DEFAULTLIB:KERNEL32.LIB /DEFAULTLIB:USER32.LIB /DYNAMICBASE /ENTRY:wWinMainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OSVERSION:5.2 /OUT:"WPBT Command Line Reader.exe" /RELEASE /STACK:1048576,65536 /SUBSYSTEM:WINDOWS,5.2 /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE WPBT.C
    ERASE WPBT.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.
    
    WPBT.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Environment Viewer

Purpose
Background Information
Implementation and Build Details
Source and Build Instructions

Purpose

The Windows® application Environment Viewer.exe displays the environment blocks of the (current) process, the (current) user and the system. [Screen shot of 'Process Environment Block' on Windows 7] [Screen shot of 'User Environment Block' on Windows 7] [Screen shot of 'System Environment Block' on Windows 7]

Background Information

The MSDN articles Environment Variables and User Environment Variables specify how environment variables are processed:
Every process has an environment block that contains a set of environment variables and their values. There are two types of environment variables: user environment variables (set for each user) and system environment variables (set for everyone).

By default, a child process inherits the environment variables of its parent process. […]

[…] To programmatically add or modify system environment variables, add them to the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment registry key, […]

Environment variables specify search paths for files, directories for temporary files, application-specific options, and other similar information. The system maintains an environment block for each user and one for the computer. The system environment block represents environment variables for all users of the particular computer. A user's environment block represents the environment variables the system maintains for that particular user, including the set of system environment variables.

By default, each process receives a copy of the environment block for its parent process. Typically, this is the environment block for the user who is logged on. […]

Both articles but fail to tell that two kinds of user environment variables exist, permanent and volatile, that volatile environment variables obscure permanent environment variables with the same name, how to add or modify them, and where they are stored: permanent user environment variables are stored in the registry key HKEY_CURRENT_USER\Environment alias HKEY_USERS\‹security identifier›\Environment, while volatile user environment variables are stored in the (volatile) registry key HKEY_CURRENT_USER\Volatile Environment alias HKEY_USERS\‹security identifier›\Volatile Environment, where they are created during user logon and discarded when the user logs off.

The articles also fail to tell that not all system environment variables are stored in the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment: the system environment variables ALLUSERSPROFILE, COMPUTERNAME, PUBLIC, CommonProgramFiles, CommonProgramFiles(x86), CommonProgramW6432, ProgramData, ProgramFiles, ProgramFiles(x86), ProgramW6432, SystemDrive and SystemRoot are created programmatically.

And they fail to tell that user environment variables obscure system environment variables of the same name – with but two notable exceptions:

Implementation and Build Details

Environment Viewer.exe is a pure Win32 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 2.0 and newer versions.

Source and Build Instructions

Optionally perform the following 2 simple steps to build the application Environment Viewer.exe from the source presented below.
  1. Create the text file GIMMICK.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2022, 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>
    
    __declspec(noreturn)
    VOID	WINAPI	wWinMainCRTStartup(VOID)
    {
    	HANDLE	hToken;
    	DWORD	dwString;
    	LPWSTR	lpString;
    	LPCWSTR	lpBlock = GetEnvironmentStrings();
    
    	if (lpBlock != NULL)
    	{
    		for (lpString = lpBlock;
    		     lpString[0] != L'\0';
    		     lpString[dwString = wcslen(lpString)] = L'\n', lpString += dwString + 1)
    			continue;
    
    		MessageBoxEx(HWND_DESKTOP,
    		             lpBlock,
    		             L"Process Environment Block",
    		             MB_OK,
    		             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
    
    		FreeEnvironmentStrings(lpBlock);
    	}
    
    	if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
    	{
    		if (CreateEnvironmentBlock(&lpBlock, hToken, FALSE))
    		{
    			for (lpString = lpBlock;
    			     lpString[0] != L'\0';
    			     lpString[dwString = wcslen(lpString)] = L'\n', lpString += dwString + 1)
    				continue;
    
    			MessageBoxEx(HWND_DESKTOP,
    			             lpBlock,
    			             L"User Environment Block",
    			             MB_OK,
    			             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
    
    			DestroyEnvironmentBlock(lpBlock);
    		}
    
    		CloseHandle(hToken);
    	}
    
    	if (CreateEnvironmentBlock(&lpBlock, (HANDLE) NULL, FALSE))
    	{
    		for (lpString = lpBlock;
    		     lpString[0] != L'\0';
    		     lpString[dwString = wcslen(lpString)] = L'\n', lpString += dwString + 1)
    			continue;
    
    		MessageBoxEx(HWND_DESKTOP,
    		             lpBlock,
    		             L"System Environment Block",
    		             MB_OK,
    		             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
    
    		DestroyEnvironmentBlock(lpBlock);
    	}
    
    	ExitProcess(GetLastError());
    }
  2. Run the following four command lines to compile the source file GIMMICK.C created in step 1., link the compiled object file GIMMICK.OBJ and cleanup afterwards:

    SET CL=/GA /GF /GS /Gy /O1 /Os /Oy /W4 /wd4090 /Zl
    SET LINK=/DEFAULTLIB:ADVAPI32.LIB /DEFAULTLIB:KERNEL32.LIB /DEFAULTLIB:USER32.LIB /DEFAULTLIB:USERENV.LIB /DYNAMICBASE /ENTRY:wWinMainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OSVERSION:5.0 /OUT:"Environment Viewer.exe" /RELEASE /SUBSYSTEM:WINDOWS,5.0 /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE GIMMICK.C
    ERASE GIMMICK.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.
    
    GIMMICK.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    …

Easter Date Calculator

Purpose
Variant 1
Variant 2
Variant 3
Variant 4
Operation

Purpose

Calculate the Easter date and display all depending movable feasts.

Variant 1

Heiner Lichtenberg’s revision of Gauss’ formula, published November 1997 as Zur Interpretation der Gaußschen Osterformel und ihrer Ausnahmeregeln in Historia Mathematica, volume 24, issue 4, on pages 441-444:
Rem Copyleft © 1999-2022, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>

Y = Year(Now())
Rem Revision of Gauss' Formula
Rem Heiner Lichtenberg, Zur Interpretation der Gaußschen Osterformel und ihrer Ausnahmeregeln
Rem Historia Mathematica, Volume 24, Issue 4, November 1997, Pages 441-444
C = Y \ 100
M = 15 + (C * 3 + 3) \ 4 - (C * 8 + 13) \ 25
S = 2 - (C * 3 + 3) \ 4
A = Y Mod 19
D = (A * 19 + M) Mod 30
R = D \ 29 + (D \ 28 - D \ 29) * (A \ 11)
M = 21 + D - R					' Full Moon in March
S = 7 - (Y + Y \ 4 + S) Mod 7			' First Sunday in March
E = M + 7 - (M - S) Mod 7

SetLocale("en-GB")

MsgBox "Ash Wednesday"   & vbTab & DateSerial(Y, 3, E - 46) & vbNewLine _
     & "Maundy Thursday" & vbTab & DateSerial(Y, 3, E - 3)  & vbNewLine _
     & "Good Friday"     & vbTab & DateSerial(Y, 3, E - 2)  & vbNewLine _
     & "Easter Sunday"   & vbTab & DateSerial(Y, 3, E)      & vbNewLine _
     & "Easter Monday"   & vbTab & DateSerial(Y, 3, E + 1)  & vbNewLine _
     & "Ascension Day"   & vbTab & DateSerial(Y, 3, E + 39) & vbNewLine _
     & "Whit Sunday"     & vbTab & DateSerial(Y, 3, E + 49) & vbNewLine _
     & "Whit Monday"     & vbTab & DateSerial(Y, 3, E + 50) & vbNewLine _
     & "Trinity Sunday"  & vbTab & DateSerial(Y, 3, E + 56) & vbNewLine _
     & "Corpus Christi"  & vbTab & DateSerial(Y, 3, E + 60), vbOKOnly, _
       "Movable Christian Feast Days in " & Y

Variant 2

Formula of an anonymous author, published April 20, 1876, as To Find Easter in Nature, volume 13, issue 338, on page 487:
Rem Copyleft © 1999-2022, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>

Y = Year(Now())
Rem Anonymous' Formula
Rem Nature, Volume 13, Issue 338, April 20, 1876, Page 487
A = Y Mod 19
B = Y \ 100
C = Y Mod 100
D = B \ 4
E = B Mod 4
F = (B + 8) \ 25
G = (B - F + 1) \ 3
H = (19 * A + B - D - G + 15) Mod 30
I = C \ 4
J = C Mod 4
K = (E * 2 + I * 2 - H - J + 32) Mod 7
L = (A + H * 11 + K * 22) \ 451
M = H + K - L * 7 + 114
N = M \ 31
O = M Mod 31

SetLocale("en-GB")

MsgBox "Ash Wednesday"   & vbTab & DateSerial(Y, N, O - 45) & vbNewLine _
     & "Maundy Thursday" & vbTab & DateSerial(Y, N, O - 2)  & vbNewLine _
     & "Good Friday"     & vbTab & DateSerial(Y, N, O - 1)  & vbNewLine _
     & "Easter Sunday"   & vbTab & DateSerial(Y, N, O + 1)  & vbNewLine _
     & "Easter Monday"   & vbTab & DateSerial(Y, N, O + 2)  & vbNewLine _
     & "Ascension Day"   & vbTab & DateSerial(Y, N, O + 40) & vbNewLine _
     & "Whit Sunday"     & vbTab & DateSerial(Y, N, O + 50) & vbNewLine _
     & "Whit Monday"     & vbTab & DateSerial(Y, N, O + 51) & vbNewLine _
     & "Trinity Sunday"  & vbTab & DateSerial(Y, N, O + 57) & vbNewLine _
     & "Corpus Christi"  & vbTab & DateSerial(Y, N, O + 61), vbOKOnly, _
       "Movable Christian Feast Days in " & Y

Variant 3

Revision of Anonymous’ formula by T. H. O’Beirne, published March 30, 1961, as How ten divisions lead to Easter in New Scientist, volume 9, issue 228, on page 828:
Rem Copyleft © 1999-2022, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>

Y = Year(Now())
Rem T. H. O'Beirne, How ten divisions lead to Easter
Rem New Scientist, Volume 9, Issue 228, March 30, 1961, Page 828
A = Y Mod 19
B = Y \ 100
C = Y Mod 100
D = B \ 4
E = B Mod 4
G = (B * 8 + 13) \ 25
H = (19 * A + B - D - G + 15) Mod 30
I = C \ 4
J = C Mod 4
K = (E * 2 + I * 2 - H - J + 32) Mod 7
L = (A + H * 11 + K * 22) \ 451
M = (A + H * 11 + L * 19) \ 433
N = (H + L - M * 7 + 90) \ 25
P = (H + L - M * 7 + N * 33 + 19) Mod 32

SetLocale("en-GB")

MsgBox "Ash Wednesday"   & vbTab & DateSerial(Y, N, P - 46) & vbNewLine _
     & "Maundy Thursday" & vbTab & DateSerial(Y, N, P - 3)  & vbNewLine _
     & "Good Friday"     & vbTab & DateSerial(Y, N, P - 2)  & vbNewLine _
     & "Easter Sunday"   & vbTab & DateSerial(Y, N, P)      & vbNewLine _
     & "Easter Monday"   & vbTab & DateSerial(Y, N, P + 1)  & vbNewLine _
     & "Ascension Day"   & vbTab & DateSerial(Y, N, P + 39) & vbNewLine _
     & "Whit Sunday"     & vbTab & DateSerial(Y, N, P + 49) & vbNewLine _
     & "Whit Monday"     & vbTab & DateSerial(Y, N, P + 50) & vbNewLine _
     & "Trinity Sunday"  & vbTab & DateSerial(Y, N, P + 56) & vbNewLine _
     & "Corpus Christi"  & vbTab & DateSerial(Y, N, P + 60), vbOKOnly, _
       "Movable Christian Feast Days in " & Y

Variant 4

J. M. Oudin’s Formula, published 1940:
Rem Copyleft © 1999-2022, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>

Y = Year(Now())
Rem Oudin's Formula
C = Y \ 100					' Century
G = Y Mod 19					' Golden number - 1
H = (C - C \ 4 - (C - (C - 17) \ 25) \ 3 + G * 19 + 15) Mod 30
I = H - (H \ 28) * (1 - (H \ 28) * (29 \ (H + 1)) * ((21 - G) \ 11))
J = (Y + Y \ 4 + I + 2 - C + C \ 4) Mod 7	' Weekday of Paschal full Moon
L = I - J
M = (L + 40) \ 44 + 3
D = L + 28 - (M \ 4) * 31

SetLocale("en-GB")

MsgBox "Ash Wednesday"   & vbTab & DateSerial(Y, M, D - 46) & vbNewLine _
     & "Maundy Thursday" & vbTab & DateSerial(Y, M, D - 3)  & vbNewLine _
     & "Good Friday"     & vbTab & DateSerial(Y, M, D - 2)  & vbNewLine _
     & "Easter Sunday"   & vbTab & DateSerial(Y, M, D)      & vbNewLine _
     & "Easter Monday"   & vbTab & DateSerial(Y, M, D + 1)  & vbNewLine _
     & "Ascension Day"   & vbTab & DateSerial(Y, M, D + 39) & vbNewLine _
     & "Whit Sunday"     & vbTab & DateSerial(Y, M, D + 49) & vbNewLine _
     & "Whit Monday"     & vbTab & DateSerial(Y, M, D + 50) & vbNewLine _
     & "Trinity Sunday"  & vbTab & DateSerial(Y, M, D + 56) & vbNewLine _
     & "Corpus Christi"  & vbTab & DateSerial(Y, M, D + 60), vbOKOnly, _
       "Movable Christian Feast Days in " & Y

Operation

Create a text file GIMMICK.VBS with one of the VBScripts presented above in an arbitrary directory, then execute it per double-click.

Contact

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

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

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

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

Terms and Conditions

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

Data Protection Declaration

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

The web service is operated and provided by

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

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


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