TDB

The TDB structure (formally tagTDB) represents what is apparently called a task. Its name perhaps stands for something like Task Data Block. The tasks in question are 16-bit Windows applications. These long pre-date the development of pre-emptive multi-tasking even of virtual-8086 DOS machines on Windows 3.0 Enhanced Mode in the late 1980s. The nature of Windows back then is that 16-bit Windows applications were written for co-operative multi-tasking. For almost all practical purposes on an old-enough Windows they do own the machine except when they execute inside a “system” function that yields. If a new Windows does not provide at least a convincing illusion of the old execution environment, then they won’t behave as expected and especially not when run concurrently.

The only known way that WIN32K creates a TDB starts with the exported but undocumented USER32 function UserRegisterWowHandlers. Calling this function supplies routines for USER32 to call, but it also fills a table of routines for more calls to USER32. One of these routines is named in symbol files as InitTask. Threads in the calling process can then each call this routine to initialise as a WOW task.

There can be just the one TDB for each thread. The address of a thread’s TDB is held in the ptdb member of the THREADINFO. Moroever, task initialisation is permitted only for threads whose process already has a WOWPROCESSINFO (which is created by the process’s having called another of those USER32 routines). In version 3.51 and higher, each WOW process can have a single-linked list of TDB structures starting from the ptdbHead member of the WOWPROCESSINFO and linked through the ptdbNext member of the TDB in increasing order of their nPriority members. Version 3.10 has a TDB list too, just not a separate one for each WOW process.

Version Size (x86) Size (x64)
3.10 to 3.51 0x14  
4.0 to 10.0 0x18 0x28

From the type information in symbol files for WIN32K in Windows 7, it appears that the structure is defined in 64-bit Windows though it doesn’t support the 16-bit tasks that the structure exists for. Starting with version 6.0, ever more of the supporting code disappears. By version 6.2, the system service NtUserInitTask fails trivially and it is entirely plausible that the 64-bit WIN32K has no code for creating a TDB.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 0x00
TDB *ptdbNext;
all  
0x04 (3.51)   unaccounted 3.51 only  
0x04 (3.10);
0x08 (3.51);
0x04
0x08
INT nEvents;
all  
0x08 (3.10);
0x0C (3.51);
0x08
0x0C
INT nPriority;
all  
0x0C (3.10)  
HANDLE hIdleEvent;
3.10 only next in WOWTHREADINFO
0x10 (3.10 to 3.51);
0x0C
0x10
THREADINFO *pti;
all last member in 3.10;
last member in 3.51
0x10 0x18
WOWTHREADINFO *pwti;
4.0 and higher  
0x14  
ULONG hTaskWow;
4.0 only previously in THREADINFO;
last member in 4.0
0x20
USHORT hTaskWow;
5.0 and higher  
0x16 0x22
USHORT TDB_Flags;
5.0 and higher  

Microsoft’s name for the event handle that the TDB keeps in version 3.10 is not known. This version does not provide for running different 16-bit tasks in different processes and does not have a WOWTHREADINFO structure. It is here proposed that the event handle in the WOWTHREADINFO originated here in the TDB and kept its name.