Remko Weijnen's Blog (Remko's Blog)

About Virtualization, VDI, SBC, Application Compatibility and anything else I feel like

Archive for the ‘Delphi’ Category


If you read the MSDN documentation of WM_KEYDOWN and WM_KEYUP you can see that those message require us to interpret lParam as a bitfield:

Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.

Specifies the repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. The repeat count is always one for a WM_KEYUP message.
Specifies the scan code. The value depends on the OEM.
Specifies whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
Reserved; do not use.
Specifies the context code. The value is always 0 for a WM_KEYUP message.
Specifies the previous key state. The value is always 1 for a WM_KEYUP message.
Specifies the transition state. The value is always 1 for a WM_KEYUP message.

I was looking for a convenient way to get and read the bits and this is what I made up:

I’m working on a new build of TSAdminEx for which I need to query the total amount of physical memory. Locally we can use the GlobalMemoryStatusEx API but there’s no API to do this remotely. It would be possible using WMI but I decided not to use that because I dislike it because of it’s slowness and I need support for older OS versions which might not have WMI.

So I found in the registry the following key:

HKLM\HARDWARE\RESOURCEMAP\System Resources\Physical Memory

It has a value .Translated of type RES_RESOURCE_LIST which seems undocumented besides stating that it exists. Regedit knows how to handle it though. If you doubleclick on the key you will see something like this:


In part 1 I showed how to create and open objects in Terminal Server Sessions. However, these are not all of the possible places where you can place objects via documented kernel32.dll functions.

If we look into Winobj again, we notice, that every BaseNamedObjects directory has a subdirectory named Restricted. To be honest, I do not know why it’s created; it’s security allows object creation for LocalSystem and RESTRICTED special user (in windows 2000, Everyone can also create objects in it). So, we can use it as prefix for object creation, for example, Restricted\MyAppEvent: RestrictedObject

Of course, you can still use Global, Local, or Session links (more…)

As you know, many kernel32.dll functions, which are working with named objects, like OpenEvent, can be used to work with global and local objects. So what are global and local objects? Global objects are created in session 0 and are actually located in the \BaseNamedObjects directory, while local objects are created in the caller’s session (for example in the \Sessions\5\BaseNamedObjects directory (for session 0, global and local has no meaning since they point to the same object)). MSDN says that you can access only the objects in your own session(via the Local\ prefix) and in session 0 (via the Global\ prefix). But what if you need to access an object in another session? (more…)

Locking a workstation – part 2

In part 1 I showed how winlogon.exe registers its process and main window handle.

In the SasCreate function, winlogon.exe registers hotkeys like this:

Did you notice the MOD_SAS constant? (more…)

Locking a workstation – part 1

Win32 API provides only 1 function for locking workstation, named LockWorkstation. What does it do and how we can use it?

When a new session is started, smss.exe invokes winlogon.exe. It registers its process id in win32k.sys by calling RegisterLogonProcess. It has this prototype: (more…)

Converting a volume name to a device name

Windows has a couple of different formats for volume names but it is unclear how to convert a Volumename (example: \\?\Volume{GUID}\) to a DeviceName (example: \Device\HarddiskVolume1).

I found at that you can use the QueryDosDevice function but you need to remove the preceeding \\?\ and the trailing \ of the VolumeName:


Let’s write our own Credential Server implementation.

At first, we need to create a named pipe with a unique name. Let’s construct the pipe name using a GUID – this should be unique, but we can do it in a cycle to be absolutely sure: (more…)

I think many of you have got experience with multiple Terminal Server Sessions in windows XP, also called Fast User Switching (FUS). Let’s get inside this cool feature.

How does FUS work? Each session has its own winlogon.exe. It draws the same interface which looks like the screenshot below:



Terminal Server Internals

Hello, my name is Danila Galimov and i will write here sometimes 🙂

My first post is about communications between Terminal Server sessions and Terminal Server service process (termsrv.exe/dll). Terminal Server service needs to communicate with each session for many tasks, such as sending window message, getting message reply and so on. So, on init, Terminal Server creates a SmSsWinStationApiPort port in global namespace and runs a few WinStationLpcThread threads, which are listening on port and are used to process port messages. When csrss.exe is started, it parses its command line, which usually looks like:

%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=4096,4096,1024 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16

and loads the required dlls (winsrv.dll in our case). Initialization of winsrv.dll creates a thread, which connects to SmSsWinStationApiPort port and does the loop for processing Terminal Server messages until it receives WinStationTerminate message.

We’ll try to fool Terminal Server (more…)