Remko Weijnen's Blog (Remko's Blog)

About Terminal Server, Citrix, Delphi and other stuff

Archive for the ‘Delphi’ Category

Logon SIDToday I was reusing some old (pre vista) code the retrieves the Logon SID that I wrote a few years ago. The Logon SID is a special SID that identifies a logon session that has the form S-1-5-5-X-Y.

You can view your Logon SID with Process Explorer, right click a GUI process, select Properties and goto the Security Tab:

Process Explorer|Security Tab|Logon SID

 

(more…)

Snippet below can be used to programmatically determine if User Account Control is enabled:

uses
  JwaWinbase, JwaWinNt;

function IsUACEnabled: Boolean;
var
  hToken: THandle;
  tet: TOKEN_ELEVATION_TYPE;
  dwSize: DWORD;
begin
  Win32Check(OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hToken));
  // TokenElevationType class only available on Vista+
  Win32Check(GetTokenInformation(hToken, TokenElevationType, @tet, SizeOf(tet), dwSize));

  Result := tet <> TokenElevationTypeDefault;
end;

In my SATA Controller Identification tool I was using the TSaveDialog (Delphi 2010) but I got a report that under Windows PE the dialog is never shown.

There’s no exception and I didn’t really bother to check why it fails. Instead I decided to replace it with the GetSaveFileName API which does work under Windows PE.

Example:

var
  sl: TStringList;
  ofn: OPENFILENAME;
  Buf: array[0..MAX_PATH] of Char;

  ZeroMemory(@ofn, SizeOf(ofn));
  ofn.lStructSize := SizeOf(ofn);
  ofn.hWndOwner := Form1.Handle;
  ofn.lpstrFile := @Buf[0];
  ofn.nMaxFile := Length(Buf);
  ofn.lpstrInitialDir := PChar(GetCurrentDir);
  ofn.lpstrFilter := ‘Any File’#0‘*.*’#0‘Registry file’#0‘*.reg’#0#0;
  ofn.nFilterIndex := 0;
  ZeroMemory(@Buf, SizeOf(Buf));
  if GetSaveFileName(ofn) then
  begin
    // Buf now contains the filename
  end;

  • 0 Comments
  • Filed under: Delphi
  • Determining stack size

    I just read an answer on StackOverflow with this code:

    var
      eu:DWORD;
    begin
      asm  
        mov eax,[fs:$4]
        mov ebx,[fs:$8]
        sub eax,ebx  
        mov eu,eax
      end;

      ShowMessage(IntToStr(eu));
    end;

    Unfortunately it lacked explanation, so what does this code do?

    It reads offset $4 from the Thread Information Block (the top of stack) into eax and then offset $8 (stack base) into ebx.

    Then it substracts the two and moves that into variable eu, that’s all!

    Again an old war story, this time about timezone handling in Outlook/Exchange.

    I am not sure which year it was but I had just started to work for a new company and inherited an Exchange 5.5 Server.

    The mail had been migrated from an earlier version and calendar data was migrated from Schedule+.

    On the first change to Daylight Savings (DTS) all recurring appointments where shown one hour later (or earlier can’t remember) in Outlook. A manual change was not an option: there were over 2000 mailboxes each with a lot of appointments.

    We first tried a workaround by disabling DTS on the the workstations and then manually change the time when changing from and to DTS. 

    But this influenced the timestamps on externals mails and of course appointments with external parties.

    After a lot of (and I really mean a lot) of researching I found that Outlook stores all times in an appointment as relative (UTC) time.

    Upon display it uses an undocumented TimeZone descriptor field to convert to Local Time.

     

    (more…)

    If you want to check if you are running on a Server Core edition of Windows you can use the GetProductInfo API.

    GetProductInfo takes 4 input parameters that can be obtained using GetVersionEx and the OSVERSIONINFOEX structure:

    var
      osvi: OSVERSIONINFOEX;
    begin
      ZeroMemory(@osvi, SizeOf(osvi));
      osvi.dwOSVersionInfoSize := SizeOf(osvi);
      Win32Check(GetVersionEx(osvi));

    No we call GetProductInfo:

    var
      dwProdType: DWORD;
    begin
      Win32Check(GetProductInfo(osvi.dwMajorVersion, osvi.dwMinorVersion,
        osvi.wServicePackMajor, osvi.wServicePackMinor, dwProdType));

     

     

    (more…)

    In the previous parts (part 1 part 2) i’ve described the theoretical part and implementation problems. So, now we can write the code:

    1) In case we login the user, we just call LsaLogonUser to get the token:
    (more…)

    In part 1 I’ve described the theoretical parts needed for a custom autologon application implementation.

    But there are some practical problems which I will describe here.

    1) I use the LsaLogonUser function to log in the user. However, if I do not pass not null for the LocalGroups parameter, msgina.dll fails to process the logon.

    Why? Because it looks for the SE_GROUP_LOGON_ID SID and treat it as logon SID. So we have to add the logon SID manually:
    (more…)

    Windows XP introduced the ability to use Fast User Switching (FUS from here on), which is implemented using Terminal Services.

    But in some cases (i.e. when FUS is not enabled, or when you connect to the console in Windows 2003 server), the Winlogon process in an RDP session needs to transfer credentials to Session 0.

    Although not documented in MSDN, the process of transferring credentials is described by Keith Brown in the June 2005 issue of MSDN magazine: Customizing GINA, Part 2.

    WlxQueryConsoleSwitchCredentials and WlxGetConsoleSwitchCredentials are used in the transfer with the semi-documented WLX_SAS_TYPE_AUTHENTICATED SAS code constant.

    Internally, winlogon.exe uses a Named Pipe, \\.\Pipe\TerminalServer\AutoReconnect, to implement both of these functions.

    The pipe format is described in this structure:
    (more…)

    If you want to obtain a user’s token in a Terminal Server or Citrix session (eg to launch a process in a session) you can call the WTSQueryUserToken function.

    On the x64 versions of Windows XP and Server 2003 this function fails however and returns ERROR_INSUFFICIENT_BUFFER (“The data area passed to a system call is too small.”) when called from a 32 bit process.

    Internally WTSQueryUserToken calls the undocumented function WinstationQueryInformationW with the WinStationUserToken class (14) and passing a WINSTATIONUSERTOKEN struct, filled with caller ProcessId and ThreadId.

    But on x64 Windows the size of this structure is 24 bytes, while on 32 bit Windows the size of the structure is 12 bytes!

    (more…)

    Profile

    Recent Tweets

    Views