Geoff Chappell, Software Analyst
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.