2

I would like to translate some type definitions from winnt.h which contain some unions with bitfields. However, is this the correct way of doing it? I am particularly not sure about the union in _TP_CALLBACK_ENVIRON_V3.

  typedef struct _UMS_SYSTEM_THREAD_INFORMATION {
      ULONG UmsVersion;
      union {
          struct {
              ULONG IsUmsSchedulerThread : 1;
              ULONG IsUmsWorkerThread : 1;
          } DUMMYSTRUCTNAME;
          ULONG ThreadUmsFlags;
      } DUMMYUNIONNAME;
  } UMS_SYSTEM_THREAD_INFORMATION, *PUMS_SYSTEM_THREAD_INFORMATION;

  typedef struct _TP_CALLBACK_ENVIRON_V3 {
    TP_VERSION                         Version;
    PTP_POOL                           Pool;
    PTP_CLEANUP_GROUP                  CleanupGroup;
    PTP_CLEANUP_GROUP_CANCEL_CALLBACK  CleanupGroupCancelCallback;
    PVOID                              RaceDll;
    struct _ACTIVATION_CONTEXT        *ActivationContext;
    PTP_SIMPLE_CALLBACK                FinalizationCallback;
    union {
        DWORD                          Flags;
        struct {
            DWORD                      LongFunction :  1;
            DWORD                      Persistent   :  1;
            DWORD                      Private      : 30;
        } s;
    } u;
    TP_CALLBACK_PRIORITY               CallbackPriority;
    DWORD                              Size;
} TP_CALLBACK_ENVIRON_V3;

type
  UMS_SYSTEM_THREAD_INFORMATION = record
    UmsVersion: ULONG;
    ThreadUmsFlags: ULONG;
    case Integer of
      0:(IsUmsSchedulerThread : ULONG);
      1:(IsUmsWorkerThread : ULONG);
  end;
  PUMS_SYSTEM_THREAD_INFORMATION = ^UMS_SYSTEM_THREAD_INFORMATION;

  TP_CALLBACK_ENVIRON_V3 = record
    Version: TP_VERSION;
    Pool: PTP_POOL;
    CleanupGroup: PTP_CLEANUP_GROUP;
    CleanupGroupCancelCallback: PTP_CLEANUP_GROUP_CANCEL_CALLBACK;
    RaceDll: PVOID;
    ActivationContext: PACTIVATION_CONTEXT; // Pointer
    FinalizationCallback: PTP_SIMPLE_CALLBACK;
    case Flags: DWORD of
      1: (LongFunction: DWORD)
      1: (Persistent: DWORD)
      30: (Private: DWORD)
    end;
    CallbackPriority: TP_CALLBACK_PRIORITY;
    Size: DWORD;
  end;
  PTP_CALLBACK_ENVIRON = ^TP_CALLBACK_ENVIRON_V3;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
John Lewis
  • 337
  • 3
  • 12

2 Answers2

4

Those : something notations are bit fields. There is no direct Pascal equivalent.

However, since the three bitfields combined are a complete dword, a general outline for the equivalent becomes something like this:

type
  _TP_CALLBACK_ENVIRON_V3 = record
  ...
    FinalizationCallback: PTP_SIMPLE_CALLBACK;
    case Integer of
    1: (Flags: DWord);
    2: (LongFunctionPersistentPrivate: DWord)
  end;
  • And in modern Delphi versions, records can have methods and properties, so you can simulate the individual bitfields fairly easily with some appropriate bit shifting. – Remy Lebeau Jan 02 '15 at 08:27
  • John, you don't need to care about literal translation of the `TP_CALLBACK_ENVIRON` structure bitfields since the callback environment structure is used only internally by the thread pool API. You are not supposed to access any of those fields. So merging those bitfields into a single `DWORD` is fine. Your proposed translation is wrong. `1: (LongFunction: DWORD)` stands for the first bit of `DWORD`, `1: (Persistent: DWORD)` second bit of `DWORD` and `30: (Private: DWORD)` is remaining 30 bits of `DWORD`. You have declared 3 `DWORD`s for those fields which is wrong. Do what is suggested here. – TLama Jan 02 '15 at 12:59
  • @TLama Thanks! Since its used only internally in the `kernel32.dll` I can just use an opaque pointer to the structure. :) – John Lewis Jan 02 '15 at 13:11
  • 1
    John, not in this case. It is used internally, but you cannot define it (the whole `TP_CALLBACK_ENVIRON` structure) as an opaque pointer. The type must be complete since it is your application that allocates it. The `InitializeThreadpoolEnvironment` function is implemented as inline function whose only business is returning initialized structure of this type (hence it must be known). – TLama Jan 02 '15 at 13:42
1

As noted, the ':' notations are bit fields. There is no direct solution, but there is a simple way to translate them that makes them useful again. See my article that describes this. It uses a simple set of functions to get or set a number of bits and to shift them into place, and a clever way (I did not invent it, BTW) to declare them, using the rather unknown property index.

Take a look here: Pitfalls of converting

The idea came from a Stack Overflow answer.

FWIW, the article also describes how to handle unions in such translations.

Community
  • 1
  • 1
Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94