About Terminal Server, Citrix, Delphi and other stuff
2 May
Justin Shepard converted my code to encrypt RPD passwords to VB.NET:
1 May
Recently I needed to convert a C header file to Delphi which contained bitfields. Let’s take a look at a sample structure that contains bitfields:
It means that there is a DWORD (Cardinal) dwValue1 followed by a bitfield with the size of a ULONG (32 bits). In this bitfield 4 values are defined (BitValue1..4) which are used as boolean’s because the value can offcourse be 0 or 1. Since Delphi doesn’t know a bitfield type the question is how to translate it. Usually it would mean that we simply treat the whole bitfield value as a ULONG and extract the required properties by applying a bitmask (shl/shr). Starting from BDS2006 we can define a record with propertes and use getters and setters. Using this technique we can present boolean values to the user:
Code completion shows that the record has one DWORD Value and 4 Boolean Values which is just what we want!

Offcourse we need to implement the Getters and Setters:
function _BITFIELDSTRUCTURE.GetBitValue2;
begin
Result := BitField and 2 = 2;
end;
function _BITFIELDSTRUCTURE.GetBitValue3;
begin
Result := BitField and 4 = 4;
end;
function _BITFIELDSTRUCTURE.GetBitValue4;
begin
Result := BitField and 8 = 8;
end;
procedure _BITFIELDSTRUCTURE.SetBitValue1(const Value: Boolean);
begin
if Value then BitField := BitField or 1 else BitField := BitField and (not 1);
end;
procedure _BITFIELDSTRUCTURE.SetBitValue2(const Value: Boolean);
begin
if Value then BitField := BitField or 2 else BitField := BitField and (not 2);
end;
procedure _BITFIELDSTRUCTURE.SetBitValue3(const Value: Boolean);
begin
if Value then BitField := BitField or 4 else BitField := BitField and (not 4);
end;
procedure _BITFIELDSTRUCTURE.SetBitValue4(const Value: Boolean);
begin
if Value then BitField := BitField or 8 else BitField := BitField and (not 8);
end;
We can even add a constructor to it, this can be used to e.g. initialize the record (in the example below we fill with zeroes). Note that only a constructor with at least one argument can be used:
implementation
constructor _BITFIELDSTRUCTURE.Create; // Did you know that Delphi permits leaving out (const dummy: word) here?
begin
ZeroMemory(@Self, SizeOf(Self));
end;
…
procedure TForm1.Button1Click(Sender: TObject);
var
BitFieldStructure: TBitFieldStructure;
begin
BitFieldStructure := TBitFieldStructure.Create(0);
So why not use a class instead of record? The answer is that a class is just a pointer we can never pass this to a function, procedure or api call that expects a record. But if we want to support older Delphi versions, like Delphi 6 or Delphi 7 and even Delphi 2005, which are still used a lot we need to find another solution. I came up with (ab)using sets to emulate bitfields, we can do this because a set is actually a set of bits (limited to 256 bits). The example structure could look like this if we use sets:
We can use normal set operations to get and set bitvalues:
Settings like minimal enum size and record alignment are important because we need to asssure that te record size matches the C structure’s size (especially when using structures with a lot of bitfields. I choose to do this with a litte trick, first I declare some constants:
We use these constants to force the correct size, in the example the bitfield was a ULONG which is 32 bits. We add the al32Bit constant to the bitfield:
So I thought I had it figured out… until I came to this line in the C header file:
So we have a bitfield consisting off multiple bits! This gave me some headaches but I finally came up with the following approach
We need a helper function to retreive the numeric value of ColorDepth:
// A Delphi Set contains at most 256 bits. So we raise Exception is we exceed
if StartBit + Count > 255 then Raise
EIntOverflow.Create(‘Startbit + Count cannot exceed maximum set size (255)’);
Result := 0;
BitValue := 1;
// A Delphi Set Of can hold a maximum of 256 bits, since we do not know
// which size was passed to us we cast to 256 bits.
MaxBitSet := TMaxBitSet(ABitSet);
// Loop through the requested bits from end to start (Little Endian)
for i := StartBit+Count-1 downto StartBit do
begin
// is the bit set?
if i in MaxBitSet then
begin
// Multiply with BitValue and add to result
Result := Result + BitValue;
end;
// Multiply BitValue by 2
BitValue := BitValue shl 1;
end;
end;
The helper function is used like this:
Some limitations remain, although I don’t think you are likely to encouter these:
Active Directory Altiris bug Citrix Dell Delphi Exchange Exchange2003 Exchange2010 Hewlett-Packard HP iOS Jailbreak Java LinkedIn Linux MSI MySQL Navigation Objects Office Outlook Passat PowerPoint PowerShell referall was returned RNS315 RNS510 SasLibEx script slow Terminal Server ThinApp TSAdmin TSAdminEx VBS VCDS Vista VMWare Volkswagen Windows PE WLAN Wordpress WTSWaitSystemEvent wts_event_flush
WP Cumulus Flash tag cloud by Roy Tanck requires Flash Player 9 or better.