WINSRV User API Routines

As a CSRSS Server DLL, the user server in WINSRV.DLL implements API routines which a CSRSS client can call through the NTDLL function CsrClientCallServer and which other DLLs in the server process may be allowed to call through the CSRSRV function CsrCallServerFromServer. Although most CSRSS server DLLs allow most API routines to be called from the server process, the user server does not. For the following table, an API routine is invalid as a server call unless explicitly noted as valid.

The caller selects a routine by specifying an API number. The high word is a 0-based index for the user server as a CSRSS server DLL. Known clients and WINSRV itself (for the slightly different matter of accessing server-specific per-process data) assume that this index is 3. Whatever symbolic names Microsoft has for the API numbers as constants to use when calling the corresponding API routines are not known. The tables below give only the name of each API routine as known from public symbol files for WINSRV.DLL.

In an immediate sense, the user server is here named the user server because of the function, named UserServerDllInitialization, that WINSRV exports for CSRSRV is to call for initialising this server rather than the one or two others that WINSRV has hosted. The intended caller of by far the most API routines that the user server has ever implemented is USER32.DLL.

User-Mode Windowing

In early versions, the user server does almost all the work that is nowadays done in kernel mode by WIN32K.SYS. Cross-process calls to the user server’s API routines must have been very frequent. Decent performance would be unachievable if every one of them is a Local Procedure Call (LPC) through the CsrClientCallServer function. In these versions, the user server’s API routines are written on the assumption that they are reached through something named QLPC that exchanges messages—indeed, batches of messages—in shared memory and is managed from the client side by calling CsrClientSendMessage instead.

If only in version 3.10, the user server’s API routines may in principle have the usual prototype


for being called by CSRSRV, but the first argument is in fact the address of a CSR_QLPC_API_MSG, not of a CSR_API_MSG. Version 3.51 throws this away in the apparent pursuit of yet more efficiency. The user server in this version sets a routine into the ApiDispatchRoutine member of the CSR_SERVER_DLL such that API routines are not called from CSRSRV. Their distribution is instead an internal matter for WINSRV. One effect is that some (but not all) API routines in version 3.51 have the prototype


Plainly none of this internal detail matters to a client and wouldn’t matter here if the functionality of the API routines could instead be described by naming the API numbers. It’s far from clear that the API routines are even worth listing: were a list to be made, it might go something like…

API Number API Routine Versions Remarks
0x00030000 (3.51) __ChildWindowFromPointEx 3.51 only  
0x00030001 (3.51) __CsCreateCaret 3.51 only previously 0x003001B
0x00030002 (3.51) __CsEndPaint 3.51 only previously 0x00030021
0x00030003 (3.51) __CsExcludeUpdateRgn 3.51 only previously 0x00030023
0x00030004 (3.51) __CsGetCPD 3.51 only previously 0x0003014F
TO BE DONE      
0x00030013 (3.51) __ServerGetWindowLong 3.51 previously 0x00030150
TO BE DONE      
0x00030000 (3.10);
0x0003006E (3.51)
__ActivateKeyboardLayout 3.10 to 3.51  
0x00030001 (3.10);
0x0003006F (3.51)
__AppendMenu 3.10 to 3.51  
0x00030002 (3.10) __ArrangeIconicWindows 3.10 only  
0x00030003 (3.10);
0x00030070 (3.51)
__AttachThreadInput 3.10 to 3.51  
0x00030004 (3.10) __BeginDeferWindowPos 3.10 only  
0x00030005 (3.10);
0x00030071 (3.51)
__BringWindowToTop 3.10 to 3.51  
0x00030006 (3.10) __CalcChildScroll 3.10 only  
0x00030007 (3.10);
0x00030072 (3.51)
__CallMsgFilter 3.10 to 3.51  
TO BE DONE      
0x0003001B (3.10) __CsCreateCaret 3.10 only next as 0x00030001
TO BE DONE      
0x00030021 (3.10) __CsEndPaint 3.10 only next as 0x00030002
TO BE DONE      
0x00030023 (3.10) __CsExcludeUpdateRgn 3.10 only next as 0x00030003
TO BE DONE      
0x0003014F (3.10) __CsGetCPD 3.10 only next as 0x00030004
0x00030150 (3.10) __ServerGetWindowLong 3.10 only next as 0x00030013
0x00030151 (3.10) __TransferInputBits 3.10 only  
0x00030152 (3.10);
0x00030102 (3.51)
__ResyncKeyState 3.10 to 3.51  
TO BE DONE      

Kernel-Mode Windowing

The change to in-process calls in kernel mode left the user server with a greatly reduced role in version 4.0. Not only are there many fewer API routines but they revert to the usual prototype:


Pehaps to avoid all misunderstanding, not that mismatching low-level DLLs such as CSRSRV and USER32 seems likely ever to produce anything but chaos, the API numbers begin with a non-zero base for the low word.

API Number API Routine Versions Remarks
0x00030A00 (4.0);
SrvExitWindowsEx 4.0 and higher conditionally valid as server call in 5.0 to 5.2;
valid as server call in 6.0 and higher
0x00030A01 (4.0);
SrvEndTask 4.0 and higher  
0x00030A02 (4.0) SrvInitSoundDriver 4.0 only valid as server call
0x00030A03 (4.0) SrvPlaySound 4.0 only valid as server call
0x00030A04 (4.0);
SrvLogon 4.0 and higher  
0x00030A05 (4.0) SrvServiceMessageBox 4.0 only  
0x00030A06 (4.0);
0x00030403 (5.0 to 6.0)
SrvRegisterServicesProcess 4.0 to 6.0  
0x00030A07 (4.0);
0x00030404 (5.0 to 6.0);
SrvActivateDebugger 4.0 and higher  
0x00030A08 (4.0);
0x00030405 (5.0 to 6.0)
SrvGetThreadConsoleDesktop 4.0 to 6.0 valid as server call
0x00030406 (5.0 to 6.0);
0x00030404 (6.1 to 6.2)
SrvDeviceEvent 5.0 to 6.2  
0x00030407 (5.0 to 6.0) SrvRegisterLogonProcess 5.0 to 6.0  
0x00030408 (5.0 to 5.1) SrvWin32HeapStat 5.0 to 5.1 succeeds trivially
0x00030409 (5.0 to 5.1) SrvWin32HeapFail 5.0 to 5.1 succeeds trivially
0x0003040A (5.1);
0x00030408 (5.2 to 6.0);
0x00030405 (6.1 to 6.2);
SrvCreateSystemThreads 5.1 and higher  
0x00030409 (5.2 to 6.0);
0x00030406 (6.1 to 6.2);
SrvRecordShutdownReason 5.2 and higher valid as server call
0x0003040A (6.0);
0x00030407 (6.1 to 6.2);
SrvCancelShutdown 6.0 and higher  
0x00030408 (6.1) SrvConsoleHandleOperation 6.1 only  
0x0003040B (6.0);
0x00030409 (6.1)
SrvGetSetShutdownBlockReason 6.0 to 6.1  

In versions 5.0 to 5.2 inclusive, the API numbered 0x00030400 (for exiting Windows) is enabled for server-side calls when running on a Terminal Server (in the sense of having the 0x0010 bit set in the product suite).

The two routines SrvWin32HeapStat and SrvWin32HeapFail both succeed trivially and have the same address. It is not known which has which API number! Presumably, they are not trivial in some checked build.