$theTitle=wp_title(" - ", false); if($theTitle != "") { ?>
About Virtualization, VDI, SBC, Application Compatibility and anything else I feel like
A while ago I was doing some research for Magic Filter when I stumbled upon something interesting within Receiver.
Inside wfica32.exe is a function called _Eng_RunExecutableOnExit. That name caught my interest, I’ve made it a little more readable with Ida Pro:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | LSTATUS __cdecl _Eng_RunExecutableOnExit() { LSTATUS result; // eax@1 size_t v1; // eax@8 bool v2; // zf@10 char *v3; // eax@10 const CHAR *v4; // edi@11 size_t v5; // eax@13 HKEY hKey; // [sp+4h] [bp-38Ch]@1 DWORD cbData; // [sp+8h] [bp-388h]@2 DWORD Type; // [sp+Ch] [bp-384h]@2 BOOL bRunOnExit; // [sp+10h] [bp-380h]@2 struct _PROCESS_INFORMATION ProcessInformation; // [sp+14h] [bp-37Ch]@15 struct _STARTUPINFOA StartupInfo; // [sp+24h] [bp-36Ch]@15 char Src[4]; // [sp+68h] [bp-328h]@8 char v13; // [sp+6Fh] [bp-321h]@10 char Str; // [sp+70h] [bp-320h]@5 const CHAR ApplicationName; // [sp+71h] [bp-31Fh]@5 CHAR CommandLine; // [sp+178h] [bp-218h]@8 char v17; // [sp+179h] [bp-217h]@8 char lpApplicationName; // [sp+284h] [bp-10Ch]@5 hKey = 0; result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Citrix\\XenDesktop", 0, KEY_READ, &hKey); if ( !result ) { bRunOnExit = 0; cbData = REG_DWORD; if ( !RegQueryValueExA(hKey, "XDControlRunOnExit", 0, &Type, (LPBYTE)&bRunOnExit, &cbData) && Type == REG_DWORD ) { if ( bRunOnExit ) { lpApplicationName = 0; memset(&lpApplicationName + 1, 0, 260u); Str = 0; memset((void *)&ApplicationName, 0, 260u); cbData = 260; if ( !RegQueryValueExA(hKey, "XDControlExe", 0, &Type, (LPBYTE)&lpApplicationName, &cbData) && (Type == REG_SZ || Type == REG_EXPAND_SZ) ) { strcpy(Src, "ctx "); CommandLine = 0; memset(&v17, 0, 265u); _strcpy_s(&CommandLine, 266u, Src); ExpandEnvironmentStringsA(&lpApplicationName, &Str, 0x105u); v1 = _strnlen(&Str, 0x7FFFFFFFu); if ( v1 > 0 && Str == 34 && (v2 = *(&v13 + v1) == 34, v3 = &v13 + v1, v2) ) { *v3 = 0; v4 = &ApplicationName; } else { v4 = &Str; } cbData = 260; v5 = _strnlen(Src, 0x7FFFFFFFu); if ( !RegQueryValueExA(hKey, "XDControlArgs", 0, &Type, (LPBYTE)&CommandLine + v5, &cbData) && Type == REG_SZ ) { memset(&StartupInfo.lpReserved, 0, 0x40u); ProcessInformation.hThread = 0; ProcessInformation.dwProcessId = 0; ProcessInformation.dwThreadId = 0; ProcessInformation.hProcess = 0; StartupInfo.cb = 68; if ( CreateProcessA(v4, &CommandLine, 0, 0, 0, 0, 0, 0, &StartupInfo, &ProcessInformation) ) { CloseHandle(ProcessInformation.hProcess); CloseHandle(ProcessInformation.hThread); } } } } } result = RegCloseKey(hKey); } return result; } |
So what’s the conclusion?
We can create the following registry values in HKLM\SOFTWARE\Wow6432Node\Citrix\ICA Client\Engine\Lockdown Profiles\All Regions\Lockdown\XenDesktop:
XDControlRunOnExit | DWORD: 0 for off 1 for on |
XDControlExe | String or Expandable String: Executable including path to run, maximum length 260 characters. Environment variables can be used |
XDControlArgs | String: Commandline arguments, maximum length 260 characters |
How is that useful?
An example is automatically locking the workstation when the Citrix session ends. Use the following settings:
XDControlRunOnExit | 1 |
XDControlExe | rundll32.exe |
XDControlArgs | user32.dll,LockWorkStation |
4 Responses for "Run a Process when Citrix Receiver Exits"
Awesome work Remko! As always
Very interesting and useful function, wondering why it is not public documented by Citrix
Cheers
Michael
It is indeed very neat – it’d be useful to get it more widely documented as a function. Given its hidden nature its the type of thing that got added for a specific project, but could get deleted just as easily.
[…] Recently I published an article on my blog that shows how to run an executable of choice when the Citrix Receiver exits. […]
Has anyone testet this with Receiver 4.2?
I found out, that it is not possible to create a DWORD within this registry hive. Changing it to REG_SZ with “1”, “True” or “*” does not help as well.
Any other ideas to logoff or shutdown a Workstation, when a Published Desktop Ends?
Leave a reply