SlideShare a Scribd company logo
1 of 108
Download to read offline
MARSHALING WITH C#
                          POCKET REFERENCE




   Author | Mohammad Elsheimy
MARSHALING WITH C# POCKET REFERENCE
         © 2010 MOHAMMAD ELSHEIMY




MARSHALING WITH C#
 POCKET REFERENCE


                      Mohammad Elsheimy
 A freelance software developer and trainer




                      2
MARSHALING WITH C# POCKET REFERENCE
    © 2010 MOHAMMAD ELSHEIMY




  © 2010 Mohammad Elsheimy




                 3
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY


                 ABOUT THE AUTHOR


Mohammad Elsheimy
                   Mohammad is a MCP, MCTS, and MCPD independent
                   consultant, trainer, and author. He was born in 1991 in KB,
                   Egypt.

                   Besides self-studying computer science, yet, he is a student in
                   Al-Azhar Holy Quran Institute. There, he studies Islamic
                   legislation and sciences related to Islam, The Holy Quran, and
                   the Arabic language.

                    Mohammad loves community work. He always works on
helping developers and average users all over the world. He is writing in many
places including his own blog, http://JustLikeAMagic.WordPress.com.

You can reach Mohammad at Geming.Leader@Hotmail.com. In addition, you can
reach him directly at +2 018 577 1171.




    WHO SHOULD READ THIS BOOK?

This book discusses the marshaling process between managed and unmanaged
code using C#, devoted for developers who know the basics of unmanaged code
(especially Windows API) and platform invocation.

For the sake of simplicity, this book focuses on Windows API as the source for
unmanaged code. However, information in this book can be applied to any of the
unmanaged environments.

In addition, this book assumes a 32-bit version of Windows. All DWORDs,
HANDLEs, etc. are considered 4-bytes. If you want to hand your application to
64-bit machine, consider revising your code to avoid memory layout problems.

For VB.NET developers, it is helpful reading pages in Appendix A.




                                        4
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY


                CONTENTS AT A GLANCE



About the Author

Who should read this book?

Chapter 1: Introducing Marshaling

Chapter 2: Marshaling Simple Types

Chapter 3: Marshaling Compound Types

Chapter 4: Marshaling Arrays

Chapter 5: Marshaling Callbacks

Chapter 6: Memory Management

Chapter 7: Controlling the Marshaling Process

Appendix A: What about VB.NET

Where to Go Next

References

Figures

Code Listings

Glossary




                                       5
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY


               TABLE OF CONTENTS

About the Author

Who should read this book?

Chapter 1: Introducing Marshaling

      What is Marshaling?

      Why Marshaling?

      When I Need to Marshal?

Chapter 2: Marshaling Simple Types

      Chapter Contents

      Overview

      Simple and Compound data Types

      Blittable and Non-Blittable Data Types

      Marshaling Blittable Data Types

             Numeric Data Types

             Textual Data Types

             Examining Type Definition

             Variants

             Try It Out!

      A Rule of Thumb

      Marshaling Booleans

             The Two Types

             Try It Out!

      Marshaling Textual Data types

             How to Marshal Strings and Buffers

             Handling Character Encoding

             Try It Out!


                                        6
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY

      Marshaling Handles

            Generic Handles

            Safe Handles

            Critical Handles

      Passing Mechanism

      Additional Techniques

            Encapsulation

            Creating Wrappers

            Working with Nullable Arguments

            Working out the CLS Problem

      Real-World Examples

            Programmatically Swapping Mouse Buttons

            Programmatically Turning On the Screen Saver

            Dragging a Form without a Title Bar

      Summary

Chapter 3: Marshaling Compound Types

      Chapter Contents

      Overview

      Introduction

      Marshaling Unmanaged Structures

            How to Marshal a Structure

            Handling Memory Layout Problem

            Try It Out!

      Marshaling Unions

            A Short Speech About Unions

            How to Marshal a Union

            Unions with Arrays

            Try It Out!


                                     7
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

      Value-Types and Reference-Types

      Passing Mechanism

      Real-World Examples

                The DEVMODE Structure

                Working with Display Settings

      Summary

Chapter 4: Marshaling Arrays

Chapter 5: Marshaling Callbacks

Chapter 6: Memory Management

Chapter 7: Controlling the Marshaling Process

Appendix A: What about VB.NET

Where to Go Next

References

Figures

Code Listings

Glossary




                                        8
MARSHALING WITH C# POCKET REFERENCE
    © 2010 MOHAMMAD ELSHEIMY




    This page intentionally left blank.




                    9
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY


              CHAPTER 1
        INTRODUCING MARSHALING



                        WHAT IS MARSHALING ?

Marshaling is the process of creating a bridge between managed code and
unmanaged code; it is the homer that carries messages from the managed to the
unmanaged environment and reverse. It is one of the core services offered by the
CLR (Common Language Runtime).

Because much of the types in unmanaged environment do not have counterparts
in managed environment, you need to create conversion routines that convert
the managed types into unmanaged and vice versa; and that is the marshaling
process.

As a refresher, we call .NET code "managed" because it is controlled (managed)
by the CLR. Other code that is not controlled by the CLR is called unmanaged .




                          WHY MARSHALING ?

You already know that there is no such compatibility between managed and
unmanaged environments. In other words, .NET does not contain such the types
HRESULT, DWORD, and HANDLE that exist in the realm of unmanaged code.
Therefore, you need to find a .NET substitute or create your own if needed. That
is what called marshaling.

An example is the unmanaged DWORD; it is an unsigned 32-bit integer, so we
can marshal it in .NET as System.UInt32. Therefore, System.UInt32 is a substitute
for the unmanaged DWORD. On the other hand, unmanaged compound types
(structures, unions, etc.) do not have counterparts or substitutes in the managed
environment. Thus, you’ll need to create your own managed types
(structures/classes) that will serve as the substitutes for the unmanaged types
you use.




                                       10
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY


                       WHEN I NEED TO MARSH AL ?

Marshaling comes handy when you are working with unmanaged code, whether
you are working with Windows API or COM components. It helps you
interoperating (i.e. working) correctly with these environments by providing a
way to share data between the two environments. Figure 1 shows the
marshaling process, where it fall, and how it is required in the communication
process between the two environments.




Figure 1.1 - The Marshaling Process




                                      11
MARSHALING WITH C# POCKET REFERENCE
    © 2010 MOHAMMAD ELSHEIMY




    This page intentionally left blank.




                    12
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY


              CHAPTER 2
        MARSHALING SIMPLE TYPES


                            CHAPTER CONTENTS

Contents of this chapter:

      Chapter Contents

      Overview

      Simple and Compound data Types

      Blittable and Non-Blittable Data Types

      Marshaling Blittable Data Types

          o Numeric Data Types

          o Textual Data Types

          o Examining Type Definition

          o Variants

          o Try It Out!

      A Rule of Thumb

      Marshaling Booleans

          o The Two Types

          o Try It Out!

      Marshaling Textual Data types

          o How to Marshal Strings and Buffers

          o Handling Character Encoding

          o Try It Out!

      Marshaling Handles

          o Generic Handles

          o Safe Handles


                                         13
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

          o Critical Handles

      Passing Mechanism

      Additional Techniques

          o Encapsulation

          o Creating Wrappers

          o Working with Nullable Arguments

          o Working out the CLS Problem

      Real-World Examples

          o Programmatically Swapping Mouse Buttons

          o Programmatically Turning On the Screen Saver

          o Dragging a Form without a Title Bar

      Summary




                                  OVERVIEW

This chapter discusses the nitty-gritty part of marshaling process. It is the base
for the rest of discussion about marshaling. It is about marshaling simple data
types.

The first section of this chapter breaks data types into two categories, simple and
compound. Simple types (integers, booleans, etc.) are those that are not made of
other types. On the contrary, compound types (structures and classes) are those
types that require special handling and made of other types.

After that, we will dig into the discussion of simple types and we will break them
into two categories, blittable and non-blittable.

Before we end this chapter, we will discuss the passing mechanism and handles
in .NET Framework.




               SIMPLE AND COMPOUND DATA TYPES

There are two kinds of data types:

      Simple (primitive/basic)



                                        14
MARSHALING WITH C# POCKET REFERENCE
                        © 2010 MOHAMMAD ELSHEIMY

       Compound (complex)

Primitive data types are those that are not defined in terms of other data types.
They are the basis for all other types. Examples of managed primitives are
numbers like System.Byte, System.Int32, System.UInt32, and System.Double,
strings like System.Char and System.String, and handles like System.IntPtr.

Compound data types are those that built up of other data types. For example a
class or a structure that encapsulates simple types and other compound types.

        We will use terms simple, primitive, and basic types to refer to base types
        like integers, strings, etc. Terms compound, and complex types also will be
        used interchangeably to refer to classes and structures.

        Some considers that strings are not primitives.




          BLITTABLE AND NON-BLITTABLE DATA TYPES

Most data types have common representations in both managed and unmanaged
memory and do not require special handling. These types are called blittable
types because they do not require special handling when passed between
managed and unmanaged code. Other types that require special handling are
called non-blittable types. You can think that most of simple types are blittable
and all of compound types are non-blittable.

The following table lists the blittable data types exist in .NET (their counterparts
in unmanaged code will be covered soon):
Table 2.1 Blittable Types
Managed Type                                Description
System.SByte                                8-bit signed integer.

System.Byte                                 8-bit unsigned integer

System.Int16                                16-bit signed integer.

System.UInt16                               16-bit unsigned integer

System.Int32                                32-bit signed integer

System.UInt32                               32-bit unsigned integer

System.Int64                                64-bit signed integer

System.UInt64                               64-bit unsigned integer

System.IntPtr                               Signed pointer

System.UIntPtr                              Unsigned pointer


                                         15
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

                 MARSHALING BLITTABLE DATA TYPES

You can marshal an unmanaged simple data type by tracking its definition then
finding its counterpart (marshaling type) in the managed environment based on
its definition (we will see how soon.)

                               NUMERIC DATA TYPES

The following table lists some of the unmanaged data types in Windows, their
C/C++ keywords, and their counterparts (marshaling types) in .NET. As you
might guess, by tracking each of these unmanaged types, we were able to find its
managed counterpart. Notice that so
Table 2.2 Numeric Data Types
Description       Windows Type         C/C++           Managed Type     C#
                                       Keyword                          Keyword
8-bit   signed CHAR                    char            System.SByte     sbyte
integer

8-bit unsigned BYTE                    unsigned char   System.Byte      byte
integer

16-bit signed SHORT                    Short           System.Int16     short
integer

16-bit unsigned WORD and USHORT        unsigned        System.UInt16    ushort
integer                                short

32-bit signed INT, INT32, LONG, int, long              System.Int32     int
integer       and LONG32

32-bit unsigned DWORD, DWORD32, unsigned int, System.UInt32             uint
integer         UINT, and UINT32 unsigned long

64-bit signed INT64, LONGLONG, __int64,           long System.Int64     long
integer       and LONG64       long

64-bit unsigned DWORDLONG,             unsigned      System.UInt64      ulong
integer         DWORD64,               __int64,
                ULONGLONG,         and unsigned long
                UINT64                 long

Floating-point    FLOAT                float           System.Double    double
integer



       Notice that long and int defer from a platform to another and from a
       compiler to another. In 32-bit versions of Windows, most compilers refer to
       both long and int as 32-bit integers.



                                        16
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

       Some types are based on the version of Windows. DWORD, for instance, is 32
       bits on 32-bit versions and 64 bits on 64-bit versions of Windows. This
       writing assumes that it is a 32-bit version of Windows.

       Know that there is no difference between Windows data types and C/C++
       data types. Windows data types are just aliases for the actual C types.

       Do not be confused with the many types that refer to one thing, they are all
       just names (aliases.) INT, INT32, LONG, and LONG32 are all 32-bit integers
       for instance.

       To keep things simple, we will focus on Windows API in our examples.

Although, some unmanaged types have names similar to names of some
managed types, they have different meanings. An example is LONG, it has similar
name as System.Long. However, LONG is 32-bit and System.Long is 64-bit!

If you need to learn more about these types, check out the article “Windows Data
Types” in MSDN library.

                               TEXTUAL DATA TYPES

In addition to the numeric data types, you will need to know how to marshal
unmanaged textual data types (a single character or a string.) However, these
types are non-blittable, so they require special handling.

The following table lists briefly unmanaged textual data types.
Table 2.3 Textual Data Types
Description                    Unmanaged Type(s)        Managed Type
8-bit ANSI character           CHAR                     System.Char

16-bit Unicode character       WCHAR                    System.Char

8-bit ANSI      string     of LPSTR, LPCSTR, PCSTR, and System.String
characters                    PSTR

16-bit Unicode string of LPCWSTR,       LPWSTR, System.String
characters               PCWSTR, and PWSTR



Soon we will cover textual data types in details.

                           EXAMINING TYPE DEFINITIO N

As we have said, for the sake of simplicity, we will use Windows API as the base
for our discussion in this book. Therefore, you need to know that all Windows
Data Types (INT, DWORD, etc.) are just names (technically, typedefs) for the
actual C types. Therefore, many names may refer to one thing just as INT and
LONG.

                                         17
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

Thus, we can say that LONG is defined as C int and DWORD is defined as C
unsigned long.

INT and LONG are easy to marshal. However, there are primitive types that you
will need to track their definitions to know how to marshal it.

Remember that we will use MSDN documentation (specially the article
“Windows Data Types”) when tracking unmanaged data types (Windows data
types specially.)

The next are some of the types defined as another types. You can think of these
types as aliases for the base types. Yet, some are platform-specific, and others
not.

      HRESULT:
       As you will see, plenty of functions return a HRESULT to represent the
       status of the operation. If HRESULT equals to zero, then the function
       succeeded, otherwise it represents the error code or status information
       for the operation. HRESULT defined as LONG, and LONG in turn defined as
       a 32-bit signed integer. Therefore, you can marshal HRESULT as
       System.Int32.

      BOOL                            and                           BOOLEAN:
       Both are Boolean types, that means that they take either TRUE (non-zero)
       or FALSE (zero.) The big difference between BOOL and BOOLEAN is that
       BOOL is defined as INT, thus occupies 4 bytes. BOOLEAN on the other
       hand is defined as BYTE, thus occupies only 1 byte. Booleans are covered
       soon.

      HFILE:
       A handle to a file opened using one of the Windows File IO functions like
       OpenFile() function. This type is defined as INT, and INT in turn is defined
       as a 32-bit signed integer. Therefore, you can marshal HFILE as
       System.Int32. Although, HFILE defined as INT, handles should be
       marshaled as System.IntPtr, which is internally encapsulates the raw
       handle. To be clear, you would better marshal an unmanaged handle as a
       System.Runtime.InteropServices.SafeHandle or CriticalHandle, this is the
       ideal marshaling type for any handle. Hence, file handles best marshaled
       as Microsoft.Win32.SafeHandles.SafeFileHandle that is derived from
       SafeHandleZeroOrMinusOneIsInvalid that is in turn derived from the
       abstract class System.Runtime.InteropServices.SafeHandle. For more
       details about handles, refer to the section "Marshaling Handles" later in
       this chapter.




                                        18
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

In addition, there are types that are variable based on the operating system.
Examples are:

      INT_PTR:
       A pointer to a signed integer. Defined as INT64 if this is a 64-bit OS, or INT
       otherwise.

      LONG_PTR:
       A pointer to a signed long. Defined as INT64 if this is a 64-bit OS, or LONG
       otherwise.

      UINT_PTR:
       A pointer to an unsigned integer. Defined as DWORD64 if this is a 64-bit
       OS, or DWORD otherwise.

      ULONG_PTR:
       A pointer to an unsigned long. Defined as DWORD64 if this is a 64-bit OS,
       or DWORD otherwise.

Keep in mind that there is a big difference between a variable and a pointer to a
variable. A variable refers directly to its value into the memory. However, a
pointer contains an address of another value into the memory. Consider the
following illustration, Figure 2.1:




Figure 2.1 - Pointers into Memory

In the illustration above, the variable i contains the value 320 and you can get the
value from the variable directly. The pointer ptr on the other hand contains the

                                        19
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

address of the variable i. Thus, it indirectly contains the value of the variable i.
That is why we cannot get the value of the pointer directly. We need to
dereference it first before retrieving its value.

       More on pointers later in this chapter. Memory management is discussed in
       details in chapter 6.




In addition, for textual data types, there are types variable based on Unicode
definition (strings and buffers are covered soon.) Examples are:

      TBYTE                          and                                  TCHAR:
       Defined as WCHAR if UNICODE defined, otherwise CHAR.

      LPCTSTR,               LPTSTR,               and             PCTSTR:
       All defined as LPCWSTR if UNICODE defined, otherwise LPCSTR.

      PTSTR:
       Defined as PWSTR if UNICODE defined, otherwise PSTR.

More on textual data types and Unicode later in this chapter.

Notice that some types have special characters in their names. For example, A in
textual data types stands for ANSI, and W in stands for Wide, which means
Unicode. In addition, the letter T in textual information too means it varies based
on OS. Another example is the prefix P (lowercase,) it means a pointer, and LP
means a long pointer. LPC stands for long pointer to a constant.

                                   VARIANTS

In addition, Win32 API defines the types VOID, LPVOID, and LPCVOID. VOID
indicates that the function does accept no arguments. Consider the following
function:
DWORD GetVersion(VOID);

It is required to tag the function with VOID if it does not accept any arguments
(that is one of the specifications of C89.) Notice that VOID is defined as void.

LPVOID and LPCVOID are defined as any type (variant). That means that they can
accept any value. They can be marshaled as integers, strings, handles, or even
compound types, anything you want. In addition, you can marshal them as
System.IntPtr, so you can set them to the address of any object in memory. In
addition, you can marshal them as pointers to object. For example, marshaling a
LPCVOID as System.Int32* (a pointer to an integer) in unsafe code. Moreover,
you can use unsafe code and marshal them as void*. Furthermore, you can



                                        20
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

marshal them as System.Object, so you can set them to any type (refer to chapter
6 for more information about memory management and unsafe code.)

It is worth mentioning that when working with VOIDs it is recommended
decorating your variable with MarshalAsAttribute attribute specifying
UnmanagedType.AsAny which tells the compiler to work out the marshaling
process and sets the type of the argument at runtime. Refer to the last chapter:
"Controlling the Marshaling Process" for more information about this attribute.

       If you have worked with traditional Visual Basic, thinking about LPVOID
       and LOCVOID as a Variant could help too much.

       If you are interoperating with the traditional Visual Basic code, you can use
       the same way we did on marshaling LPVOID and LPCVOID in marshaling
       the type Variant.

                                   TRY IT OUT!

Now, we will try to create the PInvoke method for the MessageBoxEx() function.
The example demonstrates how to control precisely the marshaling process
using the MarshalAsAttribute attribute. We will cover this attribute and more in
the last chapter of this book: "Controlling the Marshaling Process." Handles are
covered in the section: "Marshaling Handles" of this chapter.

The following example creates the PInvoke method for the MessageBoxEx()
function and calls it to display a friendly message to the user.

The definition of the MessageBoxEx() function is as following:
Listing 2.1 MessageBoxEx() Unmanaged Signature
int MessageBoxEx(

     HWND hWnd,

     LPCTSTR lpText,

     LPCTSTR lpCaption,

     UINT uType,

     WORD wLanguageId

);

And here is the managed signature (the PInvoke method) of this function:

       In order for the example to run you must add a using statement to
       System.Runtime.InteropServices namespace. Be sure to add it for all
       examples throughout this book.
Listing 2.2 MessageBoxEx() Managed Signature
      // CharSet.Unicode defines the UNICODE.

      // Use either this way to control


                                         21
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY
     // the whole function, or you can control

     // the parameters individually using the

     // MarshalAsAttribute attribute

     [DllImport("User32.dll", CharSet = CharSet.Unicode)]

     [return: MarshalAs(UnmanagedType.I4)]

     static extern Int32 MessageBoxEx

         (IntPtr hWnd,

         // Marshaling as Unicode characters

         [param: MarshalAs(UnmanagedType.LPTStr)]

         String lpText,

         // Marshaling as Unicode characters

         [param: MarshalAs(UnmanagedType.LPTStr)]

         String lpCaption,

         // Marshaling as 4-bytes (32-bit) unsigned integer

         [param: MarshalAs(UnmanagedType.U4)]

         UInt32 uType,

         // Marshaling as 2-bytes (16-bit) unsigned integer

         [param: MarshalAs(UnmanagedType.U2)]

         UInt16 wLanguageId);


       For more information about marshaling strings, see section “Marshaling
       Strings and Buffers” later in this chapter.




                             A RULE OF THUMB

Keep in mind that. .NET Framework allows you to take a granular level of control
over the marshaling process and that would be very complicated. However,
things can be so simple.

You can ignore attributes in most cases and just use the counterparts and CLR
will do its best. Likely, you are not required to use managed signed integers for



                                        22
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY

unmanaged equivalents. You can use managed signed integers for unmanaged
unsigned integers and vice versa. You can also marshal a SHORT as System.Char!

The key point is that as long as the managed marshal type occupies the same
memory size as the unmanaged type, you are in safe. However, keeping things in
its right position helps avoiding undesirable errors that maybe very difficult to
know and handle.

Another thing that you should keep in mind that the information in this book can
be applied to any unmanaged environment. You can apply this information when
interoperating with Windows API, C/C++ libraries, Visual Basic, COM, OLE,
ActiveX, etc. However, for the sake of simplicity, we will talk about the Windows
API as the source of the unmanaged code.

Another thing, this writing assumes a 32-bit version of Windows. Thus, it
considers that DWORDs, HANDLEs, etc. are all 4 bytes. On 64-bit versions, they
are 8 bytes.




                       MARSHALING BOOLEANS

                               THE TWO TYPES

In general, marshaling simple data types is very easy and booleans are no
exception. However, Booleans are non-blittable types. Therefore, they require
some handling.

There are some notes about marshaling booleans in the managed environment.
The first thing to mention about is that Windows defines two types of Boolean
variables:

   1. BOOL:
      Defined as INT, therefore, it is 4-bytes wide.

   2. BOOLEAN:
      Defined as BYTE, therefore it is only 1-byte.

Both can be set to non-zero to indicate a true (TRUE) value, and zero otherwise
(FALSE.)

       Again, the two types exist only in the Windows SDK. Other environments
       may define other types with similar names.

While it is true that BOOL and BOOLEAN are best marshaled as System.Boolean,
BOOL can be marshaled as System.Int32 too, because it is defined as a 32-bit
integer. On the other hand, BOOLEAN can be marshaled as System.Byte or
System.U1, because it is defined as 8-bits integer. Do you remember our rule of
thumb?

                                        23
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

Take into consideration that whether you are marshaling your Boolean type to
System.Boolean, System.Int32, or System.Byte, it is recommended that you apply
MarshalAsAttribute attribute to the variable to specify the underlying
unmanaged type. For example, to specify that the underlying type is BOOL,
specify UnmanagedType.Bool (recommended) or UnmanagedType.I4 in the
MarshalAsAttribute constructor. On the other hand, BOOLEAN can be specified
as UnmanagedType.U1. If you omit MarshalAsAttribute, CLR assumes the default
behavior for System.Boolean, which is 2 bytes wide. For more information about
MarshalAsAttribute attribute, see the last chapter: "Controlling the Marshaling
Process."

                                    TRY IT OUT!

Fortunately, plenty of functions return BOOL indicating whether the function
succeeded (TRUE) or failed (FALSE.)

The following is the definition of the famous CloseHandle() function:
Listing 2.3 CloseHandle() Unmanaged Signature
BOOL CloseHandle(HANDLE hObject);

The managed version of CloseHandle() is as following:
Listing 2.4 CloseHandle() Managed Signature
     [DllImport("Kernel32.dll")]

     [return: MarshalAs(UnmanagedType.Bool)]

     // In addition, you can marshal it as:

     // [return: MarshalAs(UnmanagedType.I4)]

     // Moreover, You can change System.Boolean to System.Int32

     static extern Boolean CloseHandle(IntPtr hObject);

       Handles covered soon. For now, it is OK to know that all handles marshaled
       to System.IntPtr.




                 MARSHALING TEXTUAL DATA TYPES

                 HOW TO MAR SHAL STRINGS A ND BUFFERS

This section discusses how to marshal strings and buffers. We will use the terms
string and buffer interchangeably to refer to a sequence of characters.

Two types exist in the managed environment for marshaling unmanaged string
buffers. They are System.String and System.Text.StringBuilder. Of course, they



                                          24
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

both hold character sequences. However, StringBuilder is more advantageous
because it is very efficient working with mutable strings than System.String.

Every time you use one of the methods of System.String class or you pass a
System.String to a function, normally, you create a new string object in memory,
which requires a new allocation of memory space for the new object. In addition,
if the function changes the string you will not get the results back. That is why
System.String is called immutable. On the other hand, StringBuilder does not
require re-allocating of space unless you exceed its capacity. Besides the talk
about marshaling, you should use StringBuilder to accommodate performance
issues if you often change the same string many times.

To keep System.String immutable, the marshaler copies the contents of the string
to another buffer before calling the function, and then it passes that buffer to the
function. If you were passing the string by reference, the marshaler copies the
contents of the buffer into the original string when returning from the function.

Conversely, when using StringBuilder, it passes a reference to the internal buffer
of StringBuilder if passed by value. Passing a StringBuilder by reference actually
passes a pointer to the StringBuilder object into memory to the function not a
pointer to the buffer itself.

       Read more about passing a type by value or by reference in the section
       "Passing Mechanism" later in this chapter.

Another feature of StringBuilder is its ability to specify buffer capacity. As we will
see, this can be very helpful in plenty of cases.

To summarize, System.String is preferable when working with immutable
strings, especially for input (In) arguments. On the other hand,
System.Text.StringBuilder is preferable with changeable strings especially
output (Out) arguments.

Noteworthy to say that StringBuilder cannot be used inside compound types.
Therefore, you will need to use String instead.

Another point to mention is that you can pass array of System.Char in place of a
System.String or System.Text.StringBuilder. In other words, you can marshal
unmanaged strings as managed arrays of System.Char (or System.Int16, do you
remember?)

       Compound types discussed in the next chapter.

                     HANDLING CHARACTER E NCODING

Encoding of a character is very important because it determines the value that
the character can hold and the size it occupies into memory. For example, if the
character is ANSI-encoded it can be one of only 256 characters. Likewise, if it is



                                         25
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

Unicode-encoded, it can hold one of 65536 characters, which is very good for
most languages.

       If you need more information about Unicode, you can check the official site
       of Unicode, www.Unicode.org. In addition, Programming Windows 5th by
       Charles Petzold includes a must-read introduction of Unicode and
       character sets.

For controlling character encoding when marshaling unmanaged types, you may
take one of two approaches or you can combine them as needed. You can control
the encoding of the overall function (i.e. at the function level,) or you can drill
down and control the encoding process at a granular level by controlling every
argument separately (the second approach is required in certain cases e.g.
MultiByteToWideChar() function.)



For changing the encoding of the overall function, DllImportAttribute offers the
property CharSet that indicates the encoding (character set) for the strings and
arguments of the function. This property can take one of several values:

      CharSet.Auto                       (CLR                          Default):
       Strings encoding varies based on operating system; it is Unicode-encoded
       on Windows NT and ANSI-encoded on other versions of Windows.

      CharSet.Ansi                        (C#                            Default):
       Strings are always 8-bit ANSI-encoded.

      CharSet.Unicode:
       Strings are always 16-bit Unicode-encoded.

      CharSet.None:
       Obsolete. Has the same behavior as CharSet.Ansi.

       Take into consideration that if you have not set the CharSet property, CLR
       automatically sets it to CharSet.Auto. However, some languages override the
       default behavior. For example, C# defaults to CharSet.Ansi.

It is worth mentioning that plenty of functions that accept strings and buffers are
just names (technically typedefs)! They are not real functions, they are entry-
points (aliases) for the real functions. For example, ReadConsole() function is
nothing except an entry point redirects the call to the right function, either
ReadConsoleA() if ANSI is defined, or ReadConsoleW() if Unicode is defined (A
stands for ANSI, and W stands for Wide which means Unicode.) Therefore, you
can actually bypass this entry-point by changing the PInvoke method name to
match the right function or by changing DllImportAttribute.EntryPoint to the
name of the required function. In both cases, setting DllImportAttribute.CharSet
along with is no use.



                                        26
MARSHALING WITH C# POCKET REFERENCE
                          © 2010 MOHAMMAD ELSHEIMY

If you want to control the encoding at a granular level, you can apply the
MarshalAsAttribute attribute to the argument specifying the underlying
unmanaged type.

Usually, you will need to unify the character encoding of all your native functions
and types. This is, all the functions should be either Unicode or ANSI. Under rare
occasions, some functions would be different in character encoding.

It is worth mentioning that, for fixed-length strings you will need to set the
SizeConst property of MarshalAsAttribute to the buffer length.

         These techniques are not limited to arguments only! You can use them with
         variables of compound types too. We will look at compound types in the
         following chapter.

                                   TRY IT OUT!

Now we will look on both ReadConsole() and FormatConsole() unmanaged
functions and how to call them from your managed environment. Next is the
definition of both functions and other functions required for the example:
Listing 2.5 GetStdHandle(),   ReadConsole(),   GetLastError(),   and   FormatMessage()
Unmanaged Signature
HANDLE GetStdHandle(

     DWORD nStdHandle

);



BOOL ReadConsole(

     HANDLE hConsoleInput,

     [out] LPVOID lpBuffer,

     DWORD nNumberOfCharsToRead,

     [out] LPDWORD lpNumberOfCharsRead,

     LPVOID lpReserved

);



DWORD GetLastError(void);



DWORD FormatMessage(

     DWORD dwFlags,

     LPCVOID lpSource,

     DWORD dwMessageId,



                                          27
MARSHALING WITH C# POCKET REFERENCE
                        © 2010 MOHAMMAD ELSHEIMY
     DWORD dwLanguageId,

     [out] LPTSTR lpBuffer,

     DWORD nSize,

     va_list* Arguments

);

And this is the managed version along with the driver code.
Listing 2.6 Reading from the Console Screen Buffer Example
          // For retrieving a handle to a specific console device

          [DllImport("Kernel32.dll")]

          static extern IntPtr GetStdHandle(

               [param: MarshalAs(UnmanagedType.U4)]

               int nStdHandle);



          // Used with GetStdHandle() for retrieving console input buffer

          const int STD_INPUT_HANDLE = -10;




          // Specifying the DLL along with the character set

          [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]

          [return: MarshalAs(UnmanagedType.Bool)]

          static extern bool ReadConsole(

               // Handle to the input device

               IntPtr hConsoleInput,

               // The buffer of which to write input to

               [param: MarshalAs(UnmanagedType.LPTStr), Out()]

               // [param: MarshalAs(UnmanagedType.AsAny)]

               StringBuilder lpBuffer,

               // Number of characters to read

               [param: MarshalAs(UnmanagedType.U4)]

               uint nNumberOfCharsToRead,

               // Outputs the number of characters read

               [param: MarshalAs(UnmanagedType.U4), Out()]

               out uint lpNumberOfCharsRead,

               // Reserved = Always set to NULL


                                           28
MARSHALING WITH C# POCKET REFERENCE
            © 2010 MOHAMMAD ELSHEIMY
    [param: MarshalAs(UnmanagedType.AsAny)]

    uint lpReserved);




// For getting the code for the last error occurred

[DllImport("Kernel32.dll")]

[return: MarshalAs(UnmanagedType.U4)]

static extern uint GetLastError();



// Retrieves error messages

[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]

[return: MarshalAs(UnmanagedType.U4)]

static extern uint FormatMessage(

    // Options

    [param: MarshalAs(UnmanagedType.U4)]

    uint dwFlags,

    // Source to get the message from

    // [param: MarshalAs(UnmanagedType.AsAny)]

    [param: MarshalAs(UnmanagedType.U4)]

    uint lpSource,

    // Message code = error code

    [param: MarshalAs(UnmanagedType.U4)]

    uint dwMessageId,

    // Language ID (Reserved)

    [param: MarshalAs(UnmanagedType.U4)]

    uint dwLanguageId,

    // Outputs the error message

    [param: MarshalAs(UnmanagedType.LPTStr), Out()]

    out string lpBuffer,

    // Size of error message

    [param: MarshalAs(UnmanagedType.U4)]

    uint nSize,

    // Additional options




                                29
MARSHALING WITH C# POCKET REFERENCE
            © 2010 MOHAMMAD ELSHEIMY
    [param: MarshalAs(UnmanagedType.U4)]

    uint Arguments);



// Message Options

const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x0100;

const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x0200;

const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;

const uint FORMAT_MESSAGE_FLAGS =

    FORMAT_MESSAGE_ALLOCATE_BUFFER |

    FORMAT_MESSAGE_IGNORE_INSERTS |

    FORMAT_MESSAGE_FROM_SYSTEM;



// Message Source

public const int FORMAT_MESSAGE_FROM_HMODULE = 0x0800;




static void Main()

{

    // Handle to input buffer

    IntPtr handle = GetStdHandle(STD_INPUT_HANDLE);



    const int maxCount = 256;



    uint noCharacters;

    StringBuilder builder = new StringBuilder(maxCount);



    if (ReadConsole(handle, builder, (uint)maxCount,

        out noCharacters, 0) == false) // false = non-zero = failed

    {

        string errMsg;

        FormatMessage(FORMAT_MESSAGE_FLAGS,

            FORMAT_MESSAGE_FROM_HMODULE,

            GetLastError(),




                                30
MARSHALING WITH C# POCKET REFERENCE
        © 2010 MOHAMMAD ELSHEIMY
        0,   // Means NULL

        out errMsg,

        0,   // Maximum length

        0); // Means NULL



    Console.WriteLine("ERROR:n{0}", errMsg);

}

else // true = zero = succeeded

    // Writing user input withour the newline

    Console.WriteLine("User wroted: = " +

        builder.ToString().Substring(0,

        builder.Length - Environment.NewLine.Length));



Console.WriteLine(new string('-', 25));




builder = new StringBuilder(maxCount);



// Invalid handle

handle = GetStdHandle(12345);



if (ReadConsole(handle, builder, (uint)maxCount,

    out noCharacters, 0) == false) // false = non-zero = failed

{

    string errMsg;

    FormatMessage(FORMAT_MESSAGE_FLAGS,

        FORMAT_MESSAGE_FROM_HMODULE,

        GetLastError(),

        0,   // Means NULL

        out errMsg,

        0,   // Maximum length

        0); // Means NULL




                             31
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY
                 Console.WriteLine("ERROR: {0}", errMsg);

            }

            else // true = zero = succeeded

                 // Exculding the newline characters

                 Console.WriteLine("User wroted: = " +

                     builder.ToString().Substring(0,

                     builder.Length - Environment.NewLine.Length));

The last code demonstrates other useful techniques:

      Until now, handles should be marshaled as System.IntPtr. The following
       section talks in details about handles.

      Because LPVOID and LPCVOID are both defined as a pointer to a variant
       (i.e. any type,) you can set them to any type you want. They are very
       similar to System.Object in the .NET methodology or Variant for people
       who are familiar with the traditional Visual Basic. In our example, we
       have marshaled LPVOID as System.UInt32 and set it to zero. Again, you
       are free to play with the marshaling types. LPVOID and LPCVOID are both
       32-bit integer. Why not just marshaling them as any of the 32-bit
       managed types and forgetting about them? In addition, you can marshal it
       as System.IntPtr, and pass it System.IntPtr.Zero to indicate a NULL value.
       Moreover, you can marshal it as System.Object, and set it to any value,
       even null to indicate the NULL value. Variant has been discussed in details
       previously in the section “Marshaling Blittable Data Types.”

      va_list* is a pointer to an array of specific arguments. You can marshal it
       as an array, or System.IntPtr. System.IntPtr is preferred if you intend to
       pass it a NULL value.

      If the function requires a parameter passed by value or by reference you
       can add the required modifiers like ref and out to the parameter, and
       decorate the parameter with either InAttribute or OutAttribute, or both.
       The section “Passing an Argument by Value or by Reference” later in this
       chapter discusses by-value and by-reference parameters.

      While DWORD is defined as unsigned 32-bit integer and it should be
       marshaled as System.UInt32, we find that the GetStdHandle() can take
       one of three values: -10 for the input device, -11 for the output device, and
       -12 for the error device (usually is the output device.) Although
       System.UInt32 does not support negative values, Windows handles this
       for you. It converts the signed value to its equivalent unsigned value.
       Therefore, you should not worry about the value passed. However, keep
       in mind that the unsigned values are too different (from the perspective of
       most developers.) For example, the unsigned value of -11 is 0xFFFFFFF5!



                                        32
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

       Does this seem strange for you? Start by consulting the documentation
       about binary notation.




                         MARSHALING HANDLES

                              GENERIC HANDLES

What is a handle? A handle is a pointer to some resource loaded in memory, such
as handles to the console standard input, output, and error devices, the handle
for the window, and the handle to a device context (DC.)

There are plenty of type handles in unmanaged code, here is some of them:

      HANDLE:
       This is the most widely used handle type in the unmanaged environment.
       It represents a generic handle.

      HWND:
       Most widely used with Windows application. It is a handle to a window or
       a control.

      HDC, HGDIOBJ, HBITMAP, HICON, HBRUSH, HPEN, and HFONT:
       If you have worked with GDI, you will be familiar with these handles. HDC
       is a handle to a device context (DC) object that will be used for drawing.
       HGDIOBJ is a handle for any GDI object. HBITMAP is a handle to a bitmap,
       while HICON is a handle to an icon. HBRUSH is a handle to a brush, HPEN
       is a handle to pen, and HFONT is a handle to a font.

      HFILE:
       A handle to a file opened by any of Windows File IO functions like
       OpenFile() function.

      HMENU:
       A handle to a menu or menu item.

       Again, from all you have seen, you may have noticed that most types
       identified by a prefix or a suffix. For example, handles prefixed with the
       letter H, while some pointers have the suffix _PTR, or the prefix P or LP.
       While strings with letter W are Unicode-encoded, and strings with letter T
       are OS-based.

Handles can be marshaled as the managed type System.IntPtr that represents a
pointer to an object into memory. It is worth mentioning that because
System.IntPtr represents a pointer to an object no matter what the object is, you
can use System.IntPtr for marshaling any type not handles only, but that is not
recommended because it is more difficult to work with, and it is not very flexible,


                                        33
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY

but it provides more control over the object in memory. For more information
about memory management, see chapter 6: “Memory Management.”

In addition, starting from version 2.0, new managed types for working with
unmanaged handles added to the .NET Framework. A new namespace
Microsoft.Win32.SafeHandles that contains most of the new types has been
added too. Other types exist in System.Runtime.InteropServices. These types
called managed handles.

Managed handles allow you to pass, to unmanaged code, a handle to an
unmanaged resource (such as DC) wrapped by managed class.

There are two kinds of managed handles safe and critical handles.

                               SAFE HA NDLES

Safe        handles          represented         by         the         abstract
System.Runtime.InteropServices.SafeHandle. Safe handles provide protection
from recycling security attacks by perform reference counting (and that makes
safe handles slower.) In addition, it provides critical finalization for handle
resources. As a refresher, finalization means releasing the object and its
resources from the memory, and critical finalization ensures object finalization
under any circumstances. Figure 2.2 shows the definition of SafeHandle and its
descendants.




                                      34
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY




Figure 2.2 SafeFileHandle and Descendants Class Definitions

As the diagram illustrates, SafeHandle is the base class that represents any safe
handle.                     It                   inherits                   from
System.Runtime.ConstrainedExecution.CriticalFinalizerObject that ensures the
finalization process. The following are the most common members of
SafeHandle:

      IsClosed:
       Returns a value indicates whether the handle is closed.

      IsInvalid:
       Abstract. If overridden, returns a value indicates whether the handle is
       invalid or not.

      Close()                         and                            Dispose():
       Both close the handle and dispose its resources. Internally, they rely on
       the abstract method ReleaseHandle() for releasing the handle. Therefore,


                                           35
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

       classes inherit from SafeHandle must implement this member. Be aware
       that Dispose() is inherited from System.IDispose interface that is
       implemented by SafeHandle, and Close() does not do anything except
       calling the Dispose() method. Therefore, you strictly should dispose
       (close) the handle as soon as you finish your work with it.

      ReleaseHandle():
       Protected Abstract. Use to provide handle clean-up code. This function
       should returns true if successfully released, or false otherwise. In the case
       of false, it generates a ReleaseHandleFailed Managed Debugging Assistant
       (MDA) exception that will not interrupt your code but provides you with a
       bad sign about it. Keep in mind that ReleaseHandle() called internally by
       Dispose().

      SetHandle():
       Protected. Sets the handle to the specified pre-existing handle.

      SetHandleAsInvalid():
       Sets the handle as invalid so it is no longer used.

      DangerousGetHandle():
       Returns System.IntPtr that represents the handle. Beware that if you have
       called SetHandleAsInvalid() before calling DangerousGetHandle(), it
       returns the original handle not the invalid one.

      DangerousRelease():
       Manually releasing the handle in unsafe manner. It is recommended using
       Close() or Dispose() methods instead.

      DangerousAddRef():
       Increments the reference count of the handle. It is not recommended
       using neither DangerousRelease() nor DangerousAddRef(), use safe
       methods instead. However, when working with COM, you will find
       yourself using these functions

       Do not use unsafe methods unless you really need to use it because they pass
       the protection level offered by safe handles.

Because SafeHandle is abstract, you must either implement it or use one of its
implementation classes. Only two classes from the new namespace
Microsoft.Win32.SafeHandles implement SafeHandle, both are abstract too:

      SafeHandleMinusOneIsInvalid:
       Represents a safe handle of which a value of -1 indicates that the handle is
       invalid. Therefore, IsInvalid returns true only if the handle equals to -1.

      SafeHandleZeroOrMinusOneIsInvalid:
       Represents a safe handle of which a value of 0 or -1 indicates that the
       handle is invalid. So, IsInvalid returns true only if the handle equals to 0
       or -1.

                                         36
MARSHALING WITH C# POCKET REFERENCE
                        © 2010 MOHAMMAD ELSHEIMY

Notice that, choosing between the two implementations is up to the type of the
underlying handle. If it considered invalid if set to -1, use
SafeHandleMinusOneIsInvalid. If it considered invalid if set to 0 or -1, use
SafeHandleZeroOrMinusOneIsInvalid. Using the right class for the handle
ensures that methods like IsInvalid() returns correct results. It also ensures that
CLR will mark the handle as garbage only if it is invalid.

If you need to provide a safe handle for your object, you will need to inherit from
SafeHandleMinusOneIsInvalid, SafeHandleZeroOrMinusOneIsInvalid, or even
from SafeHandle. Be aware that, you will always need to override the
ReleaseHandle() method because neither SafeHandleMinusOneIsInvalid nor
SafeHandleZeroOrMinusOneIsInvalid does override it.

As the diagram illustrates, two                 concrete   classes   inherit   from
SafeHandleZeroOrMinusOneIsInvalid:

         SafeFileHandle:
          A wrapper class for an IO device handle (e.g. HFILE.) This class internally
          overrides the ReleaseHandle() and calls the unmanaged CloseHandle()
          function to close the handle. Use when working with HFILE handles in
          Windows File IO functions like OpenFile() and CreateFile(). Internally,
          System.FileStream uses a HFILE as SafeFileHandle, and it exposes a
          constructor that accepts SafeFileHandle.

         SafeWaitHandle:
          If you are working with unmanaged thread synchronization objects like a
          Mutex or an Event, then this should be the desired marshaling type for
          synchronization objects' handles.

Now, we are going to create a file using CreateFile() function with SafeFileHandle
for the marshaling process. The definition of CreateFile() is as following:
Listing 2.7 CreateFile() Unmanaged Signature
HANDLE CreateFile(

     LPCTSTR lpFileName,

     DWORD dwDesiredAccess,

     DWORD dwShareMode,

     LPSECURITY_ATTRIBUTES lpSecurityAttributes,

     DWORD dwCreationDisposition,

     DWORD dwFlagsAndAttributes,

     HANDLE hTemplateFile

);




                                           37
MARSHALING WITH C# POCKET REFERENCE
                        © 2010 MOHAMMAD ELSHEIMY

In addition, here is the .NET code:
Listing 2.8 Create File Example
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]

    static extern SafeFileHandle CreateFile(

         string lpFileName,

         uint dwDesiredAccess,

         uint dwShareMode,

         // Because we are going to set the argument

         // to NULL we marshaled it as IntPtr

         // so we can set it to IntPtr.Zero

         // to represent a NULL value

         IntPtr lpSecurityAttributes,

         uint dwCreationDisposition,

         uint dwFlagsAndAttributes,

         // A handle for a template file

         // we are going to set it to NULL

         // so e can marshal it as System.IntPtr

         // and pass IntPtr.Zero for the NULL value

         // But, this is another way

         SafeFileHandle hTemplateFile);



    // Accessing the file for writing

    const uint GENERIC_WRITE = 0x40000000;

    // Do now allow file sharing

    const uint FILE_SHARE_NONE = 0x0;

    // Create the file and overwrites it if exists

    const uint CREATE_ALWAYS = 0x2;

    // Normal file, no attribute set

    const uint FILE_ATTRIBUTE_NORMAL = 0x80;



    static void Main()

    {

         SafeFileHandle handle =

              CreateFile("C:MyFile.txt",


                                        38
MARSHALING WITH C# POCKET REFERENCE
             © 2010 MOHAMMAD ELSHEIMY
     GENERIC_WRITE,

     FILE_SHARE_NONE,

     IntPtr.Zero, // NULL

     CREATE_ALWAYS,

     FILE_ATTRIBUTE_NORMAL,

     new SafeFileHandle(IntPtr.Zero, true));



// Because SafeFileHandle inherits

// SafeHandleZeroOrMinusOneIsInvalid

// IsInvalid returns true only if

// the handle equals to 0 or -1

if (handle.IsInvalid) // 0 or -1

{

     Console.WriteLine("ERROR: {0}", Marshal.GetLastWin32Error());

     return;

     // Marshal.GetLastWin32Error() returns the last error only

     // if DllImportAttribute.SetLastError is set to true

}



FileStream stream = new FileStream(handle, FileAccess.Write);

StreamWriter writer = new StreamWriter(stream);

writer.WriteLine("Hello, World!");

writer.Close();



/*

 * Order of methods called by

 * StreamWriter by this example:

 *

 * StreamWriter.Close()

 * - StreamWriter.BaseStream.Close()

 * - - FileStream.SafeFileHandle.Close()

 * - - - SafeHandleZeroOrMinusOneIsInvalid

 *                .Close()




                                39
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY
          * - - - - SafeHandle.Close()

          * - - - - - SafeHandle.ReleaseHandle()

          */

    }

        Although, you can use IntPtr instead of SafeFileHandle, the FileStream
        constructor that accepts the IntPtr is considered obsolete (.NET 2.0 and
        higher) and you should use the constructor that accepts the SafeFileHandle.

The next example demonstrates how to create your custom safe handle. This
custom safe handle represents a handle invalid only if equals to zero. Although,
you can extend the functionality of either SafeHandleMinusOneIsInvalid or
SafeHandleZeroOrMinusOneIsInvalid, we have inherited SafeHandle directly.
Code is very simple:
Listing 2.9 Custom Safe Handle Example
    public sealed class SafeHandleZeroIsInvalid : SafeHandle

    {

         [DllImport("Kernel32.dll")]

         [return: MarshalAs(UnmanagedType.Bool)]

         private static extern bool CloseHandle(IntPtr hObject);



         // If ownsHandle equals true handle will

         // be automatically released during the

         // finalization process, otherwise, you

         // will have the responsibility to

         // release it outside the class.

         // Automatic releasing means calling

         // the ReleaseHandle() method.

         public SafeHandleZeroIsInvalid

               (IntPtr preexistingHandle, bool ownsHandle)

               : base(IntPtr.Zero, ownsHandle)

         {

               this.SetHandle(preexistingHandle);

         }



         public override bool IsInvalid

         {



                                         40
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY
            get

            {

                  // this.handle.ToInt32() == 0

                  // this.handle == new IntPtr(0)

                  return this.handle == IntPtr.Zero;

            }

        }



        protected override bool ReleaseHandle()

        {

            return CloseHandle(this.handle);

        }

}

      Until now, I do not have an answer for why a handle could be invalid only if
      it is set to zero! Maybe you will need this for your custom handles. However,
      this is just an illustration.

                             CRITICAL HANDLES

Critical handles are the same as safe handles, except that they do not perform
reference counting, so they do not provide protection from recycling security
attacks.

Use critical handles instead of safe handles to address performance
considerations, but you will be required to provide necessary synchronization
for reference counting yourself.

Critical       handles          represented       by        the      abstract
System.Runtime.InteropServices.CriticalHandle. Figure 2.3 shows the definition
of CriticalHandle and its descendants.




                                       41
MARSHALING WITH C# POCKET REFERENCE
                        © 2010 MOHAMMAD ELSHEIMY




Figure 2.3 CriticalHandle and descendants Class Definitions

As the diagram illustrates, CriticalHandle is the base class that represents any
critical             handle.            It             inherits             from
System.Runtime.ConstrainedExecution.CriticalFinalizerObject that ensures the
finalization process. The members of CriticalHandle are the same as SafeHandle,
except that it does not include the Dangerous-prefixed methods because critical
handles themselves are dangerous because they do not provide the necessary
protection. For more information about CriticalHandle members, refer to
members of SafeHandle discussed previously.

Because CriticalHandle is abstract, you must either implement it or use one of its
implementation classes. Only two classes from the new namespace
Microsoft.Win32.SafeHandles implement CriticalHandle, both are abstract too:

      CriticalHandleMinusOneIsInvalid:
       Represents a critical handle of which a value of -1 indicates that the
       handle is invalid. Therefore, IsInvalid returns true only if the handle
       equals to -1.


                                            42
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

      CriticalHandleZeroOrMinusOneIsInvalid:
       Represents a critical handle of which a value of 0 or -1 indicates that the
       handle is invalid. So, IsInvalid returns true only if the handle equals to 0
       or -1.

Examples are the same as SafeHandle, only to change the type name.




                          PASSING MECHANISM

When passing an argument to a function, the function may require either passing
the argument by value or by reference. If the function intends to change
argument value, it requires it to be passed by reference, otherwise, by value. This
is what called passing mechanism.

Value arguments (i.e. input/In arguments,) when passed to a function, a copy of
the argument is sent to the function. Therefore, any changes to the argument do
not affect the original copy. On the other hand, reference arguments, when
passed to a function, the argument itself is passed to the function. Therefore, the
caller sees any changes happen inside the function.

Arguments passed by reference can be either In/Out (Input/Output) or only Out
(Output.) In/Out arguments are used for passing input to the function and
returning output. On the other hand, Out arguments used for returning output
only. Therefore, In/Out arguments must be initialized before they are passed to
the function. Conversely, Out arguments do not require pre-initialization.

When passing an argument by value, no changes to the PInvoke method are
required. Conversely, passing an argument by reference requires two additional
changes. The first is adding the ref modifier to the argument if it is In/Out
argument, or the out modifier if it is Out argument. The second is decorating your
argument with both InAttribute and OutAttribute attributes if it is In/Out
argument or only OutAttribute if it is Out argument. To be honest, applying those
attributes is not required, the modifiers are adequate in most cases. However,
applying them gives the CLR a notation about the passing mechanism.

As you have seen, when marshaling a string, you can marshal it as a
System.String or as a System.Text.StringBuilder. By default, StringBuilder is
passed by reference (you do not need to apply any changes.) System.String on
the other hand is passed by value.

It is worth mentioning that Windows API does not support reference arguments.
Instead, if a function requires an argument to be passed by reference, it declares
it as a pointer so that caller can see the applied changes. Other code such as COM
libraries can require either a pointer or a reference argument. In either cases,
you can safely apply the changes required. You can also marshal a pointer
argument as System.IntPtr or as the unsafe void* for example.


                                        43
MARSHALING WITH C# POCKET REFERENCE
                          © 2010 MOHAMMAD ELSHEIMY

Many of the previous examples demonstrated only functions those require
arguments to be passed by value. Some functions require one or more arguments
to be passed by reference. A good example of a function requires In/Out
argument is GetVersionEx() which returns version information of the current
system. It requires a single reference (In/Out) argument. The argument is of the
structure OSVERSIONINFOEX. For our discussion, we will leave this function to
the next chapter in the discussion of compound types.

A great deal of functions require Out arguments specially for returning results or
status information. Good examples are ReadConsole() and WriteConsole() that
require by-reference Out arguments for returning the characters read/written.
The following is the unmanaged signature for the WriteConsole() function.
Listing 2.10 WriteConsole() Unmanaged Signature
BOOL WriteConsole(

     HANDLE hConsoleOutput,

     VOID lpBuffer,

     DWORD nNumberOfCharsToWrite,

     LPDWORD lpNumberOfCharsWritten,

     LPVOID lpReserved

);

And this is the managed version along with the driver code:
Listing 2.11 Writing to Console Screen Example
      [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]

      [return: MarshalAs(UnmanagedType.Bool)]

      static extern bool WriteConsole(

          IntPtr hConsoleOutput,

          String lpBuffer,

          [param: MarshalAs(UnmanagedType.U4)]

          UInt32 nNumberOfCharsToWrite,

          [param: MarshalAs(UnmanagedType.U4)]

          out UInt32 lpNumberOfCharsWritten,

          [param: MarshalAs(UnmanagedType.AsAny)]

          object lpReserved);



      [DllImport("Kernel32.dll")]

      static extern IntPtr GetStdHandle(

          [param: MarshalAs(UnmanagedType.U4)]



                                           44
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY
        Int32 nStdHandle);



    const int STD_OUTPUT_HANDLE = -11;




    static void Main()

    {

        IntPtr handle = GetStdHandle(STD_OUTPUT_HANDLE);



        String textToWrite = "Hello, World!" + Environment.NewLine;

        uint noCharactersWritten;



        WriteConsole(handle,

            textToWrite,

            (uint)textToWrite.Length,

            out noCharactersWritten,

            null);



        Console.WriteLine("No. Characters written = {0}",

            noCharactersWritten);

    }

Finally yet importantly, chapter 6 provides you with more granular and down-
level details about the memory management and the passing mechanism.




                      ADDITIONAL TECHNIQUES

Here we will talk about techniques that should be taken into consideration when
working with unmanaged code, they are encapsulation, creating wrappers,
working with nullable arguments, and working out CLS problem.

                               ENCAPSULATION

If the function requires an argument that can be set to a value or more, you can
define these values (constants or typedefs) in an enumeration so you can easily
access every set of values separately; that technique called encapsulation


                                        45
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

(grouping.) The following example shows the MessageBoxEx() example, the most
suitable function for the example:
Listing 2.12 Message Box Example
    [DllImport("User32.dll", CharSet = CharSet.Unicode)]

    [return: MarshalAs(UnmanagedType.I4)]

    static extern UInt32 MessageBoxEx

        (IntPtr hWnd,

        [param: MarshalAs(UnmanagedType.LPTStr)]

        String lpText,

        [param: MarshalAs(UnmanagedType.LPTStr)]

        String lpCaption,

        [param: MarshalAs(UnmanagedType.U4)]

        UInt32 uType,

        [param: MarshalAs(UnmanagedType.U2)]

        UInt16 wLanguageId);



    public enum MB_BUTTON : uint

    {

        MB_OK = 0x0,

        MB_OKCANCEL = 0x1,

        MB_ABORTRETRYIGNORE = 0x2,

        MB_YESNOCANCEL = 0x3,

        MB_YESNO = 0x4,

        MB_RETRYCANCEL = 0x5,

        MB_HELP = 0x4000,

    }

    public enum MB_ICON : uint

    {

        MB_ICONHAND = 0x10,

        MB_ICONQUESTION = 0x20,

        MB_ICONEXCLAMATION = 0x30,

        MB_ICONASTERISK = 0x40,

        MB_ICONERROR = MB_ICONHAND,

        MB_ICONSTOP = MB_ICONHAND,



                                        46
MARSHALING WITH C# POCKET REFERENCE
                © 2010 MOHAMMAD ELSHEIMY
    MB_ICONWARNING = MB_ICONEXCLAMATION,

    MB_ICONINFORMATION = MB_ICONASTERISK,

}

public enum MB_DEF_BUTTON : uint

{

    MB_DEFBUTTON1 = 0x0,

    MB_DEFBUTTON2 = 0x100,

    MB_DEFBUTTON3 = 0x200,

    MB_DEFBUTTON4 = 0x300,

}

public enum MB_MODAL : uint

{

    MB_APPLMODAL = 0x0,

    MB_SYSTEMMODAL = 0x1000,

    MB_TASKMODAL = 0x2000,

}

public enum MB_SPECIAL : uint

{

    MB_SETFOREGROUND = 0x10000,

    MB_DEFAULT_DESKTOP_ONLY = 0x20000,

    MB_SERVICE_NOTIFICATION_NT3X = 0x40000,

    MB_TOPMOST = 0x40000,

    MB_RIGHT = 0x80000,

    MB_RTLREADING = 0x100000,

    MB_SERVICE_NOTIFICATION = 0x200000,

}

public enum MB_RETURN : uint

{

    IDOK = 1,

    IDCANCEL = 2,

    IDABORT = 3,

    IDRETRY = 4,

    IDIGNORE = 5,




                                   47
MARSHALING WITH C# POCKET REFERENCE
                   © 2010 MOHAMMAD ELSHEIMY
    IDYES = 6,

    IDNO = 7,

    IDCLOSE = 8,

    IDHELP = 9,

    IDTRYAGAIN = 10,

    IDCONTINUE = 11,

}



static void Main()

{

    UInt32 result = MessageBoxEx(IntPtr.Zero, // NULL

           "Do you want to save changes before closing?",

           "MyApplication",

           (UInt32)MB_BUTTON.MB_YESNOCANCEL |

           (UInt32)MB_ICON.MB_ICONQUESTION |

           (UInt32)MB_DEF_BUTTON.MB_DEFBUTTON3 |

           (UInt32)MB_SPECIAL.MB_TOPMOST,

           0);// Reserved



    if (result == 0) // error occurred

           Console.WriteLine("ERROR");

    else

    {

           MB_RETURN ret = (MB_RETURN)result;



           if (ret == MB_RETURN.IDYES)

              Console.WriteLine("User clicked Yes!");

           else if (ret == MB_RETURN.IDNO)

              Console.WriteLine("User clicked No!");

           else if (ret == MB_RETURN.IDCANCEL)

              Console.WriteLine("User clicked Cancel!");

    }

}




                                    48
MARSHALING WITH C# POCKET REFERENCE
                        © 2010 MOHAMMAD ELSHEIMY

You could also change the names of the constants to friendly names.

Figure 2.4 shows the message box resulted from running of the last code.




Figure 2.4 Message Box Example Result

In addition, you can marshal an argument as an enumeration which of the
argument type of course. The following example demonstrates this:

Listing 2.13 Console Standard Devices Example
    [DllImport("Kernel32.dll")]

    static extern IntPtr GetStdHandle(

         [param: MarshalAs(UnmanagedType.U4)]

         CONSOLE_STD_HANDLE nStdHandle);



    public enum CONSOLE_STD_HANDLE

    {

         STD_INPUT_HANDLE = -10,

         STD_OUTPUT_HANDLE = -11,

         STD_ERROR_HANDLE = -12

    }



    static void Main()

    {

         IntPtr handle;

         handle =

                GetStdHandle(CONSOLE_STD_HANDLE.STD_INPUT_HANDLE);

         if (handle == IntPtr.Zero)

                Console.WriteLine("Failed!");

         else

                Console.WriteLine("Succeeded!");

    }


                                          49
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

                              CREATING WRAPPERS

Exposing PInvoke methods to the outside the assembly is not a good practice. It
is always recommended that you group your PInvoke methods into an internal
class, and that class should be named as NativeMethods, SafeNativeMethods or
UnsafeNativeMethods. For more information about this, check Code Analyzing
Rules in MSDN documentation. Read “Move PInvokes to Native Methods Class”
article.

The following code segment illustrates the wrapper method for our
MessageBoxEx() function:
Listing 2.14 Message Box Example Revised
    public static MB_RETURN MessageBox

         (IntPtr handle, string text, string title,

         MB_BUTTON buttons, MB_ICON icon, MB_DEF_BUTTON defaultButton,

         MB_MODAL modality, MB_SPECIAL options)

    {

         UInt32 result = MessageBoxEx(handle,

             "Do you want to save changes before closing?",

             "MyApplication",

             (UInt32)buttons |

             (UInt32)icon |

             (UInt32)defaultButton |

             (UInt32)modality |

             (UInt32)options,

             0);



         if (result == 0)

             // Not recommended throwing System.Exception

             // throw a derived exception instead

             throw new Exception("FAILED");

         return (MB_RETURN)result;

    }

In addition, it is recommended changing the type of enumerations to any CLS-
compliant type like System.Int32. Check the last technique in this section.




                                           50
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

                  WORKING WITH NULLA BLE ARGUMENT S

Some function arguments are nullable. Means that they can take a NULL (null in
C#) value. To pass a NULL value to an argument, you can marshal this argument
as System.IntPtr, so you can set it to System.IntPtr.Zero to represent a NULL
value. Another trick here is creating an overload for the function, in which the
first is marshaled as the argument type, and the other is marshaled as
System.IntPtr. Thus, if you pass a System.IntPtr.Zero, CLR directs the call to the
function with System.IntPtr. Conversely, passing a value to the argument, directs
the call to the function with the correct type. The following code segment
demonstrates this technique:

       Code abbreviated for clarity.
Listing 2.15 ScrollConsoleScreenBuffer() Managed Signature
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]

    [return: MarshalAs(UnmanagedType.Bool)]

    static extern bool ScrollConsoleScreenBuffer(

          IntPtr hConsoleOutput,

          SMALL_RECT lpScrollRectangle,

          SMALL_RECT lpClipRectangle,

          COORD dwDestinationOrigin,

          CHAR_INFO lpFill);



    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]

    [return: MarshalAs(UnmanagedType.Bool)]

    static extern bool ScrollConsoleScreenBuffer(

          IntPtr hConsoleOutput,

          SMALL_RECT lpScrollRectangle,

          IntPtr lpClipRectangle,

          COORD dwDestinationOrigin,

          CHAR_INFO lpFill);

    ...



                      WORKING O UT THE CLS PROBLEM

You should know that some types are non-CLS-compliant and you should avoid
exposing them outside the assembly. For example, the famous System.UInt32 is
non-CLS-compliant, and you strictly should not expose it.




                                          51
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

Being non-CLS-compliant means that the type violates with CLS (Common
Language Specifications) specifications. Following CLS specifications helps the
interoperation of .NET languages. It helps avoiding some actions like declaring
specific types or following uncommon naming conventions.

Why to avoid such these acts? This helps the big goal of .NET Framework, the
interoperation of .NET languages. Some languages for example does not support
variable names beginning with an underscore (_) others do. Therefore, following
the CLS specifications allows your assembly to be callable from any other
assembly build with any language easily.

To force the check of CLS specification, you can decorate the assembly with
System.CLSCompliantAttribute attribute -specifying true,- and that would result
in compiler warnings whenever you try to expose non-CLS-compliant type out.

To work out this CLS dilemma, for functions require UInt32 as an argument, you
can create a wrapper that behaves as an entry-point to the private non-CLS-
compliant method. That wrapper method accepts, for instance, System.Int32 and
converts it internally to System.UInt32.

For structures, you can declare the structure as internal and continue using it the
normal way.

Again, you could replace all non-CLS-compliant types like System.UInt32 with
CLS-compliant equivalents like System.Int32 and take advantage of easily
distributing your types and assembly. However, that would not be easy in all
cases.

It   is    very    helpful    consulting        the     documentation        about
System.CLSCompliantAttribute attribute.




                        REAL-WORLD EXAMPLES

In this chapter, we have covered many aspects of marshaling in many examples.
However, most of all were just for illustration.

The following are some real-world examples that solve problems that you might
face while developing your application. Those problems can be solved only via
interoperability with unmanaged code.

           PROGRAMMATICALLY SWAPPING MO USE BUTTONS

The following code swaps mouse buttons programmatically. It makes the left
button acts like the right button (e.g. opens the context menu) and vice versa.




                                        52
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY
Listing 2.16 Swapping Mouse Buttons Sample
[DllImport("user32.dll")]

[return: MarshalAs(UnmanagedType.Bool)]

public static extern bool SwapMouseButton

    ([param: MarshalAs(UnmanagedType.Bool)] bool fSwap);




public void MakeRightButtonPrimary()

{

    SwapMouseButton(true);

}



public void MakeLeftButtonPrimary()

{

    SwapMouseButton(false);

}



         PROGRAMMATICALLY TUR NING ON THE SCREEN SAVER

The following code shows how to turn on the screen saver programmatically.
Listing 2.19 Dragging a Form without a Title Bar Sample
[DllImport("User32.dll")]

public static extern int SendMessage

    (IntPtr hWnd,

    uint Msg,

    uint wParam,

    uint lParam);



public const uint WM_SYSCOMMAND = 0x112;

public const uint SC_SCREENSAVE = 0xF140;



public enum SpecialHandles

{

    HWND_DESKTOP = 0x0,

    HWND_BROADCAST = 0xFFFF



                                           53
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY
}



public static void TurnOnScreenSaver()

{

    SendMessage(

         new IntPtr((int)SpecialHandles.HWND_BROADCAST),

         WM_SYSCOMMAND,

         SC_SCREENSAVE,

         0);

}



                 DRAGGING A FORM WITHOUT A TITLE BAR

The following code allows the form to be dragged from its body. This code is a
good example for the wrapper creating technique discussed earlier.
Listing 2.18 Dragging a Form without a Title Bar Sample
SafeNativeMethods.cs



internal static class SafeNativeMethods

{

    [DllImport("user32.dll")]

    [return: MarshalAs(UnmanagedType.I4)]

    public static extern int SendMessage(

         IntPtr hWnd,

         [param: MarshalAs(UnmanagedType.U4)]

         uint Msg,

         [param: MarshalAs(UnmanagedType.U4)]

         uint wParam,

         [param: MarshalAs(UnmanagedType.I4)]

         int lParam);



    [DllImport("user32.dll")]

    [return: MarshalAs(UnmanagedType.Bool)]

    public static extern bool ReleaseCapture();




                                           54
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY
    public const uint WM_NCLBUTTONDOWN = 0xA1; // 161

    public const uint HTCAPTION = 2;

}



HelperMethods.cs



internal static class HelperMethods

{

    public static void MoveObject(IntPtr hWnd)

    {

        SafeNativeMethods.ReleaseCapture();

        SafeNativeMethods.SendMessage

              (hWnd, SafeNativeMethods.WM_NCLBUTTONDOWN,

              SafeNativeMethods.HTCAPTION, 0);

    }

}



MainForm.cs



// In the form, write the following code

// in the handler of the MouseDown event



private void MainForm_MouseDown(object sender, MouseEventArgs e)

{

    HelperMethods.MoveObject(this.Handle);

}




                                        55
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY

                                SUMMARY

The last word to say is that MarshalAsAttribute is not required all the time.
Sometimes it is optional, and other times it is required.

For example, if you marshal blittable data types like DWORD, you can safely
ignore MarshalAsAttribute. Conversely, if you are marshaling non-blittable data
types like booleans and strings, you will need to use the MarshalAsAttribute to
ensure correct marshaling process. However, it is always better giving the CLR
and other developers a notation about the underlying data type by apply the
MarshalAsAttribute attribute to blittable data types too.

Finally yet importantly, this chapter was the key for the gate to the
interoperation with unmanaged environments. It discussed the most important
part of the marshaling process, marshaling the simple types, which you will
always need to keep it into your mind.

Next, you will learn how to work with compound types and marshal them in your
managed environment.




                                      56
MARSHALING WITH C# POCKET REFERENCE
    © 2010 MOHAMMAD ELSHEIMY




    This page intentionally left blank.




                    57
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY


                   CHAPTER 3
   M A R S H A L I N G C O M P O U N D T Y P ES



                            CHAPTER CONTENTS

Contents of this chapter:

      Chapter Contents

      Overview

      Introduction

      Marshaling Unmanaged Structures

          o How to Marshal a Structure

          o Handling Memory Layout Problem

          o Try It Out!

      Marshaling Unions

          o A Short Speech About Unions

          o How to Marshal a Union

          o Unions with Arrays

          o Try It Out!

      Value-Types and Reference-Types

      Passing Mechanism

      Real-World Examples

          o The DEVMODE Structure

          o Working with Display Settings

      Summary




                                     58
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

                                   OVERVIEW

This chapter demonstrates how to marshal compound types. Compound types
are those build of other types, for example structures and classes.

Like the previous chapter. This chapter breaks unmanaged compound types into
two categories, structures and unions. We first discuss structures and then we
will dive into unions and how to marshal them.

You might ask, why you have divided compound types into just two categories,
structures and unions, I can create classes too? The answer is easy. For its
simplicity, this book will focus primarily on Windows API. Therefore, you will
find much of our talking about Win32 functions and structures. However, the
same rules apply to classes and other unmanaged types.




                                INTRODUCTION

A compound type encapsulates related data together; it provides an organized
and arranged container for transmitting a group of variables between the client
application and the unmanaged server. It consists (usually) of variables of simple
types and (optionally) other compound types. In addition, it could define other
compound types inside.

Compound types come in two kinds:

      Unmanaged Structures

      Unmanaged Unions

An example of a structure is OSVERSIONINFOEX structure that encapsulates
operating system version information together. For those who are somewhat
familiar with DirectX, they may find that DirectX API relies heavily on structures.

As you know, because there is no compatibility between .NET and unmanaged
code, data must undergo some conversion routines for transmitting from the
managed code to the unmanaged server and vice versa, and compound types are
no exception.

In the next section, we will focus of the first kind, structures.




                                          59
MARSHALING WITH C# POCKET REFERENCE
                         © 2010 MOHAMMAD ELSHEIMY

               MARSHALING UNMANAGED STRUCTURES

                        HOW TO MAR SHAL A STR UCTURE

Unmanaged structures can be marshaled as managed structures or even classes.
Choosing between a managed structure and a class is up to you, there are no
rules to follow. However, when marshaling as managed classes, there are some
limitations with the passing mechanism as we will see later in this chapter.

When marshaling structures in the managed environment, you must take into
consideration that while you access a variable into your by its name, Windows
accesses it via its address (i.e. position) inside the memory, it does not care about
field name, but it cares about its location and size. Therefore, the memory layout
and size of the type are very crucial.

You can marshal an unmanaged structure in few steps:

      1. Create the marshaling type either a managed structure or a class.

      2. Add the type fields (variables) only. Again, layout and size of the type are
         very crucial. Therefore, fields must be ordered as they are defined, so that
         the Windows can access them correctly.

      3. Decorate your type with StructLayoutAttribute attribute specifying the
         memory layout kind.

                     HANDLING MEMORY LAYO UT PROBLEM

When marshaling an unmanaged structure, you must take care of how that type
is laid-out into memory.

Actually, application memory is divided into blocks (in a 4-bytes base,) and every
block has its own address. When you declare a variable or a type in your
program it is stored inside the memory and got its memory address.
Consequently, all data members inside a structure have their own addresses that
are relative to the address of the beginning of the structure.

Consider the following structures:
Listing 3.1 SMALL_RECT and COORD Unmanaged Signature
typedef struct SMALL_RECT {

     SHORT Left;

     SHORT Top;

     SHORT Right;

     SHORT Bottom;

};




                                          60
MARSHALING WITH C# POCKET REFERENCE
                        © 2010 MOHAMMAD ELSHEIMY


typedef struct COORD {

     SHORT X;

     SHORT Y;

};

When we declare those structures in our code they are laid-out into memory and
got addresses like that:




Figure 3.1 How Memory is Laid-Out

Thus, you should keep in mind that the size and location of each of type members
is very crucial and you strictly should take care of how this type is laid-out into
the memory.

         For now, you do not have to think about the last illustration. We will cover
         memory management in details in chapter 6.

For handling the memory layout problem, you must apply the
StructLayoutAttribute attribute to your marshaling type specifying the layout
kind using the LayoutKind property.




                                          61
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY

This property can take one of three values:

      LayoutKind.Auto                                                 (Default):
       Lets the CLR chooses how the type is laid-out into memory. Setting this
       value prevents interoperation with this type, that means that you will not
       be able to marshal the unmanaged structure with this type, and if you
       tried, an exception will be thrown.

      LayoutKind.Sequential:
       Variables of the type are laid-out sequentially. When setting this value
       ensure that all variables are on the right order as they are defined in the
       unmanaged structure.

      LayoutKind.Explicit:
       Lets you control precisely each variable’s location inside the type. When
       setting this value, you must apply the FieldOffsetAttribute attribute to
       every variable in your type specifying the relative position in bytes of the
       variable to the start of the type. Note that when setting this value, order of
       variables becomes unimportant.

For the sake of simplicity, you should lay-out all of your types sequentially.
However, when working with unions, you are required to explicitly control every
variable’s location. Unions are covered in the next section.

       We have said that you should add only the type members into the
       marshaling type, however, this is not always true. In structures where there
       is a member that you can set to determine the structure size (like the
       OPENFILENAME structure,) you can add your own members to the end of
       the structure. However, you should set the size member to the size of the
       entire structure minus the new members that you have added. This
       technique is discussed in details in chapter 6.

                                  TRY IT OUT!

The following example demonstrates how to marshal the famous structures
SMALL_RECT           and      COORD.       Both      used       earlier   with the
ScrollConsoleScreenBuffer() function in the last chapter. You can check code
listing 3.1 earlier in this chapter for the definition of the structures.

Next is the managed signature for both the structures. Note that you can marshal
them as managed classes too.
Listing 3.2 SMALL_RECT and COORD Managed Signature
    // Laying-out the structure sequentially

    [StructLayout(LayoutKind.Sequential)]

    //public class SMALL_RECT

    public struct SMALL_RECT



                                        62
MARSHALING WITH C# POCKET REFERENCE
                      © 2010 MOHAMMAD ELSHEIMY
    {

        // Because we are laying the structure sequentially,

        // we preserve field order as they are defined.



        public UInt16 Left;

        public UInt16 Top;

        public UInt16 Right;

        public UInt16 Bottom;

    }



    // The same as SMALL_RECT applies to COORD

    [StructLayout(LayoutKind.Sequential)]

    //public struct COORD

    public struct COORD

    {

        public UInt16 X;

        public UInt16 Y;

    }




                           MARSHALING UNIONS

                      A SHORT SPEECH ABO UT UNIONS

A union is a memory location that is shared by two or more different types of
variables. A union provides a way for interpreting the same bit pattern in two or
more different ways (or forms.)

In fact, unions share structures lots of characteristics, like the way they defined
and marshaled. It might be helpful to know that, like structures, unions can be
defined inside a structure or even as a single entity. In addition, unions can
define compound types inside, like structures too.

To understand unions, we will take a simple example. Consider the following
union:




                                        63
MARSHALING WITH C# POCKET REFERENCE
                          © 2010 MOHAMMAD ELSHEIMY
Listing 3.3 SOME_CHARACTER Unmanaged Signature
typedef union SOME_CHARACTER {

     int i;

     char c;

};

This was a simple union defines a character. It declared two members, i and c, it
defined them in the same memory location. Thus, it provides two ways for
accessing the character, by its code (int) and by its value (char). For this to work
it allocates enough memory storage for holding the largest member of the union
and that member is called container. Other members will overlap with the
container. In our case, the container is i because it is 4 bytes (on Win32, 16 on
Win16), while c is only 1 byte. Figure 3.2 shows how the memory is allocated for
the union.




Figure 3.2 SOME_CHARACTER Union

Because the two members are sharing the same memory location, when you
change one member the other is changed too. Consider the following C example:
Listing 3.4 Unions Example 1
int main()

{

         union CHARACTER ch;



         ch.i = 65;                 // 65 for A

         printf("c = %c", ch.c);    // prints 'A'

         printf("n");



         ch.c += 32;                // 97 for a

         printf("i = %d", ch.i);    // prints '97'

         printf("n");



         return 0;
}



                                        64
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY

When you change any of the members of the union, other members change too
because they are all share the same memory address .

Now consider the same example but with values that won’t fit into the char
member:
Listing 3.5 Unions Example 2
int main()

{

       union CHARACTER ch;



       ch.i = 330;

       printf("c = %c", ch.c);     // prints 'J'

       printf("n");               // Ops!



       ch.c += 32;

       printf("i = %d", ch.i);     // prints '362'

       printf("n");



       return 0;
}

What happened? Because char is 1 bye wide, it interprets only the first 8 bits of
the union that are equal to 32.

The same rule applies if you add another member to the union. See the following
example. Notice that order of member declarations doesn’t matter.
Listing 3.6 Unions Example 3
int main()

{

       union {

               int i;

               char c;

               short n;

       } ch;



       ch.i = 2774186;



       printf("i = %d", ch.i);



                                       65
MARSHALING WITH C# POCKET REFERENCE
                       © 2010 MOHAMMAD ELSHEIMY
       printf("n");

       printf("c = %i", (unsigned char)ch.c);

       printf("n");

       printf("n = %d", ch.n);

       printf("n");



       return 0;

}

Now, member i, the container, interprets the 32 bits. Member c, interprets the
first 8 bits (notice that we converted it to unsigned char to not to show the
negative value.) Member n, interprets the first high word (16 bits.)

You might ask: Why I need unions at all? I could easily use the cast operator to
convert between data types !

The answer is very easy. Unions come very efficient when casting between types
require much overhead. Consider the following example: You are about to write
an integer to a file. Unfortunately, there are no functions in the C standard library
that allow you to write an int to a file, and using fwrite() function requires
excessive overhead. The perfect solution is to define a union that contains an
integer and a character array to allow it to be interpreted as an integer and as a
character array when you need to pass it to fwrite() for example. See the
following code snippet:
Listing 3.7 Unions Example 4
typedef union myval{

       int i;

       char str[4];

};

In addition, unions offer you more performance than casts. Moreover, your code
will be more readable and efficient when you use unions.

       More on how the unions are laid-out into memory in chapter 6.

                          HOW TO MAR SHAL A UNION

You can marshal a union the same way as you marshal structures, except that
because of the way that unions laid-out into memory, you will need to explicitly
set variable positions inside the type.

Follow these steps to marshal a union:




                                         66
MARSHALING WITH C# POCKET REFERENCE
                     © 2010 MOHAMMAD ELSHEIMY

   1. Create your marshaling type, no matter whether your marshaling type is a
      managed structure or class. Again, classes require special handling when
      passed as function arguments. Passing mechanism is covered soon.

   2. Decorate the type with the StructLayoutAttribute attribute specifying
      LayoutKind.Explicit for the explicit layout kind.

   3. Add the type fields. Do not add fields other than those defined in the
      unmanaged signature. Because we are controlling the type layout
      explicitly, order of fields is not important.

   4. Decorate every field with the FieldOffsetAttribute attribute specifying the
      absolute position in bytes of the member from the start of the type.

The following example demonstrates how to marshal our SOME_CHARACTER
union.
Listing 3.8 SOME_CHARACTER Managed Signature
    // Unions require explicit memory layout

    [StructLayout(LayoutKind.Explicit)]

    //public class SOME_CHARACTER

    public struct SOME_CHARACTER

    {

        // Both members located on the same

        // position in the beginning of the union



        // This is the continer it is 4 bytes

        [FieldOffset(0)]

        [MarshalAs(UnmanagedType.U4)]

        public int i;

        // This is only 1 byte. Therefore, it is contained

        [FieldOffset(0)]

        public char c;

    }



    public static void Main()

    {

        SOME_CHARACTER character = new SOME_CHARACTER();



        // The code for letter 'A'


                                        67
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference
Marshaling with C# Pocket Reference

More Related Content

What's hot

Nat presentation
Nat presentationNat presentation
Nat presentationhassoon3
 
BGP (Border Gateway Protocol)
BGP (Border Gateway Protocol)BGP (Border Gateway Protocol)
BGP (Border Gateway Protocol)NetProtocol Xpert
 
Computational logic Propositional Calculus proof system
Computational logic Propositional Calculus proof system Computational logic Propositional Calculus proof system
Computational logic Propositional Calculus proof system banujahir1
 
bài giảng lập trình hướng đối tượng
bài giảng lập trình hướng đối tượngbài giảng lập trình hướng đối tượng
bài giảng lập trình hướng đối tượngMountain Nguyen
 
Configure DHCP Server and DHCP-Relay
Configure DHCP Server and DHCP-RelayConfigure DHCP Server and DHCP-Relay
Configure DHCP Server and DHCP-RelayTola LENG
 
lap trinh assembly cho VXL
lap trinh  assembly cho VXLlap trinh  assembly cho VXL
lap trinh assembly cho VXLThân Khương
 
Dhcp & dhcp relay agent in cent os 5.3
Dhcp & dhcp relay agent in cent os 5.3Dhcp & dhcp relay agent in cent os 5.3
Dhcp & dhcp relay agent in cent os 5.3Sophan Nhean
 
19 Network Layer Protocols
19 Network Layer Protocols19 Network Layer Protocols
19 Network Layer ProtocolsMeenakshi Paul
 
(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...
(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...
(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...mauricemuteti2015
 
Packet Tracer Simulation Lab Layer 2 Switching
Packet Tracer Simulation Lab Layer 2 SwitchingPacket Tracer Simulation Lab Layer 2 Switching
Packet Tracer Simulation Lab Layer 2 SwitchingJohnson Liu
 

What's hot (20)

Nat presentation
Nat presentationNat presentation
Nat presentation
 
Chuong6 hoạt động ngắt
Chuong6 hoạt động ngắtChuong6 hoạt động ngắt
Chuong6 hoạt động ngắt
 
Cpu scheduling
Cpu schedulingCpu scheduling
Cpu scheduling
 
BGP (Border Gateway Protocol)
BGP (Border Gateway Protocol)BGP (Border Gateway Protocol)
BGP (Border Gateway Protocol)
 
Computational logic Propositional Calculus proof system
Computational logic Propositional Calculus proof system Computational logic Propositional Calculus proof system
Computational logic Propositional Calculus proof system
 
bài giảng lập trình hướng đối tượng
bài giảng lập trình hướng đối tượngbài giảng lập trình hướng đối tượng
bài giảng lập trình hướng đối tượng
 
Transport layer protocol
Transport layer protocolTransport layer protocol
Transport layer protocol
 
Configure DHCP Server and DHCP-Relay
Configure DHCP Server and DHCP-RelayConfigure DHCP Server and DHCP-Relay
Configure DHCP Server and DHCP-Relay
 
Arpspoofing
ArpspoofingArpspoofing
Arpspoofing
 
lap trinh assembly cho VXL
lap trinh  assembly cho VXLlap trinh  assembly cho VXL
lap trinh assembly cho VXL
 
Default routing
Default routingDefault routing
Default routing
 
IPv6
IPv6IPv6
IPv6
 
Routing protocols
Routing protocolsRouting protocols
Routing protocols
 
Cn ipv4 addressing
Cn ipv4 addressingCn ipv4 addressing
Cn ipv4 addressing
 
V.f. pdf
V.f. pdfV.f. pdf
V.f. pdf
 
Dhcp & dhcp relay agent in cent os 5.3
Dhcp & dhcp relay agent in cent os 5.3Dhcp & dhcp relay agent in cent os 5.3
Dhcp & dhcp relay agent in cent os 5.3
 
19 Network Layer Protocols
19 Network Layer Protocols19 Network Layer Protocols
19 Network Layer Protocols
 
(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...
(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...
(CRUD) How To Connect To Microsoft Access Database Insert Update Delete Clear...
 
GRE Tunnel Configuration
GRE Tunnel ConfigurationGRE Tunnel Configuration
GRE Tunnel Configuration
 
Packet Tracer Simulation Lab Layer 2 Switching
Packet Tracer Simulation Lab Layer 2 SwitchingPacket Tracer Simulation Lab Layer 2 Switching
Packet Tracer Simulation Lab Layer 2 Switching
 

Similar to Marshaling with C# Pocket Reference

Man in-the-browser-in-depth-report
Man in-the-browser-in-depth-reportMan in-the-browser-in-depth-report
Man in-the-browser-in-depth-reportHai Nguyen
 
On Coding Guidelines
On Coding GuidelinesOn Coding Guidelines
On Coding GuidelinesDIlawar Singh
 
How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.PVS-Studio
 
How to make fewer errors at the stage of code writing. Part N1
How to make fewer errors at the stage of code writing. Part N1How to make fewer errors at the stage of code writing. Part N1
How to make fewer errors at the stage of code writing. Part N1Andrey Karpov
 
What Is MISRA and how to Cook It
What Is MISRA and how to Cook ItWhat Is MISRA and how to Cook It
What Is MISRA and how to Cook ItAndrey Karpov
 
Automate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPT
Automate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPTAutomate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPT
Automate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPTAnant Corporation
 
Dot Net Interview Questions - Part 1
Dot Net Interview Questions - Part 1Dot Net Interview Questions - Part 1
Dot Net Interview Questions - Part 1ReKruiTIn.com
 
Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3Akshay Nagpurkar
 
Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3Akshay Nagpurkar
 
Introduction to SOLID Principles
Introduction to SOLID PrinciplesIntroduction to SOLID Principles
Introduction to SOLID PrinciplesGanesh Samarthyam
 
Top 10+ Things .NET Developers Should Know About Ruby
Top 10+ Things .NET Developers Should Know About RubyTop 10+ Things .NET Developers Should Know About Ruby
Top 10+ Things .NET Developers Should Know About RubyJeff Cohen
 
Coding style of Linux Kernel
Coding style of Linux KernelCoding style of Linux Kernel
Coding style of Linux KernelPeter Chang
 
Basics of c# by sabir
Basics of c# by sabirBasics of c# by sabir
Basics of c# by sabirSabir Ali
 
DEF CON 23 - Saif el-sherei and etienne stalmans - fuzzing
DEF CON 23 - Saif el-sherei and etienne stalmans - fuzzingDEF CON 23 - Saif el-sherei and etienne stalmans - fuzzing
DEF CON 23 - Saif el-sherei and etienne stalmans - fuzzingFelipe Prado
 
Top 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | EdurekaTop 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | EdurekaEdureka!
 

Similar to Marshaling with C# Pocket Reference (20)

Man in-the-browser-in-depth-report
Man in-the-browser-in-depth-reportMan in-the-browser-in-depth-report
Man in-the-browser-in-depth-report
 
Introduction to programming using c
Introduction to programming using cIntroduction to programming using c
Introduction to programming using c
 
On Coding Guidelines
On Coding GuidelinesOn Coding Guidelines
On Coding Guidelines
 
Rust presentation convergeconf
Rust presentation convergeconfRust presentation convergeconf
Rust presentation convergeconf
 
How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.
 
How to make fewer errors at the stage of code writing. Part N1
How to make fewer errors at the stage of code writing. Part N1How to make fewer errors at the stage of code writing. Part N1
How to make fewer errors at the stage of code writing. Part N1
 
What Is MISRA and how to Cook It
What Is MISRA and how to Cook ItWhat Is MISRA and how to Cook It
What Is MISRA and how to Cook It
 
Automate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPT
Automate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPTAutomate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPT
Automate your Job and Business with ChatGPT #3 - Fundamentals of LLM/GPT
 
Object Oriented Programming
Object Oriented ProgrammingObject Oriented Programming
Object Oriented Programming
 
Dot Net Interview Questions - Part 1
Dot Net Interview Questions - Part 1Dot Net Interview Questions - Part 1
Dot Net Interview Questions - Part 1
 
Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3
 
Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3Ppl for students unit 1,2 and 3
Ppl for students unit 1,2 and 3
 
Introduction to SOLID Principles
Introduction to SOLID PrinciplesIntroduction to SOLID Principles
Introduction to SOLID Principles
 
Top 10+ Things .NET Developers Should Know About Ruby
Top 10+ Things .NET Developers Should Know About RubyTop 10+ Things .NET Developers Should Know About Ruby
Top 10+ Things .NET Developers Should Know About Ruby
 
Coding style of Linux Kernel
Coding style of Linux KernelCoding style of Linux Kernel
Coding style of Linux Kernel
 
Basics of c# by sabir
Basics of c# by sabirBasics of c# by sabir
Basics of c# by sabir
 
C sharp
C sharpC sharp
C sharp
 
DEF CON 23 - Saif el-sherei and etienne stalmans - fuzzing
DEF CON 23 - Saif el-sherei and etienne stalmans - fuzzingDEF CON 23 - Saif el-sherei and etienne stalmans - fuzzing
DEF CON 23 - Saif el-sherei and etienne stalmans - fuzzing
 
Top 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | EdurekaTop 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | Edureka
 
ERP_Up_Down.ppt
ERP_Up_Down.pptERP_Up_Down.ppt
ERP_Up_Down.ppt
 

More from Mohammad Elsheimy

Mohammad Elsheimy - Solution Developer (CV)
Mohammad Elsheimy - Solution Developer (CV)Mohammad Elsheimy - Solution Developer (CV)
Mohammad Elsheimy - Solution Developer (CV)Mohammad Elsheimy
 
PM Notebook - Appendix H - Formula Sheet
PM Notebook - Appendix H - Formula SheetPM Notebook - Appendix H - Formula Sheet
PM Notebook - Appendix H - Formula SheetMohammad Elsheimy
 
PM Notebook - Appendix G - Interpersonal/Team/Soft Skills
PM Notebook - Appendix G - Interpersonal/Team/Soft SkillsPM Notebook - Appendix G - Interpersonal/Team/Soft Skills
PM Notebook - Appendix G - Interpersonal/Team/Soft SkillsMohammad Elsheimy
 
PM Notebook - Appendix F - Forecasting Methods
PM Notebook - Appendix F - Forecasting MethodsPM Notebook - Appendix F - Forecasting Methods
PM Notebook - Appendix F - Forecasting MethodsMohammad Elsheimy
 
PM Notebook - Appendix E - Estimating Techniques
PM Notebook - Appendix E - Estimating TechniquesPM Notebook - Appendix E - Estimating Techniques
PM Notebook - Appendix E - Estimating TechniquesMohammad Elsheimy
 
PM Notebook - Appendix D - Decision-Making Techniques
PM Notebook - Appendix D - Decision-Making TechniquesPM Notebook - Appendix D - Decision-Making Techniques
PM Notebook - Appendix D - Decision-Making TechniquesMohammad Elsheimy
 
PM Notebook - Appendix C - Data Representation Tools
PM Notebook - Appendix C - Data Representation ToolsPM Notebook - Appendix C - Data Representation Tools
PM Notebook - Appendix C - Data Representation ToolsMohammad Elsheimy
 
PM Notebook - Appendix B - Data Gathering Techniques
PM Notebook - Appendix B - Data Gathering TechniquesPM Notebook - Appendix B - Data Gathering Techniques
PM Notebook - Appendix B - Data Gathering TechniquesMohammad Elsheimy
 
PM Notebook - Chapter 14 - Professional and Social Responsibility
PM Notebook - Chapter 14 - Professional and Social ResponsibilityPM Notebook - Chapter 14 - Professional and Social Responsibility
PM Notebook - Chapter 14 - Professional and Social ResponsibilityMohammad Elsheimy
 
PM Notebook - Chapter 13 - Stakeholder Management
PM Notebook - Chapter 13 - Stakeholder ManagementPM Notebook - Chapter 13 - Stakeholder Management
PM Notebook - Chapter 13 - Stakeholder ManagementMohammad Elsheimy
 
PM Notebook - Chapter 12 - Procurement Management
PM Notebook - Chapter 12 - Procurement ManagementPM Notebook - Chapter 12 - Procurement Management
PM Notebook - Chapter 12 - Procurement ManagementMohammad Elsheimy
 
PM Notebook - Chapter 11: Risk Management
PM Notebook - Chapter 11: Risk ManagementPM Notebook - Chapter 11: Risk Management
PM Notebook - Chapter 11: Risk ManagementMohammad Elsheimy
 
PM Notebook - Chapter 10: Communication Management
PM Notebook - Chapter 10: Communication ManagementPM Notebook - Chapter 10: Communication Management
PM Notebook - Chapter 10: Communication ManagementMohammad Elsheimy
 
PM Notebook - Chapter 9: Resources Management
PM Notebook - Chapter 9: Resources ManagementPM Notebook - Chapter 9: Resources Management
PM Notebook - Chapter 9: Resources ManagementMohammad Elsheimy
 
PM Notebook - Chapter 8: Quality Management
PM Notebook - Chapter 8: Quality ManagementPM Notebook - Chapter 8: Quality Management
PM Notebook - Chapter 8: Quality ManagementMohammad Elsheimy
 
PM Notebook - Chapter 7 - Cost Management
PM Notebook - Chapter 7 - Cost ManagementPM Notebook - Chapter 7 - Cost Management
PM Notebook - Chapter 7 - Cost ManagementMohammad Elsheimy
 
PM Notebook - Chapter 6 - Schedule Management
PM Notebook - Chapter 6 - Schedule ManagementPM Notebook - Chapter 6 - Schedule Management
PM Notebook - Chapter 6 - Schedule ManagementMohammad Elsheimy
 
PM Notebook - Chapter 5 - Scope Management
PM Notebook - Chapter 5 - Scope ManagementPM Notebook - Chapter 5 - Scope Management
PM Notebook - Chapter 5 - Scope ManagementMohammad Elsheimy
 
PM Notebook - Chapter 4: Integration Management
PM Notebook - Chapter 4: Integration ManagementPM Notebook - Chapter 4: Integration Management
PM Notebook - Chapter 4: Integration ManagementMohammad Elsheimy
 

More from Mohammad Elsheimy (20)

Mohammad Elsheimy - Solution Developer (CV)
Mohammad Elsheimy - Solution Developer (CV)Mohammad Elsheimy - Solution Developer (CV)
Mohammad Elsheimy - Solution Developer (CV)
 
PM Notebook
PM NotebookPM Notebook
PM Notebook
 
PM Notebook - Appendix H - Formula Sheet
PM Notebook - Appendix H - Formula SheetPM Notebook - Appendix H - Formula Sheet
PM Notebook - Appendix H - Formula Sheet
 
PM Notebook - Appendix G - Interpersonal/Team/Soft Skills
PM Notebook - Appendix G - Interpersonal/Team/Soft SkillsPM Notebook - Appendix G - Interpersonal/Team/Soft Skills
PM Notebook - Appendix G - Interpersonal/Team/Soft Skills
 
PM Notebook - Appendix F - Forecasting Methods
PM Notebook - Appendix F - Forecasting MethodsPM Notebook - Appendix F - Forecasting Methods
PM Notebook - Appendix F - Forecasting Methods
 
PM Notebook - Appendix E - Estimating Techniques
PM Notebook - Appendix E - Estimating TechniquesPM Notebook - Appendix E - Estimating Techniques
PM Notebook - Appendix E - Estimating Techniques
 
PM Notebook - Appendix D - Decision-Making Techniques
PM Notebook - Appendix D - Decision-Making TechniquesPM Notebook - Appendix D - Decision-Making Techniques
PM Notebook - Appendix D - Decision-Making Techniques
 
PM Notebook - Appendix C - Data Representation Tools
PM Notebook - Appendix C - Data Representation ToolsPM Notebook - Appendix C - Data Representation Tools
PM Notebook - Appendix C - Data Representation Tools
 
PM Notebook - Appendix B - Data Gathering Techniques
PM Notebook - Appendix B - Data Gathering TechniquesPM Notebook - Appendix B - Data Gathering Techniques
PM Notebook - Appendix B - Data Gathering Techniques
 
PM Notebook - Chapter 14 - Professional and Social Responsibility
PM Notebook - Chapter 14 - Professional and Social ResponsibilityPM Notebook - Chapter 14 - Professional and Social Responsibility
PM Notebook - Chapter 14 - Professional and Social Responsibility
 
PM Notebook - Chapter 13 - Stakeholder Management
PM Notebook - Chapter 13 - Stakeholder ManagementPM Notebook - Chapter 13 - Stakeholder Management
PM Notebook - Chapter 13 - Stakeholder Management
 
PM Notebook - Chapter 12 - Procurement Management
PM Notebook - Chapter 12 - Procurement ManagementPM Notebook - Chapter 12 - Procurement Management
PM Notebook - Chapter 12 - Procurement Management
 
PM Notebook - Chapter 11: Risk Management
PM Notebook - Chapter 11: Risk ManagementPM Notebook - Chapter 11: Risk Management
PM Notebook - Chapter 11: Risk Management
 
PM Notebook - Chapter 10: Communication Management
PM Notebook - Chapter 10: Communication ManagementPM Notebook - Chapter 10: Communication Management
PM Notebook - Chapter 10: Communication Management
 
PM Notebook - Chapter 9: Resources Management
PM Notebook - Chapter 9: Resources ManagementPM Notebook - Chapter 9: Resources Management
PM Notebook - Chapter 9: Resources Management
 
PM Notebook - Chapter 8: Quality Management
PM Notebook - Chapter 8: Quality ManagementPM Notebook - Chapter 8: Quality Management
PM Notebook - Chapter 8: Quality Management
 
PM Notebook - Chapter 7 - Cost Management
PM Notebook - Chapter 7 - Cost ManagementPM Notebook - Chapter 7 - Cost Management
PM Notebook - Chapter 7 - Cost Management
 
PM Notebook - Chapter 6 - Schedule Management
PM Notebook - Chapter 6 - Schedule ManagementPM Notebook - Chapter 6 - Schedule Management
PM Notebook - Chapter 6 - Schedule Management
 
PM Notebook - Chapter 5 - Scope Management
PM Notebook - Chapter 5 - Scope ManagementPM Notebook - Chapter 5 - Scope Management
PM Notebook - Chapter 5 - Scope Management
 
PM Notebook - Chapter 4: Integration Management
PM Notebook - Chapter 4: Integration ManagementPM Notebook - Chapter 4: Integration Management
PM Notebook - Chapter 4: Integration Management
 

Recently uploaded

Q4-PPT-Music9_Lesson-1-Romantic-Opera.pptx
Q4-PPT-Music9_Lesson-1-Romantic-Opera.pptxQ4-PPT-Music9_Lesson-1-Romantic-Opera.pptx
Q4-PPT-Music9_Lesson-1-Romantic-Opera.pptxlancelewisportillo
 
How to Add Barcode on PDF Report in Odoo 17
How to Add Barcode on PDF Report in Odoo 17How to Add Barcode on PDF Report in Odoo 17
How to Add Barcode on PDF Report in Odoo 17Celine George
 
Daily Lesson Plan in Mathematics Quarter 4
Daily Lesson Plan in Mathematics Quarter 4Daily Lesson Plan in Mathematics Quarter 4
Daily Lesson Plan in Mathematics Quarter 4JOYLYNSAMANIEGO
 
ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...
ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...
ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...JojoEDelaCruz
 
EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...
EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...
EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...liera silvan
 
Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Celine George
 
Congestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentationCongestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentationdeepaannamalai16
 
Student Profile Sample - We help schools to connect the data they have, with ...
Student Profile Sample - We help schools to connect the data they have, with ...Student Profile Sample - We help schools to connect the data they have, with ...
Student Profile Sample - We help schools to connect the data they have, with ...Seán Kennedy
 
Karra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptxKarra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptxAshokKarra1
 
Keynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designKeynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designMIPLM
 
Measures of Position DECILES for ungrouped data
Measures of Position DECILES for ungrouped dataMeasures of Position DECILES for ungrouped data
Measures of Position DECILES for ungrouped dataBabyAnnMotar
 
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...Nguyen Thanh Tu Collection
 
4.16.24 Poverty and Precarity--Desmond.pptx
4.16.24 Poverty and Precarity--Desmond.pptx4.16.24 Poverty and Precarity--Desmond.pptx
4.16.24 Poverty and Precarity--Desmond.pptxmary850239
 
Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)Mark Reed
 
Virtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdf
Virtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdfVirtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdf
Virtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdfErwinPantujan2
 
ANG SEKTOR NG agrikultura.pptx QUARTER 4
ANG SEKTOR NG agrikultura.pptx QUARTER 4ANG SEKTOR NG agrikultura.pptx QUARTER 4
ANG SEKTOR NG agrikultura.pptx QUARTER 4MiaBumagat1
 
Presentation Activity 2. Unit 3 transv.pptx
Presentation Activity 2. Unit 3 transv.pptxPresentation Activity 2. Unit 3 transv.pptx
Presentation Activity 2. Unit 3 transv.pptxRosabel UA
 

Recently uploaded (20)

Q4-PPT-Music9_Lesson-1-Romantic-Opera.pptx
Q4-PPT-Music9_Lesson-1-Romantic-Opera.pptxQ4-PPT-Music9_Lesson-1-Romantic-Opera.pptx
Q4-PPT-Music9_Lesson-1-Romantic-Opera.pptx
 
How to Add Barcode on PDF Report in Odoo 17
How to Add Barcode on PDF Report in Odoo 17How to Add Barcode on PDF Report in Odoo 17
How to Add Barcode on PDF Report in Odoo 17
 
Daily Lesson Plan in Mathematics Quarter 4
Daily Lesson Plan in Mathematics Quarter 4Daily Lesson Plan in Mathematics Quarter 4
Daily Lesson Plan in Mathematics Quarter 4
 
ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...
ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...
ENG 5 Q4 WEEk 1 DAY 1 Restate sentences heard in one’s own words. Use appropr...
 
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptxLEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
 
EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...
EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...
EmpTech Lesson 18 - ICT Project for Website Traffic Statistics and Performanc...
 
Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17
 
Congestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentationCongestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentation
 
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptxYOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
 
Student Profile Sample - We help schools to connect the data they have, with ...
Student Profile Sample - We help schools to connect the data they have, with ...Student Profile Sample - We help schools to connect the data they have, with ...
Student Profile Sample - We help schools to connect the data they have, with ...
 
Karra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptxKarra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptx
 
FINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptx
FINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptxFINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptx
FINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptx
 
Keynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designKeynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-design
 
Measures of Position DECILES for ungrouped data
Measures of Position DECILES for ungrouped dataMeasures of Position DECILES for ungrouped data
Measures of Position DECILES for ungrouped data
 
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
 
4.16.24 Poverty and Precarity--Desmond.pptx
4.16.24 Poverty and Precarity--Desmond.pptx4.16.24 Poverty and Precarity--Desmond.pptx
4.16.24 Poverty and Precarity--Desmond.pptx
 
Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)Influencing policy (training slides from Fast Track Impact)
Influencing policy (training slides from Fast Track Impact)
 
Virtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdf
Virtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdfVirtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdf
Virtual-Orientation-on-the-Administration-of-NATG12-NATG6-and-ELLNA.pdf
 
ANG SEKTOR NG agrikultura.pptx QUARTER 4
ANG SEKTOR NG agrikultura.pptx QUARTER 4ANG SEKTOR NG agrikultura.pptx QUARTER 4
ANG SEKTOR NG agrikultura.pptx QUARTER 4
 
Presentation Activity 2. Unit 3 transv.pptx
Presentation Activity 2. Unit 3 transv.pptxPresentation Activity 2. Unit 3 transv.pptx
Presentation Activity 2. Unit 3 transv.pptx
 

Marshaling with C# Pocket Reference

  • 1. MARSHALING WITH C# POCKET REFERENCE Author | Mohammad Elsheimy
  • 2. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY MARSHALING WITH C# POCKET REFERENCE Mohammad Elsheimy A freelance software developer and trainer 2
  • 3. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY © 2010 Mohammad Elsheimy 3
  • 4. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY ABOUT THE AUTHOR Mohammad Elsheimy Mohammad is a MCP, MCTS, and MCPD independent consultant, trainer, and author. He was born in 1991 in KB, Egypt. Besides self-studying computer science, yet, he is a student in Al-Azhar Holy Quran Institute. There, he studies Islamic legislation and sciences related to Islam, The Holy Quran, and the Arabic language. Mohammad loves community work. He always works on helping developers and average users all over the world. He is writing in many places including his own blog, http://JustLikeAMagic.WordPress.com. You can reach Mohammad at Geming.Leader@Hotmail.com. In addition, you can reach him directly at +2 018 577 1171. WHO SHOULD READ THIS BOOK? This book discusses the marshaling process between managed and unmanaged code using C#, devoted for developers who know the basics of unmanaged code (especially Windows API) and platform invocation. For the sake of simplicity, this book focuses on Windows API as the source for unmanaged code. However, information in this book can be applied to any of the unmanaged environments. In addition, this book assumes a 32-bit version of Windows. All DWORDs, HANDLEs, etc. are considered 4-bytes. If you want to hand your application to 64-bit machine, consider revising your code to avoid memory layout problems. For VB.NET developers, it is helpful reading pages in Appendix A. 4
  • 5. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY CONTENTS AT A GLANCE About the Author Who should read this book? Chapter 1: Introducing Marshaling Chapter 2: Marshaling Simple Types Chapter 3: Marshaling Compound Types Chapter 4: Marshaling Arrays Chapter 5: Marshaling Callbacks Chapter 6: Memory Management Chapter 7: Controlling the Marshaling Process Appendix A: What about VB.NET Where to Go Next References Figures Code Listings Glossary 5
  • 6. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY TABLE OF CONTENTS About the Author Who should read this book? Chapter 1: Introducing Marshaling What is Marshaling? Why Marshaling? When I Need to Marshal? Chapter 2: Marshaling Simple Types Chapter Contents Overview Simple and Compound data Types Blittable and Non-Blittable Data Types Marshaling Blittable Data Types Numeric Data Types Textual Data Types Examining Type Definition Variants Try It Out! A Rule of Thumb Marshaling Booleans The Two Types Try It Out! Marshaling Textual Data types How to Marshal Strings and Buffers Handling Character Encoding Try It Out! 6
  • 7. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Marshaling Handles Generic Handles Safe Handles Critical Handles Passing Mechanism Additional Techniques Encapsulation Creating Wrappers Working with Nullable Arguments Working out the CLS Problem Real-World Examples Programmatically Swapping Mouse Buttons Programmatically Turning On the Screen Saver Dragging a Form without a Title Bar Summary Chapter 3: Marshaling Compound Types Chapter Contents Overview Introduction Marshaling Unmanaged Structures How to Marshal a Structure Handling Memory Layout Problem Try It Out! Marshaling Unions A Short Speech About Unions How to Marshal a Union Unions with Arrays Try It Out! 7
  • 8. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Value-Types and Reference-Types Passing Mechanism Real-World Examples The DEVMODE Structure Working with Display Settings Summary Chapter 4: Marshaling Arrays Chapter 5: Marshaling Callbacks Chapter 6: Memory Management Chapter 7: Controlling the Marshaling Process Appendix A: What about VB.NET Where to Go Next References Figures Code Listings Glossary 8
  • 9. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY This page intentionally left blank. 9
  • 10. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY CHAPTER 1 INTRODUCING MARSHALING WHAT IS MARSHALING ? Marshaling is the process of creating a bridge between managed code and unmanaged code; it is the homer that carries messages from the managed to the unmanaged environment and reverse. It is one of the core services offered by the CLR (Common Language Runtime). Because much of the types in unmanaged environment do not have counterparts in managed environment, you need to create conversion routines that convert the managed types into unmanaged and vice versa; and that is the marshaling process. As a refresher, we call .NET code "managed" because it is controlled (managed) by the CLR. Other code that is not controlled by the CLR is called unmanaged . WHY MARSHALING ? You already know that there is no such compatibility between managed and unmanaged environments. In other words, .NET does not contain such the types HRESULT, DWORD, and HANDLE that exist in the realm of unmanaged code. Therefore, you need to find a .NET substitute or create your own if needed. That is what called marshaling. An example is the unmanaged DWORD; it is an unsigned 32-bit integer, so we can marshal it in .NET as System.UInt32. Therefore, System.UInt32 is a substitute for the unmanaged DWORD. On the other hand, unmanaged compound types (structures, unions, etc.) do not have counterparts or substitutes in the managed environment. Thus, you’ll need to create your own managed types (structures/classes) that will serve as the substitutes for the unmanaged types you use. 10
  • 11. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY WHEN I NEED TO MARSH AL ? Marshaling comes handy when you are working with unmanaged code, whether you are working with Windows API or COM components. It helps you interoperating (i.e. working) correctly with these environments by providing a way to share data between the two environments. Figure 1 shows the marshaling process, where it fall, and how it is required in the communication process between the two environments. Figure 1.1 - The Marshaling Process 11
  • 12. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY This page intentionally left blank. 12
  • 13. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY CHAPTER 2 MARSHALING SIMPLE TYPES CHAPTER CONTENTS Contents of this chapter:  Chapter Contents  Overview  Simple and Compound data Types  Blittable and Non-Blittable Data Types  Marshaling Blittable Data Types o Numeric Data Types o Textual Data Types o Examining Type Definition o Variants o Try It Out!  A Rule of Thumb  Marshaling Booleans o The Two Types o Try It Out!  Marshaling Textual Data types o How to Marshal Strings and Buffers o Handling Character Encoding o Try It Out!  Marshaling Handles o Generic Handles o Safe Handles 13
  • 14. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY o Critical Handles  Passing Mechanism  Additional Techniques o Encapsulation o Creating Wrappers o Working with Nullable Arguments o Working out the CLS Problem  Real-World Examples o Programmatically Swapping Mouse Buttons o Programmatically Turning On the Screen Saver o Dragging a Form without a Title Bar  Summary OVERVIEW This chapter discusses the nitty-gritty part of marshaling process. It is the base for the rest of discussion about marshaling. It is about marshaling simple data types. The first section of this chapter breaks data types into two categories, simple and compound. Simple types (integers, booleans, etc.) are those that are not made of other types. On the contrary, compound types (structures and classes) are those types that require special handling and made of other types. After that, we will dig into the discussion of simple types and we will break them into two categories, blittable and non-blittable. Before we end this chapter, we will discuss the passing mechanism and handles in .NET Framework. SIMPLE AND COMPOUND DATA TYPES There are two kinds of data types:  Simple (primitive/basic) 14
  • 15. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY  Compound (complex) Primitive data types are those that are not defined in terms of other data types. They are the basis for all other types. Examples of managed primitives are numbers like System.Byte, System.Int32, System.UInt32, and System.Double, strings like System.Char and System.String, and handles like System.IntPtr. Compound data types are those that built up of other data types. For example a class or a structure that encapsulates simple types and other compound types. We will use terms simple, primitive, and basic types to refer to base types like integers, strings, etc. Terms compound, and complex types also will be used interchangeably to refer to classes and structures. Some considers that strings are not primitives. BLITTABLE AND NON-BLITTABLE DATA TYPES Most data types have common representations in both managed and unmanaged memory and do not require special handling. These types are called blittable types because they do not require special handling when passed between managed and unmanaged code. Other types that require special handling are called non-blittable types. You can think that most of simple types are blittable and all of compound types are non-blittable. The following table lists the blittable data types exist in .NET (their counterparts in unmanaged code will be covered soon): Table 2.1 Blittable Types Managed Type Description System.SByte 8-bit signed integer. System.Byte 8-bit unsigned integer System.Int16 16-bit signed integer. System.UInt16 16-bit unsigned integer System.Int32 32-bit signed integer System.UInt32 32-bit unsigned integer System.Int64 64-bit signed integer System.UInt64 64-bit unsigned integer System.IntPtr Signed pointer System.UIntPtr Unsigned pointer 15
  • 16. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY MARSHALING BLITTABLE DATA TYPES You can marshal an unmanaged simple data type by tracking its definition then finding its counterpart (marshaling type) in the managed environment based on its definition (we will see how soon.) NUMERIC DATA TYPES The following table lists some of the unmanaged data types in Windows, their C/C++ keywords, and their counterparts (marshaling types) in .NET. As you might guess, by tracking each of these unmanaged types, we were able to find its managed counterpart. Notice that so Table 2.2 Numeric Data Types Description Windows Type C/C++ Managed Type C# Keyword Keyword 8-bit signed CHAR char System.SByte sbyte integer 8-bit unsigned BYTE unsigned char System.Byte byte integer 16-bit signed SHORT Short System.Int16 short integer 16-bit unsigned WORD and USHORT unsigned System.UInt16 ushort integer short 32-bit signed INT, INT32, LONG, int, long System.Int32 int integer and LONG32 32-bit unsigned DWORD, DWORD32, unsigned int, System.UInt32 uint integer UINT, and UINT32 unsigned long 64-bit signed INT64, LONGLONG, __int64, long System.Int64 long integer and LONG64 long 64-bit unsigned DWORDLONG, unsigned System.UInt64 ulong integer DWORD64, __int64, ULONGLONG, and unsigned long UINT64 long Floating-point FLOAT float System.Double double integer Notice that long and int defer from a platform to another and from a compiler to another. In 32-bit versions of Windows, most compilers refer to both long and int as 32-bit integers. 16
  • 17. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Some types are based on the version of Windows. DWORD, for instance, is 32 bits on 32-bit versions and 64 bits on 64-bit versions of Windows. This writing assumes that it is a 32-bit version of Windows. Know that there is no difference between Windows data types and C/C++ data types. Windows data types are just aliases for the actual C types. Do not be confused with the many types that refer to one thing, they are all just names (aliases.) INT, INT32, LONG, and LONG32 are all 32-bit integers for instance. To keep things simple, we will focus on Windows API in our examples. Although, some unmanaged types have names similar to names of some managed types, they have different meanings. An example is LONG, it has similar name as System.Long. However, LONG is 32-bit and System.Long is 64-bit! If you need to learn more about these types, check out the article “Windows Data Types” in MSDN library. TEXTUAL DATA TYPES In addition to the numeric data types, you will need to know how to marshal unmanaged textual data types (a single character or a string.) However, these types are non-blittable, so they require special handling. The following table lists briefly unmanaged textual data types. Table 2.3 Textual Data Types Description Unmanaged Type(s) Managed Type 8-bit ANSI character CHAR System.Char 16-bit Unicode character WCHAR System.Char 8-bit ANSI string of LPSTR, LPCSTR, PCSTR, and System.String characters PSTR 16-bit Unicode string of LPCWSTR, LPWSTR, System.String characters PCWSTR, and PWSTR Soon we will cover textual data types in details. EXAMINING TYPE DEFINITIO N As we have said, for the sake of simplicity, we will use Windows API as the base for our discussion in this book. Therefore, you need to know that all Windows Data Types (INT, DWORD, etc.) are just names (technically, typedefs) for the actual C types. Therefore, many names may refer to one thing just as INT and LONG. 17
  • 18. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Thus, we can say that LONG is defined as C int and DWORD is defined as C unsigned long. INT and LONG are easy to marshal. However, there are primitive types that you will need to track their definitions to know how to marshal it. Remember that we will use MSDN documentation (specially the article “Windows Data Types”) when tracking unmanaged data types (Windows data types specially.) The next are some of the types defined as another types. You can think of these types as aliases for the base types. Yet, some are platform-specific, and others not.  HRESULT: As you will see, plenty of functions return a HRESULT to represent the status of the operation. If HRESULT equals to zero, then the function succeeded, otherwise it represents the error code or status information for the operation. HRESULT defined as LONG, and LONG in turn defined as a 32-bit signed integer. Therefore, you can marshal HRESULT as System.Int32.  BOOL and BOOLEAN: Both are Boolean types, that means that they take either TRUE (non-zero) or FALSE (zero.) The big difference between BOOL and BOOLEAN is that BOOL is defined as INT, thus occupies 4 bytes. BOOLEAN on the other hand is defined as BYTE, thus occupies only 1 byte. Booleans are covered soon.  HFILE: A handle to a file opened using one of the Windows File IO functions like OpenFile() function. This type is defined as INT, and INT in turn is defined as a 32-bit signed integer. Therefore, you can marshal HFILE as System.Int32. Although, HFILE defined as INT, handles should be marshaled as System.IntPtr, which is internally encapsulates the raw handle. To be clear, you would better marshal an unmanaged handle as a System.Runtime.InteropServices.SafeHandle or CriticalHandle, this is the ideal marshaling type for any handle. Hence, file handles best marshaled as Microsoft.Win32.SafeHandles.SafeFileHandle that is derived from SafeHandleZeroOrMinusOneIsInvalid that is in turn derived from the abstract class System.Runtime.InteropServices.SafeHandle. For more details about handles, refer to the section "Marshaling Handles" later in this chapter. 18
  • 19. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY In addition, there are types that are variable based on the operating system. Examples are:  INT_PTR: A pointer to a signed integer. Defined as INT64 if this is a 64-bit OS, or INT otherwise.  LONG_PTR: A pointer to a signed long. Defined as INT64 if this is a 64-bit OS, or LONG otherwise.  UINT_PTR: A pointer to an unsigned integer. Defined as DWORD64 if this is a 64-bit OS, or DWORD otherwise.  ULONG_PTR: A pointer to an unsigned long. Defined as DWORD64 if this is a 64-bit OS, or DWORD otherwise. Keep in mind that there is a big difference between a variable and a pointer to a variable. A variable refers directly to its value into the memory. However, a pointer contains an address of another value into the memory. Consider the following illustration, Figure 2.1: Figure 2.1 - Pointers into Memory In the illustration above, the variable i contains the value 320 and you can get the value from the variable directly. The pointer ptr on the other hand contains the 19
  • 20. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY address of the variable i. Thus, it indirectly contains the value of the variable i. That is why we cannot get the value of the pointer directly. We need to dereference it first before retrieving its value. More on pointers later in this chapter. Memory management is discussed in details in chapter 6. In addition, for textual data types, there are types variable based on Unicode definition (strings and buffers are covered soon.) Examples are:  TBYTE and TCHAR: Defined as WCHAR if UNICODE defined, otherwise CHAR.  LPCTSTR, LPTSTR, and PCTSTR: All defined as LPCWSTR if UNICODE defined, otherwise LPCSTR.  PTSTR: Defined as PWSTR if UNICODE defined, otherwise PSTR. More on textual data types and Unicode later in this chapter. Notice that some types have special characters in their names. For example, A in textual data types stands for ANSI, and W in stands for Wide, which means Unicode. In addition, the letter T in textual information too means it varies based on OS. Another example is the prefix P (lowercase,) it means a pointer, and LP means a long pointer. LPC stands for long pointer to a constant. VARIANTS In addition, Win32 API defines the types VOID, LPVOID, and LPCVOID. VOID indicates that the function does accept no arguments. Consider the following function: DWORD GetVersion(VOID); It is required to tag the function with VOID if it does not accept any arguments (that is one of the specifications of C89.) Notice that VOID is defined as void. LPVOID and LPCVOID are defined as any type (variant). That means that they can accept any value. They can be marshaled as integers, strings, handles, or even compound types, anything you want. In addition, you can marshal them as System.IntPtr, so you can set them to the address of any object in memory. In addition, you can marshal them as pointers to object. For example, marshaling a LPCVOID as System.Int32* (a pointer to an integer) in unsafe code. Moreover, you can use unsafe code and marshal them as void*. Furthermore, you can 20
  • 21. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY marshal them as System.Object, so you can set them to any type (refer to chapter 6 for more information about memory management and unsafe code.) It is worth mentioning that when working with VOIDs it is recommended decorating your variable with MarshalAsAttribute attribute specifying UnmanagedType.AsAny which tells the compiler to work out the marshaling process and sets the type of the argument at runtime. Refer to the last chapter: "Controlling the Marshaling Process" for more information about this attribute. If you have worked with traditional Visual Basic, thinking about LPVOID and LOCVOID as a Variant could help too much. If you are interoperating with the traditional Visual Basic code, you can use the same way we did on marshaling LPVOID and LPCVOID in marshaling the type Variant. TRY IT OUT! Now, we will try to create the PInvoke method for the MessageBoxEx() function. The example demonstrates how to control precisely the marshaling process using the MarshalAsAttribute attribute. We will cover this attribute and more in the last chapter of this book: "Controlling the Marshaling Process." Handles are covered in the section: "Marshaling Handles" of this chapter. The following example creates the PInvoke method for the MessageBoxEx() function and calls it to display a friendly message to the user. The definition of the MessageBoxEx() function is as following: Listing 2.1 MessageBoxEx() Unmanaged Signature int MessageBoxEx( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, WORD wLanguageId ); And here is the managed signature (the PInvoke method) of this function: In order for the example to run you must add a using statement to System.Runtime.InteropServices namespace. Be sure to add it for all examples throughout this book. Listing 2.2 MessageBoxEx() Managed Signature // CharSet.Unicode defines the UNICODE. // Use either this way to control 21
  • 22. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY // the whole function, or you can control // the parameters individually using the // MarshalAsAttribute attribute [DllImport("User32.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.I4)] static extern Int32 MessageBoxEx (IntPtr hWnd, // Marshaling as Unicode characters [param: MarshalAs(UnmanagedType.LPTStr)] String lpText, // Marshaling as Unicode characters [param: MarshalAs(UnmanagedType.LPTStr)] String lpCaption, // Marshaling as 4-bytes (32-bit) unsigned integer [param: MarshalAs(UnmanagedType.U4)] UInt32 uType, // Marshaling as 2-bytes (16-bit) unsigned integer [param: MarshalAs(UnmanagedType.U2)] UInt16 wLanguageId); For more information about marshaling strings, see section “Marshaling Strings and Buffers” later in this chapter. A RULE OF THUMB Keep in mind that. .NET Framework allows you to take a granular level of control over the marshaling process and that would be very complicated. However, things can be so simple. You can ignore attributes in most cases and just use the counterparts and CLR will do its best. Likely, you are not required to use managed signed integers for 22
  • 23. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY unmanaged equivalents. You can use managed signed integers for unmanaged unsigned integers and vice versa. You can also marshal a SHORT as System.Char! The key point is that as long as the managed marshal type occupies the same memory size as the unmanaged type, you are in safe. However, keeping things in its right position helps avoiding undesirable errors that maybe very difficult to know and handle. Another thing that you should keep in mind that the information in this book can be applied to any unmanaged environment. You can apply this information when interoperating with Windows API, C/C++ libraries, Visual Basic, COM, OLE, ActiveX, etc. However, for the sake of simplicity, we will talk about the Windows API as the source of the unmanaged code. Another thing, this writing assumes a 32-bit version of Windows. Thus, it considers that DWORDs, HANDLEs, etc. are all 4 bytes. On 64-bit versions, they are 8 bytes. MARSHALING BOOLEANS THE TWO TYPES In general, marshaling simple data types is very easy and booleans are no exception. However, Booleans are non-blittable types. Therefore, they require some handling. There are some notes about marshaling booleans in the managed environment. The first thing to mention about is that Windows defines two types of Boolean variables: 1. BOOL: Defined as INT, therefore, it is 4-bytes wide. 2. BOOLEAN: Defined as BYTE, therefore it is only 1-byte. Both can be set to non-zero to indicate a true (TRUE) value, and zero otherwise (FALSE.) Again, the two types exist only in the Windows SDK. Other environments may define other types with similar names. While it is true that BOOL and BOOLEAN are best marshaled as System.Boolean, BOOL can be marshaled as System.Int32 too, because it is defined as a 32-bit integer. On the other hand, BOOLEAN can be marshaled as System.Byte or System.U1, because it is defined as 8-bits integer. Do you remember our rule of thumb? 23
  • 24. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Take into consideration that whether you are marshaling your Boolean type to System.Boolean, System.Int32, or System.Byte, it is recommended that you apply MarshalAsAttribute attribute to the variable to specify the underlying unmanaged type. For example, to specify that the underlying type is BOOL, specify UnmanagedType.Bool (recommended) or UnmanagedType.I4 in the MarshalAsAttribute constructor. On the other hand, BOOLEAN can be specified as UnmanagedType.U1. If you omit MarshalAsAttribute, CLR assumes the default behavior for System.Boolean, which is 2 bytes wide. For more information about MarshalAsAttribute attribute, see the last chapter: "Controlling the Marshaling Process." TRY IT OUT! Fortunately, plenty of functions return BOOL indicating whether the function succeeded (TRUE) or failed (FALSE.) The following is the definition of the famous CloseHandle() function: Listing 2.3 CloseHandle() Unmanaged Signature BOOL CloseHandle(HANDLE hObject); The managed version of CloseHandle() is as following: Listing 2.4 CloseHandle() Managed Signature [DllImport("Kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] // In addition, you can marshal it as: // [return: MarshalAs(UnmanagedType.I4)] // Moreover, You can change System.Boolean to System.Int32 static extern Boolean CloseHandle(IntPtr hObject); Handles covered soon. For now, it is OK to know that all handles marshaled to System.IntPtr. MARSHALING TEXTUAL DATA TYPES HOW TO MAR SHAL STRINGS A ND BUFFERS This section discusses how to marshal strings and buffers. We will use the terms string and buffer interchangeably to refer to a sequence of characters. Two types exist in the managed environment for marshaling unmanaged string buffers. They are System.String and System.Text.StringBuilder. Of course, they 24
  • 25. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY both hold character sequences. However, StringBuilder is more advantageous because it is very efficient working with mutable strings than System.String. Every time you use one of the methods of System.String class or you pass a System.String to a function, normally, you create a new string object in memory, which requires a new allocation of memory space for the new object. In addition, if the function changes the string you will not get the results back. That is why System.String is called immutable. On the other hand, StringBuilder does not require re-allocating of space unless you exceed its capacity. Besides the talk about marshaling, you should use StringBuilder to accommodate performance issues if you often change the same string many times. To keep System.String immutable, the marshaler copies the contents of the string to another buffer before calling the function, and then it passes that buffer to the function. If you were passing the string by reference, the marshaler copies the contents of the buffer into the original string when returning from the function. Conversely, when using StringBuilder, it passes a reference to the internal buffer of StringBuilder if passed by value. Passing a StringBuilder by reference actually passes a pointer to the StringBuilder object into memory to the function not a pointer to the buffer itself. Read more about passing a type by value or by reference in the section "Passing Mechanism" later in this chapter. Another feature of StringBuilder is its ability to specify buffer capacity. As we will see, this can be very helpful in plenty of cases. To summarize, System.String is preferable when working with immutable strings, especially for input (In) arguments. On the other hand, System.Text.StringBuilder is preferable with changeable strings especially output (Out) arguments. Noteworthy to say that StringBuilder cannot be used inside compound types. Therefore, you will need to use String instead. Another point to mention is that you can pass array of System.Char in place of a System.String or System.Text.StringBuilder. In other words, you can marshal unmanaged strings as managed arrays of System.Char (or System.Int16, do you remember?) Compound types discussed in the next chapter. HANDLING CHARACTER E NCODING Encoding of a character is very important because it determines the value that the character can hold and the size it occupies into memory. For example, if the character is ANSI-encoded it can be one of only 256 characters. Likewise, if it is 25
  • 26. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Unicode-encoded, it can hold one of 65536 characters, which is very good for most languages. If you need more information about Unicode, you can check the official site of Unicode, www.Unicode.org. In addition, Programming Windows 5th by Charles Petzold includes a must-read introduction of Unicode and character sets. For controlling character encoding when marshaling unmanaged types, you may take one of two approaches or you can combine them as needed. You can control the encoding of the overall function (i.e. at the function level,) or you can drill down and control the encoding process at a granular level by controlling every argument separately (the second approach is required in certain cases e.g. MultiByteToWideChar() function.) For changing the encoding of the overall function, DllImportAttribute offers the property CharSet that indicates the encoding (character set) for the strings and arguments of the function. This property can take one of several values:  CharSet.Auto (CLR Default): Strings encoding varies based on operating system; it is Unicode-encoded on Windows NT and ANSI-encoded on other versions of Windows.  CharSet.Ansi (C# Default): Strings are always 8-bit ANSI-encoded.  CharSet.Unicode: Strings are always 16-bit Unicode-encoded.  CharSet.None: Obsolete. Has the same behavior as CharSet.Ansi. Take into consideration that if you have not set the CharSet property, CLR automatically sets it to CharSet.Auto. However, some languages override the default behavior. For example, C# defaults to CharSet.Ansi. It is worth mentioning that plenty of functions that accept strings and buffers are just names (technically typedefs)! They are not real functions, they are entry- points (aliases) for the real functions. For example, ReadConsole() function is nothing except an entry point redirects the call to the right function, either ReadConsoleA() if ANSI is defined, or ReadConsoleW() if Unicode is defined (A stands for ANSI, and W stands for Wide which means Unicode.) Therefore, you can actually bypass this entry-point by changing the PInvoke method name to match the right function or by changing DllImportAttribute.EntryPoint to the name of the required function. In both cases, setting DllImportAttribute.CharSet along with is no use. 26
  • 27. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY If you want to control the encoding at a granular level, you can apply the MarshalAsAttribute attribute to the argument specifying the underlying unmanaged type. Usually, you will need to unify the character encoding of all your native functions and types. This is, all the functions should be either Unicode or ANSI. Under rare occasions, some functions would be different in character encoding. It is worth mentioning that, for fixed-length strings you will need to set the SizeConst property of MarshalAsAttribute to the buffer length. These techniques are not limited to arguments only! You can use them with variables of compound types too. We will look at compound types in the following chapter. TRY IT OUT! Now we will look on both ReadConsole() and FormatConsole() unmanaged functions and how to call them from your managed environment. Next is the definition of both functions and other functions required for the example: Listing 2.5 GetStdHandle(), ReadConsole(), GetLastError(), and FormatMessage() Unmanaged Signature HANDLE GetStdHandle( DWORD nStdHandle ); BOOL ReadConsole( HANDLE hConsoleInput, [out] LPVOID lpBuffer, DWORD nNumberOfCharsToRead, [out] LPDWORD lpNumberOfCharsRead, LPVOID lpReserved ); DWORD GetLastError(void); DWORD FormatMessage( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, 27
  • 28. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY DWORD dwLanguageId, [out] LPTSTR lpBuffer, DWORD nSize, va_list* Arguments ); And this is the managed version along with the driver code. Listing 2.6 Reading from the Console Screen Buffer Example // For retrieving a handle to a specific console device [DllImport("Kernel32.dll")] static extern IntPtr GetStdHandle( [param: MarshalAs(UnmanagedType.U4)] int nStdHandle); // Used with GetStdHandle() for retrieving console input buffer const int STD_INPUT_HANDLE = -10; // Specifying the DLL along with the character set [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ReadConsole( // Handle to the input device IntPtr hConsoleInput, // The buffer of which to write input to [param: MarshalAs(UnmanagedType.LPTStr), Out()] // [param: MarshalAs(UnmanagedType.AsAny)] StringBuilder lpBuffer, // Number of characters to read [param: MarshalAs(UnmanagedType.U4)] uint nNumberOfCharsToRead, // Outputs the number of characters read [param: MarshalAs(UnmanagedType.U4), Out()] out uint lpNumberOfCharsRead, // Reserved = Always set to NULL 28
  • 29. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY [param: MarshalAs(UnmanagedType.AsAny)] uint lpReserved); // For getting the code for the last error occurred [DllImport("Kernel32.dll")] [return: MarshalAs(UnmanagedType.U4)] static extern uint GetLastError(); // Retrieves error messages [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.U4)] static extern uint FormatMessage( // Options [param: MarshalAs(UnmanagedType.U4)] uint dwFlags, // Source to get the message from // [param: MarshalAs(UnmanagedType.AsAny)] [param: MarshalAs(UnmanagedType.U4)] uint lpSource, // Message code = error code [param: MarshalAs(UnmanagedType.U4)] uint dwMessageId, // Language ID (Reserved) [param: MarshalAs(UnmanagedType.U4)] uint dwLanguageId, // Outputs the error message [param: MarshalAs(UnmanagedType.LPTStr), Out()] out string lpBuffer, // Size of error message [param: MarshalAs(UnmanagedType.U4)] uint nSize, // Additional options 29
  • 30. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY [param: MarshalAs(UnmanagedType.U4)] uint Arguments); // Message Options const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x0100; const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x0200; const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x1000; const uint FORMAT_MESSAGE_FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; // Message Source public const int FORMAT_MESSAGE_FROM_HMODULE = 0x0800; static void Main() { // Handle to input buffer IntPtr handle = GetStdHandle(STD_INPUT_HANDLE); const int maxCount = 256; uint noCharacters; StringBuilder builder = new StringBuilder(maxCount); if (ReadConsole(handle, builder, (uint)maxCount, out noCharacters, 0) == false) // false = non-zero = failed { string errMsg; FormatMessage(FORMAT_MESSAGE_FLAGS, FORMAT_MESSAGE_FROM_HMODULE, GetLastError(), 30
  • 31. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY 0, // Means NULL out errMsg, 0, // Maximum length 0); // Means NULL Console.WriteLine("ERROR:n{0}", errMsg); } else // true = zero = succeeded // Writing user input withour the newline Console.WriteLine("User wroted: = " + builder.ToString().Substring(0, builder.Length - Environment.NewLine.Length)); Console.WriteLine(new string('-', 25)); builder = new StringBuilder(maxCount); // Invalid handle handle = GetStdHandle(12345); if (ReadConsole(handle, builder, (uint)maxCount, out noCharacters, 0) == false) // false = non-zero = failed { string errMsg; FormatMessage(FORMAT_MESSAGE_FLAGS, FORMAT_MESSAGE_FROM_HMODULE, GetLastError(), 0, // Means NULL out errMsg, 0, // Maximum length 0); // Means NULL 31
  • 32. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Console.WriteLine("ERROR: {0}", errMsg); } else // true = zero = succeeded // Exculding the newline characters Console.WriteLine("User wroted: = " + builder.ToString().Substring(0, builder.Length - Environment.NewLine.Length)); The last code demonstrates other useful techniques:  Until now, handles should be marshaled as System.IntPtr. The following section talks in details about handles.  Because LPVOID and LPCVOID are both defined as a pointer to a variant (i.e. any type,) you can set them to any type you want. They are very similar to System.Object in the .NET methodology or Variant for people who are familiar with the traditional Visual Basic. In our example, we have marshaled LPVOID as System.UInt32 and set it to zero. Again, you are free to play with the marshaling types. LPVOID and LPCVOID are both 32-bit integer. Why not just marshaling them as any of the 32-bit managed types and forgetting about them? In addition, you can marshal it as System.IntPtr, and pass it System.IntPtr.Zero to indicate a NULL value. Moreover, you can marshal it as System.Object, and set it to any value, even null to indicate the NULL value. Variant has been discussed in details previously in the section “Marshaling Blittable Data Types.”  va_list* is a pointer to an array of specific arguments. You can marshal it as an array, or System.IntPtr. System.IntPtr is preferred if you intend to pass it a NULL value.  If the function requires a parameter passed by value or by reference you can add the required modifiers like ref and out to the parameter, and decorate the parameter with either InAttribute or OutAttribute, or both. The section “Passing an Argument by Value or by Reference” later in this chapter discusses by-value and by-reference parameters.  While DWORD is defined as unsigned 32-bit integer and it should be marshaled as System.UInt32, we find that the GetStdHandle() can take one of three values: -10 for the input device, -11 for the output device, and -12 for the error device (usually is the output device.) Although System.UInt32 does not support negative values, Windows handles this for you. It converts the signed value to its equivalent unsigned value. Therefore, you should not worry about the value passed. However, keep in mind that the unsigned values are too different (from the perspective of most developers.) For example, the unsigned value of -11 is 0xFFFFFFF5! 32
  • 33. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Does this seem strange for you? Start by consulting the documentation about binary notation. MARSHALING HANDLES GENERIC HANDLES What is a handle? A handle is a pointer to some resource loaded in memory, such as handles to the console standard input, output, and error devices, the handle for the window, and the handle to a device context (DC.) There are plenty of type handles in unmanaged code, here is some of them:  HANDLE: This is the most widely used handle type in the unmanaged environment. It represents a generic handle.  HWND: Most widely used with Windows application. It is a handle to a window or a control.  HDC, HGDIOBJ, HBITMAP, HICON, HBRUSH, HPEN, and HFONT: If you have worked with GDI, you will be familiar with these handles. HDC is a handle to a device context (DC) object that will be used for drawing. HGDIOBJ is a handle for any GDI object. HBITMAP is a handle to a bitmap, while HICON is a handle to an icon. HBRUSH is a handle to a brush, HPEN is a handle to pen, and HFONT is a handle to a font.  HFILE: A handle to a file opened by any of Windows File IO functions like OpenFile() function.  HMENU: A handle to a menu or menu item. Again, from all you have seen, you may have noticed that most types identified by a prefix or a suffix. For example, handles prefixed with the letter H, while some pointers have the suffix _PTR, or the prefix P or LP. While strings with letter W are Unicode-encoded, and strings with letter T are OS-based. Handles can be marshaled as the managed type System.IntPtr that represents a pointer to an object into memory. It is worth mentioning that because System.IntPtr represents a pointer to an object no matter what the object is, you can use System.IntPtr for marshaling any type not handles only, but that is not recommended because it is more difficult to work with, and it is not very flexible, 33
  • 34. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY but it provides more control over the object in memory. For more information about memory management, see chapter 6: “Memory Management.” In addition, starting from version 2.0, new managed types for working with unmanaged handles added to the .NET Framework. A new namespace Microsoft.Win32.SafeHandles that contains most of the new types has been added too. Other types exist in System.Runtime.InteropServices. These types called managed handles. Managed handles allow you to pass, to unmanaged code, a handle to an unmanaged resource (such as DC) wrapped by managed class. There are two kinds of managed handles safe and critical handles. SAFE HA NDLES Safe handles represented by the abstract System.Runtime.InteropServices.SafeHandle. Safe handles provide protection from recycling security attacks by perform reference counting (and that makes safe handles slower.) In addition, it provides critical finalization for handle resources. As a refresher, finalization means releasing the object and its resources from the memory, and critical finalization ensures object finalization under any circumstances. Figure 2.2 shows the definition of SafeHandle and its descendants. 34
  • 35. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Figure 2.2 SafeFileHandle and Descendants Class Definitions As the diagram illustrates, SafeHandle is the base class that represents any safe handle. It inherits from System.Runtime.ConstrainedExecution.CriticalFinalizerObject that ensures the finalization process. The following are the most common members of SafeHandle:  IsClosed: Returns a value indicates whether the handle is closed.  IsInvalid: Abstract. If overridden, returns a value indicates whether the handle is invalid or not.  Close() and Dispose(): Both close the handle and dispose its resources. Internally, they rely on the abstract method ReleaseHandle() for releasing the handle. Therefore, 35
  • 36. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY classes inherit from SafeHandle must implement this member. Be aware that Dispose() is inherited from System.IDispose interface that is implemented by SafeHandle, and Close() does not do anything except calling the Dispose() method. Therefore, you strictly should dispose (close) the handle as soon as you finish your work with it.  ReleaseHandle(): Protected Abstract. Use to provide handle clean-up code. This function should returns true if successfully released, or false otherwise. In the case of false, it generates a ReleaseHandleFailed Managed Debugging Assistant (MDA) exception that will not interrupt your code but provides you with a bad sign about it. Keep in mind that ReleaseHandle() called internally by Dispose().  SetHandle(): Protected. Sets the handle to the specified pre-existing handle.  SetHandleAsInvalid(): Sets the handle as invalid so it is no longer used.  DangerousGetHandle(): Returns System.IntPtr that represents the handle. Beware that if you have called SetHandleAsInvalid() before calling DangerousGetHandle(), it returns the original handle not the invalid one.  DangerousRelease(): Manually releasing the handle in unsafe manner. It is recommended using Close() or Dispose() methods instead.  DangerousAddRef(): Increments the reference count of the handle. It is not recommended using neither DangerousRelease() nor DangerousAddRef(), use safe methods instead. However, when working with COM, you will find yourself using these functions Do not use unsafe methods unless you really need to use it because they pass the protection level offered by safe handles. Because SafeHandle is abstract, you must either implement it or use one of its implementation classes. Only two classes from the new namespace Microsoft.Win32.SafeHandles implement SafeHandle, both are abstract too:  SafeHandleMinusOneIsInvalid: Represents a safe handle of which a value of -1 indicates that the handle is invalid. Therefore, IsInvalid returns true only if the handle equals to -1.  SafeHandleZeroOrMinusOneIsInvalid: Represents a safe handle of which a value of 0 or -1 indicates that the handle is invalid. So, IsInvalid returns true only if the handle equals to 0 or -1. 36
  • 37. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Notice that, choosing between the two implementations is up to the type of the underlying handle. If it considered invalid if set to -1, use SafeHandleMinusOneIsInvalid. If it considered invalid if set to 0 or -1, use SafeHandleZeroOrMinusOneIsInvalid. Using the right class for the handle ensures that methods like IsInvalid() returns correct results. It also ensures that CLR will mark the handle as garbage only if it is invalid. If you need to provide a safe handle for your object, you will need to inherit from SafeHandleMinusOneIsInvalid, SafeHandleZeroOrMinusOneIsInvalid, or even from SafeHandle. Be aware that, you will always need to override the ReleaseHandle() method because neither SafeHandleMinusOneIsInvalid nor SafeHandleZeroOrMinusOneIsInvalid does override it. As the diagram illustrates, two concrete classes inherit from SafeHandleZeroOrMinusOneIsInvalid:  SafeFileHandle: A wrapper class for an IO device handle (e.g. HFILE.) This class internally overrides the ReleaseHandle() and calls the unmanaged CloseHandle() function to close the handle. Use when working with HFILE handles in Windows File IO functions like OpenFile() and CreateFile(). Internally, System.FileStream uses a HFILE as SafeFileHandle, and it exposes a constructor that accepts SafeFileHandle.  SafeWaitHandle: If you are working with unmanaged thread synchronization objects like a Mutex or an Event, then this should be the desired marshaling type for synchronization objects' handles. Now, we are going to create a file using CreateFile() function with SafeFileHandle for the marshaling process. The definition of CreateFile() is as following: Listing 2.7 CreateFile() Unmanaged Signature HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); 37
  • 38. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY In addition, here is the .NET code: Listing 2.8 Create File Example [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern SafeFileHandle CreateFile( string lpFileName, uint dwDesiredAccess, uint dwShareMode, // Because we are going to set the argument // to NULL we marshaled it as IntPtr // so we can set it to IntPtr.Zero // to represent a NULL value IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, // A handle for a template file // we are going to set it to NULL // so e can marshal it as System.IntPtr // and pass IntPtr.Zero for the NULL value // But, this is another way SafeFileHandle hTemplateFile); // Accessing the file for writing const uint GENERIC_WRITE = 0x40000000; // Do now allow file sharing const uint FILE_SHARE_NONE = 0x0; // Create the file and overwrites it if exists const uint CREATE_ALWAYS = 0x2; // Normal file, no attribute set const uint FILE_ATTRIBUTE_NORMAL = 0x80; static void Main() { SafeFileHandle handle = CreateFile("C:MyFile.txt", 38
  • 39. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY GENERIC_WRITE, FILE_SHARE_NONE, IntPtr.Zero, // NULL CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, new SafeFileHandle(IntPtr.Zero, true)); // Because SafeFileHandle inherits // SafeHandleZeroOrMinusOneIsInvalid // IsInvalid returns true only if // the handle equals to 0 or -1 if (handle.IsInvalid) // 0 or -1 { Console.WriteLine("ERROR: {0}", Marshal.GetLastWin32Error()); return; // Marshal.GetLastWin32Error() returns the last error only // if DllImportAttribute.SetLastError is set to true } FileStream stream = new FileStream(handle, FileAccess.Write); StreamWriter writer = new StreamWriter(stream); writer.WriteLine("Hello, World!"); writer.Close(); /* * Order of methods called by * StreamWriter by this example: * * StreamWriter.Close() * - StreamWriter.BaseStream.Close() * - - FileStream.SafeFileHandle.Close() * - - - SafeHandleZeroOrMinusOneIsInvalid * .Close() 39
  • 40. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY * - - - - SafeHandle.Close() * - - - - - SafeHandle.ReleaseHandle() */ } Although, you can use IntPtr instead of SafeFileHandle, the FileStream constructor that accepts the IntPtr is considered obsolete (.NET 2.0 and higher) and you should use the constructor that accepts the SafeFileHandle. The next example demonstrates how to create your custom safe handle. This custom safe handle represents a handle invalid only if equals to zero. Although, you can extend the functionality of either SafeHandleMinusOneIsInvalid or SafeHandleZeroOrMinusOneIsInvalid, we have inherited SafeHandle directly. Code is very simple: Listing 2.9 Custom Safe Handle Example public sealed class SafeHandleZeroIsInvalid : SafeHandle { [DllImport("Kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CloseHandle(IntPtr hObject); // If ownsHandle equals true handle will // be automatically released during the // finalization process, otherwise, you // will have the responsibility to // release it outside the class. // Automatic releasing means calling // the ReleaseHandle() method. public SafeHandleZeroIsInvalid (IntPtr preexistingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) { this.SetHandle(preexistingHandle); } public override bool IsInvalid { 40
  • 41. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY get { // this.handle.ToInt32() == 0 // this.handle == new IntPtr(0) return this.handle == IntPtr.Zero; } } protected override bool ReleaseHandle() { return CloseHandle(this.handle); } } Until now, I do not have an answer for why a handle could be invalid only if it is set to zero! Maybe you will need this for your custom handles. However, this is just an illustration. CRITICAL HANDLES Critical handles are the same as safe handles, except that they do not perform reference counting, so they do not provide protection from recycling security attacks. Use critical handles instead of safe handles to address performance considerations, but you will be required to provide necessary synchronization for reference counting yourself. Critical handles represented by the abstract System.Runtime.InteropServices.CriticalHandle. Figure 2.3 shows the definition of CriticalHandle and its descendants. 41
  • 42. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Figure 2.3 CriticalHandle and descendants Class Definitions As the diagram illustrates, CriticalHandle is the base class that represents any critical handle. It inherits from System.Runtime.ConstrainedExecution.CriticalFinalizerObject that ensures the finalization process. The members of CriticalHandle are the same as SafeHandle, except that it does not include the Dangerous-prefixed methods because critical handles themselves are dangerous because they do not provide the necessary protection. For more information about CriticalHandle members, refer to members of SafeHandle discussed previously. Because CriticalHandle is abstract, you must either implement it or use one of its implementation classes. Only two classes from the new namespace Microsoft.Win32.SafeHandles implement CriticalHandle, both are abstract too:  CriticalHandleMinusOneIsInvalid: Represents a critical handle of which a value of -1 indicates that the handle is invalid. Therefore, IsInvalid returns true only if the handle equals to -1. 42
  • 43. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY  CriticalHandleZeroOrMinusOneIsInvalid: Represents a critical handle of which a value of 0 or -1 indicates that the handle is invalid. So, IsInvalid returns true only if the handle equals to 0 or -1. Examples are the same as SafeHandle, only to change the type name. PASSING MECHANISM When passing an argument to a function, the function may require either passing the argument by value or by reference. If the function intends to change argument value, it requires it to be passed by reference, otherwise, by value. This is what called passing mechanism. Value arguments (i.e. input/In arguments,) when passed to a function, a copy of the argument is sent to the function. Therefore, any changes to the argument do not affect the original copy. On the other hand, reference arguments, when passed to a function, the argument itself is passed to the function. Therefore, the caller sees any changes happen inside the function. Arguments passed by reference can be either In/Out (Input/Output) or only Out (Output.) In/Out arguments are used for passing input to the function and returning output. On the other hand, Out arguments used for returning output only. Therefore, In/Out arguments must be initialized before they are passed to the function. Conversely, Out arguments do not require pre-initialization. When passing an argument by value, no changes to the PInvoke method are required. Conversely, passing an argument by reference requires two additional changes. The first is adding the ref modifier to the argument if it is In/Out argument, or the out modifier if it is Out argument. The second is decorating your argument with both InAttribute and OutAttribute attributes if it is In/Out argument or only OutAttribute if it is Out argument. To be honest, applying those attributes is not required, the modifiers are adequate in most cases. However, applying them gives the CLR a notation about the passing mechanism. As you have seen, when marshaling a string, you can marshal it as a System.String or as a System.Text.StringBuilder. By default, StringBuilder is passed by reference (you do not need to apply any changes.) System.String on the other hand is passed by value. It is worth mentioning that Windows API does not support reference arguments. Instead, if a function requires an argument to be passed by reference, it declares it as a pointer so that caller can see the applied changes. Other code such as COM libraries can require either a pointer or a reference argument. In either cases, you can safely apply the changes required. You can also marshal a pointer argument as System.IntPtr or as the unsafe void* for example. 43
  • 44. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Many of the previous examples demonstrated only functions those require arguments to be passed by value. Some functions require one or more arguments to be passed by reference. A good example of a function requires In/Out argument is GetVersionEx() which returns version information of the current system. It requires a single reference (In/Out) argument. The argument is of the structure OSVERSIONINFOEX. For our discussion, we will leave this function to the next chapter in the discussion of compound types. A great deal of functions require Out arguments specially for returning results or status information. Good examples are ReadConsole() and WriteConsole() that require by-reference Out arguments for returning the characters read/written. The following is the unmanaged signature for the WriteConsole() function. Listing 2.10 WriteConsole() Unmanaged Signature BOOL WriteConsole( HANDLE hConsoleOutput, VOID lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved ); And this is the managed version along with the driver code: Listing 2.11 Writing to Console Screen Example [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool WriteConsole( IntPtr hConsoleOutput, String lpBuffer, [param: MarshalAs(UnmanagedType.U4)] UInt32 nNumberOfCharsToWrite, [param: MarshalAs(UnmanagedType.U4)] out UInt32 lpNumberOfCharsWritten, [param: MarshalAs(UnmanagedType.AsAny)] object lpReserved); [DllImport("Kernel32.dll")] static extern IntPtr GetStdHandle( [param: MarshalAs(UnmanagedType.U4)] 44
  • 45. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Int32 nStdHandle); const int STD_OUTPUT_HANDLE = -11; static void Main() { IntPtr handle = GetStdHandle(STD_OUTPUT_HANDLE); String textToWrite = "Hello, World!" + Environment.NewLine; uint noCharactersWritten; WriteConsole(handle, textToWrite, (uint)textToWrite.Length, out noCharactersWritten, null); Console.WriteLine("No. Characters written = {0}", noCharactersWritten); } Finally yet importantly, chapter 6 provides you with more granular and down- level details about the memory management and the passing mechanism. ADDITIONAL TECHNIQUES Here we will talk about techniques that should be taken into consideration when working with unmanaged code, they are encapsulation, creating wrappers, working with nullable arguments, and working out CLS problem. ENCAPSULATION If the function requires an argument that can be set to a value or more, you can define these values (constants or typedefs) in an enumeration so you can easily access every set of values separately; that technique called encapsulation 45
  • 46. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY (grouping.) The following example shows the MessageBoxEx() example, the most suitable function for the example: Listing 2.12 Message Box Example [DllImport("User32.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.I4)] static extern UInt32 MessageBoxEx (IntPtr hWnd, [param: MarshalAs(UnmanagedType.LPTStr)] String lpText, [param: MarshalAs(UnmanagedType.LPTStr)] String lpCaption, [param: MarshalAs(UnmanagedType.U4)] UInt32 uType, [param: MarshalAs(UnmanagedType.U2)] UInt16 wLanguageId); public enum MB_BUTTON : uint { MB_OK = 0x0, MB_OKCANCEL = 0x1, MB_ABORTRETRYIGNORE = 0x2, MB_YESNOCANCEL = 0x3, MB_YESNO = 0x4, MB_RETRYCANCEL = 0x5, MB_HELP = 0x4000, } public enum MB_ICON : uint { MB_ICONHAND = 0x10, MB_ICONQUESTION = 0x20, MB_ICONEXCLAMATION = 0x30, MB_ICONASTERISK = 0x40, MB_ICONERROR = MB_ICONHAND, MB_ICONSTOP = MB_ICONHAND, 46
  • 47. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY MB_ICONWARNING = MB_ICONEXCLAMATION, MB_ICONINFORMATION = MB_ICONASTERISK, } public enum MB_DEF_BUTTON : uint { MB_DEFBUTTON1 = 0x0, MB_DEFBUTTON2 = 0x100, MB_DEFBUTTON3 = 0x200, MB_DEFBUTTON4 = 0x300, } public enum MB_MODAL : uint { MB_APPLMODAL = 0x0, MB_SYSTEMMODAL = 0x1000, MB_TASKMODAL = 0x2000, } public enum MB_SPECIAL : uint { MB_SETFOREGROUND = 0x10000, MB_DEFAULT_DESKTOP_ONLY = 0x20000, MB_SERVICE_NOTIFICATION_NT3X = 0x40000, MB_TOPMOST = 0x40000, MB_RIGHT = 0x80000, MB_RTLREADING = 0x100000, MB_SERVICE_NOTIFICATION = 0x200000, } public enum MB_RETURN : uint { IDOK = 1, IDCANCEL = 2, IDABORT = 3, IDRETRY = 4, IDIGNORE = 5, 47
  • 48. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY IDYES = 6, IDNO = 7, IDCLOSE = 8, IDHELP = 9, IDTRYAGAIN = 10, IDCONTINUE = 11, } static void Main() { UInt32 result = MessageBoxEx(IntPtr.Zero, // NULL "Do you want to save changes before closing?", "MyApplication", (UInt32)MB_BUTTON.MB_YESNOCANCEL | (UInt32)MB_ICON.MB_ICONQUESTION | (UInt32)MB_DEF_BUTTON.MB_DEFBUTTON3 | (UInt32)MB_SPECIAL.MB_TOPMOST, 0);// Reserved if (result == 0) // error occurred Console.WriteLine("ERROR"); else { MB_RETURN ret = (MB_RETURN)result; if (ret == MB_RETURN.IDYES) Console.WriteLine("User clicked Yes!"); else if (ret == MB_RETURN.IDNO) Console.WriteLine("User clicked No!"); else if (ret == MB_RETURN.IDCANCEL) Console.WriteLine("User clicked Cancel!"); } } 48
  • 49. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY You could also change the names of the constants to friendly names. Figure 2.4 shows the message box resulted from running of the last code. Figure 2.4 Message Box Example Result In addition, you can marshal an argument as an enumeration which of the argument type of course. The following example demonstrates this: Listing 2.13 Console Standard Devices Example [DllImport("Kernel32.dll")] static extern IntPtr GetStdHandle( [param: MarshalAs(UnmanagedType.U4)] CONSOLE_STD_HANDLE nStdHandle); public enum CONSOLE_STD_HANDLE { STD_INPUT_HANDLE = -10, STD_OUTPUT_HANDLE = -11, STD_ERROR_HANDLE = -12 } static void Main() { IntPtr handle; handle = GetStdHandle(CONSOLE_STD_HANDLE.STD_INPUT_HANDLE); if (handle == IntPtr.Zero) Console.WriteLine("Failed!"); else Console.WriteLine("Succeeded!"); } 49
  • 50. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY CREATING WRAPPERS Exposing PInvoke methods to the outside the assembly is not a good practice. It is always recommended that you group your PInvoke methods into an internal class, and that class should be named as NativeMethods, SafeNativeMethods or UnsafeNativeMethods. For more information about this, check Code Analyzing Rules in MSDN documentation. Read “Move PInvokes to Native Methods Class” article. The following code segment illustrates the wrapper method for our MessageBoxEx() function: Listing 2.14 Message Box Example Revised public static MB_RETURN MessageBox (IntPtr handle, string text, string title, MB_BUTTON buttons, MB_ICON icon, MB_DEF_BUTTON defaultButton, MB_MODAL modality, MB_SPECIAL options) { UInt32 result = MessageBoxEx(handle, "Do you want to save changes before closing?", "MyApplication", (UInt32)buttons | (UInt32)icon | (UInt32)defaultButton | (UInt32)modality | (UInt32)options, 0); if (result == 0) // Not recommended throwing System.Exception // throw a derived exception instead throw new Exception("FAILED"); return (MB_RETURN)result; } In addition, it is recommended changing the type of enumerations to any CLS- compliant type like System.Int32. Check the last technique in this section. 50
  • 51. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY WORKING WITH NULLA BLE ARGUMENT S Some function arguments are nullable. Means that they can take a NULL (null in C#) value. To pass a NULL value to an argument, you can marshal this argument as System.IntPtr, so you can set it to System.IntPtr.Zero to represent a NULL value. Another trick here is creating an overload for the function, in which the first is marshaled as the argument type, and the other is marshaled as System.IntPtr. Thus, if you pass a System.IntPtr.Zero, CLR directs the call to the function with System.IntPtr. Conversely, passing a value to the argument, directs the call to the function with the correct type. The following code segment demonstrates this technique: Code abbreviated for clarity. Listing 2.15 ScrollConsoleScreenBuffer() Managed Signature [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ScrollConsoleScreenBuffer( IntPtr hConsoleOutput, SMALL_RECT lpScrollRectangle, SMALL_RECT lpClipRectangle, COORD dwDestinationOrigin, CHAR_INFO lpFill); [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ScrollConsoleScreenBuffer( IntPtr hConsoleOutput, SMALL_RECT lpScrollRectangle, IntPtr lpClipRectangle, COORD dwDestinationOrigin, CHAR_INFO lpFill); ... WORKING O UT THE CLS PROBLEM You should know that some types are non-CLS-compliant and you should avoid exposing them outside the assembly. For example, the famous System.UInt32 is non-CLS-compliant, and you strictly should not expose it. 51
  • 52. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Being non-CLS-compliant means that the type violates with CLS (Common Language Specifications) specifications. Following CLS specifications helps the interoperation of .NET languages. It helps avoiding some actions like declaring specific types or following uncommon naming conventions. Why to avoid such these acts? This helps the big goal of .NET Framework, the interoperation of .NET languages. Some languages for example does not support variable names beginning with an underscore (_) others do. Therefore, following the CLS specifications allows your assembly to be callable from any other assembly build with any language easily. To force the check of CLS specification, you can decorate the assembly with System.CLSCompliantAttribute attribute -specifying true,- and that would result in compiler warnings whenever you try to expose non-CLS-compliant type out. To work out this CLS dilemma, for functions require UInt32 as an argument, you can create a wrapper that behaves as an entry-point to the private non-CLS- compliant method. That wrapper method accepts, for instance, System.Int32 and converts it internally to System.UInt32. For structures, you can declare the structure as internal and continue using it the normal way. Again, you could replace all non-CLS-compliant types like System.UInt32 with CLS-compliant equivalents like System.Int32 and take advantage of easily distributing your types and assembly. However, that would not be easy in all cases. It is very helpful consulting the documentation about System.CLSCompliantAttribute attribute. REAL-WORLD EXAMPLES In this chapter, we have covered many aspects of marshaling in many examples. However, most of all were just for illustration. The following are some real-world examples that solve problems that you might face while developing your application. Those problems can be solved only via interoperability with unmanaged code. PROGRAMMATICALLY SWAPPING MO USE BUTTONS The following code swaps mouse buttons programmatically. It makes the left button acts like the right button (e.g. opens the context menu) and vice versa. 52
  • 53. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Listing 2.16 Swapping Mouse Buttons Sample [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SwapMouseButton ([param: MarshalAs(UnmanagedType.Bool)] bool fSwap); public void MakeRightButtonPrimary() { SwapMouseButton(true); } public void MakeLeftButtonPrimary() { SwapMouseButton(false); } PROGRAMMATICALLY TUR NING ON THE SCREEN SAVER The following code shows how to turn on the screen saver programmatically. Listing 2.19 Dragging a Form without a Title Bar Sample [DllImport("User32.dll")] public static extern int SendMessage (IntPtr hWnd, uint Msg, uint wParam, uint lParam); public const uint WM_SYSCOMMAND = 0x112; public const uint SC_SCREENSAVE = 0xF140; public enum SpecialHandles { HWND_DESKTOP = 0x0, HWND_BROADCAST = 0xFFFF 53
  • 54. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY } public static void TurnOnScreenSaver() { SendMessage( new IntPtr((int)SpecialHandles.HWND_BROADCAST), WM_SYSCOMMAND, SC_SCREENSAVE, 0); } DRAGGING A FORM WITHOUT A TITLE BAR The following code allows the form to be dragged from its body. This code is a good example for the wrapper creating technique discussed earlier. Listing 2.18 Dragging a Form without a Title Bar Sample SafeNativeMethods.cs internal static class SafeNativeMethods { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.I4)] public static extern int SendMessage( IntPtr hWnd, [param: MarshalAs(UnmanagedType.U4)] uint Msg, [param: MarshalAs(UnmanagedType.U4)] uint wParam, [param: MarshalAs(UnmanagedType.I4)] int lParam); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ReleaseCapture(); 54
  • 55. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY public const uint WM_NCLBUTTONDOWN = 0xA1; // 161 public const uint HTCAPTION = 2; } HelperMethods.cs internal static class HelperMethods { public static void MoveObject(IntPtr hWnd) { SafeNativeMethods.ReleaseCapture(); SafeNativeMethods.SendMessage (hWnd, SafeNativeMethods.WM_NCLBUTTONDOWN, SafeNativeMethods.HTCAPTION, 0); } } MainForm.cs // In the form, write the following code // in the handler of the MouseDown event private void MainForm_MouseDown(object sender, MouseEventArgs e) { HelperMethods.MoveObject(this.Handle); } 55
  • 56. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY SUMMARY The last word to say is that MarshalAsAttribute is not required all the time. Sometimes it is optional, and other times it is required. For example, if you marshal blittable data types like DWORD, you can safely ignore MarshalAsAttribute. Conversely, if you are marshaling non-blittable data types like booleans and strings, you will need to use the MarshalAsAttribute to ensure correct marshaling process. However, it is always better giving the CLR and other developers a notation about the underlying data type by apply the MarshalAsAttribute attribute to blittable data types too. Finally yet importantly, this chapter was the key for the gate to the interoperation with unmanaged environments. It discussed the most important part of the marshaling process, marshaling the simple types, which you will always need to keep it into your mind. Next, you will learn how to work with compound types and marshal them in your managed environment. 56
  • 57. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY This page intentionally left blank. 57
  • 58. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY CHAPTER 3 M A R S H A L I N G C O M P O U N D T Y P ES CHAPTER CONTENTS Contents of this chapter:  Chapter Contents  Overview  Introduction  Marshaling Unmanaged Structures o How to Marshal a Structure o Handling Memory Layout Problem o Try It Out!  Marshaling Unions o A Short Speech About Unions o How to Marshal a Union o Unions with Arrays o Try It Out!  Value-Types and Reference-Types  Passing Mechanism  Real-World Examples o The DEVMODE Structure o Working with Display Settings  Summary 58
  • 59. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY OVERVIEW This chapter demonstrates how to marshal compound types. Compound types are those build of other types, for example structures and classes. Like the previous chapter. This chapter breaks unmanaged compound types into two categories, structures and unions. We first discuss structures and then we will dive into unions and how to marshal them. You might ask, why you have divided compound types into just two categories, structures and unions, I can create classes too? The answer is easy. For its simplicity, this book will focus primarily on Windows API. Therefore, you will find much of our talking about Win32 functions and structures. However, the same rules apply to classes and other unmanaged types. INTRODUCTION A compound type encapsulates related data together; it provides an organized and arranged container for transmitting a group of variables between the client application and the unmanaged server. It consists (usually) of variables of simple types and (optionally) other compound types. In addition, it could define other compound types inside. Compound types come in two kinds:  Unmanaged Structures  Unmanaged Unions An example of a structure is OSVERSIONINFOEX structure that encapsulates operating system version information together. For those who are somewhat familiar with DirectX, they may find that DirectX API relies heavily on structures. As you know, because there is no compatibility between .NET and unmanaged code, data must undergo some conversion routines for transmitting from the managed code to the unmanaged server and vice versa, and compound types are no exception. In the next section, we will focus of the first kind, structures. 59
  • 60. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY MARSHALING UNMANAGED STRUCTURES HOW TO MAR SHAL A STR UCTURE Unmanaged structures can be marshaled as managed structures or even classes. Choosing between a managed structure and a class is up to you, there are no rules to follow. However, when marshaling as managed classes, there are some limitations with the passing mechanism as we will see later in this chapter. When marshaling structures in the managed environment, you must take into consideration that while you access a variable into your by its name, Windows accesses it via its address (i.e. position) inside the memory, it does not care about field name, but it cares about its location and size. Therefore, the memory layout and size of the type are very crucial. You can marshal an unmanaged structure in few steps: 1. Create the marshaling type either a managed structure or a class. 2. Add the type fields (variables) only. Again, layout and size of the type are very crucial. Therefore, fields must be ordered as they are defined, so that the Windows can access them correctly. 3. Decorate your type with StructLayoutAttribute attribute specifying the memory layout kind. HANDLING MEMORY LAYO UT PROBLEM When marshaling an unmanaged structure, you must take care of how that type is laid-out into memory. Actually, application memory is divided into blocks (in a 4-bytes base,) and every block has its own address. When you declare a variable or a type in your program it is stored inside the memory and got its memory address. Consequently, all data members inside a structure have their own addresses that are relative to the address of the beginning of the structure. Consider the following structures: Listing 3.1 SMALL_RECT and COORD Unmanaged Signature typedef struct SMALL_RECT { SHORT Left; SHORT Top; SHORT Right; SHORT Bottom; }; 60
  • 61. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY typedef struct COORD { SHORT X; SHORT Y; }; When we declare those structures in our code they are laid-out into memory and got addresses like that: Figure 3.1 How Memory is Laid-Out Thus, you should keep in mind that the size and location of each of type members is very crucial and you strictly should take care of how this type is laid-out into the memory. For now, you do not have to think about the last illustration. We will cover memory management in details in chapter 6. For handling the memory layout problem, you must apply the StructLayoutAttribute attribute to your marshaling type specifying the layout kind using the LayoutKind property. 61
  • 62. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY This property can take one of three values:  LayoutKind.Auto (Default): Lets the CLR chooses how the type is laid-out into memory. Setting this value prevents interoperation with this type, that means that you will not be able to marshal the unmanaged structure with this type, and if you tried, an exception will be thrown.  LayoutKind.Sequential: Variables of the type are laid-out sequentially. When setting this value ensure that all variables are on the right order as they are defined in the unmanaged structure.  LayoutKind.Explicit: Lets you control precisely each variable’s location inside the type. When setting this value, you must apply the FieldOffsetAttribute attribute to every variable in your type specifying the relative position in bytes of the variable to the start of the type. Note that when setting this value, order of variables becomes unimportant. For the sake of simplicity, you should lay-out all of your types sequentially. However, when working with unions, you are required to explicitly control every variable’s location. Unions are covered in the next section. We have said that you should add only the type members into the marshaling type, however, this is not always true. In structures where there is a member that you can set to determine the structure size (like the OPENFILENAME structure,) you can add your own members to the end of the structure. However, you should set the size member to the size of the entire structure minus the new members that you have added. This technique is discussed in details in chapter 6. TRY IT OUT! The following example demonstrates how to marshal the famous structures SMALL_RECT and COORD. Both used earlier with the ScrollConsoleScreenBuffer() function in the last chapter. You can check code listing 3.1 earlier in this chapter for the definition of the structures. Next is the managed signature for both the structures. Note that you can marshal them as managed classes too. Listing 3.2 SMALL_RECT and COORD Managed Signature // Laying-out the structure sequentially [StructLayout(LayoutKind.Sequential)] //public class SMALL_RECT public struct SMALL_RECT 62
  • 63. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY { // Because we are laying the structure sequentially, // we preserve field order as they are defined. public UInt16 Left; public UInt16 Top; public UInt16 Right; public UInt16 Bottom; } // The same as SMALL_RECT applies to COORD [StructLayout(LayoutKind.Sequential)] //public struct COORD public struct COORD { public UInt16 X; public UInt16 Y; } MARSHALING UNIONS A SHORT SPEECH ABO UT UNIONS A union is a memory location that is shared by two or more different types of variables. A union provides a way for interpreting the same bit pattern in two or more different ways (or forms.) In fact, unions share structures lots of characteristics, like the way they defined and marshaled. It might be helpful to know that, like structures, unions can be defined inside a structure or even as a single entity. In addition, unions can define compound types inside, like structures too. To understand unions, we will take a simple example. Consider the following union: 63
  • 64. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY Listing 3.3 SOME_CHARACTER Unmanaged Signature typedef union SOME_CHARACTER { int i; char c; }; This was a simple union defines a character. It declared two members, i and c, it defined them in the same memory location. Thus, it provides two ways for accessing the character, by its code (int) and by its value (char). For this to work it allocates enough memory storage for holding the largest member of the union and that member is called container. Other members will overlap with the container. In our case, the container is i because it is 4 bytes (on Win32, 16 on Win16), while c is only 1 byte. Figure 3.2 shows how the memory is allocated for the union. Figure 3.2 SOME_CHARACTER Union Because the two members are sharing the same memory location, when you change one member the other is changed too. Consider the following C example: Listing 3.4 Unions Example 1 int main() { union CHARACTER ch; ch.i = 65; // 65 for A printf("c = %c", ch.c); // prints 'A' printf("n"); ch.c += 32; // 97 for a printf("i = %d", ch.i); // prints '97' printf("n"); return 0; } 64
  • 65. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY When you change any of the members of the union, other members change too because they are all share the same memory address . Now consider the same example but with values that won’t fit into the char member: Listing 3.5 Unions Example 2 int main() { union CHARACTER ch; ch.i = 330; printf("c = %c", ch.c); // prints 'J' printf("n"); // Ops! ch.c += 32; printf("i = %d", ch.i); // prints '362' printf("n"); return 0; } What happened? Because char is 1 bye wide, it interprets only the first 8 bits of the union that are equal to 32. The same rule applies if you add another member to the union. See the following example. Notice that order of member declarations doesn’t matter. Listing 3.6 Unions Example 3 int main() { union { int i; char c; short n; } ch; ch.i = 2774186; printf("i = %d", ch.i); 65
  • 66. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY printf("n"); printf("c = %i", (unsigned char)ch.c); printf("n"); printf("n = %d", ch.n); printf("n"); return 0; } Now, member i, the container, interprets the 32 bits. Member c, interprets the first 8 bits (notice that we converted it to unsigned char to not to show the negative value.) Member n, interprets the first high word (16 bits.) You might ask: Why I need unions at all? I could easily use the cast operator to convert between data types ! The answer is very easy. Unions come very efficient when casting between types require much overhead. Consider the following example: You are about to write an integer to a file. Unfortunately, there are no functions in the C standard library that allow you to write an int to a file, and using fwrite() function requires excessive overhead. The perfect solution is to define a union that contains an integer and a character array to allow it to be interpreted as an integer and as a character array when you need to pass it to fwrite() for example. See the following code snippet: Listing 3.7 Unions Example 4 typedef union myval{ int i; char str[4]; }; In addition, unions offer you more performance than casts. Moreover, your code will be more readable and efficient when you use unions. More on how the unions are laid-out into memory in chapter 6. HOW TO MAR SHAL A UNION You can marshal a union the same way as you marshal structures, except that because of the way that unions laid-out into memory, you will need to explicitly set variable positions inside the type. Follow these steps to marshal a union: 66
  • 67. MARSHALING WITH C# POCKET REFERENCE © 2010 MOHAMMAD ELSHEIMY 1. Create your marshaling type, no matter whether your marshaling type is a managed structure or class. Again, classes require special handling when passed as function arguments. Passing mechanism is covered soon. 2. Decorate the type with the StructLayoutAttribute attribute specifying LayoutKind.Explicit for the explicit layout kind. 3. Add the type fields. Do not add fields other than those defined in the unmanaged signature. Because we are controlling the type layout explicitly, order of fields is not important. 4. Decorate every field with the FieldOffsetAttribute attribute specifying the absolute position in bytes of the member from the start of the type. The following example demonstrates how to marshal our SOME_CHARACTER union. Listing 3.8 SOME_CHARACTER Managed Signature // Unions require explicit memory layout [StructLayout(LayoutKind.Explicit)] //public class SOME_CHARACTER public struct SOME_CHARACTER { // Both members located on the same // position in the beginning of the union // This is the continer it is 4 bytes [FieldOffset(0)] [MarshalAs(UnmanagedType.U4)] public int i; // This is only 1 byte. Therefore, it is contained [FieldOffset(0)] public char c; } public static void Main() { SOME_CHARACTER character = new SOME_CHARACTER(); // The code for letter 'A' 67