What is Marshalling?

Marshaling is the act of taking data from the environment you are in and exporting it to another environment. In the context of .NET, marhsaling refers to moving data outside of the app-domain you are in, somewhere else.

When you work with unmanaged code, you are marshaling data from your managed app-domain to the unmanaged realm. Also, when transferring data between app-domains (to another application, on the same or another machine), you are also marshaling data from your app-domain, to another app-domain.

Unmanaged code is simply all code pre .NET. It is all code NOT compiled to operate under .NET’s runtime, the CLR. Unmanaged code is code compiled and linked natively and has no knowledge of the CLR. Unmanaged code can be
native C++ with pointers, or C, or VB 6, or Delphi, etc. It is everything not managed by the CLR. In the CLR, code is compiled into IL + metadata into assemblies and then those assemblies are JITed into assembly language
instructions while called. It is the metadata throughout that allows managed code to be managed, managed by the CLR. The CLR can control the type definitions and boundaries (enforce CTS type definitions), control memory
through automatic management of data via the garbage collector, and provide CAS security among other benefits. So a class is managed code IF compiled with a .NET compiler and controlled by the CLR whereas “other code is
unmanaged” because it is compiled without a .NET compiler and uses the unmanaged heap for memory and knows nothing of the CLR.

Essentially, both systems produce a Windows PE format file in the form of a DLL or EXE. The huge difference is that in .NET, that PE file is called an assembly and has different header. It also contains IL + metadata. All .NET compilers are REQUIRED to emit IL + metadata. The metadata fully describes all types in terms of CTS types. The metadata allows managed code to be called “self-describing.” When that assembly is loaded, and the types used, the CLR JIT’s the IL for the called method and replaces that section of IL with the native assembly language. The IL is *never* interpreted but provides a common platform-independent, language-independent standard form. Because of all this, the CLR can manage the types and provide it’s services.

Shim

Shim is a generic term for any piece of code, usually in a DLL, that acts as an intermediary between two incompatible systems.  A typical use for a shim is to make an unmanaged DLL usable to a .NET program.  It would present a managed class interface to the .NET project and translate managed method calls to native method calls, marshaling the method arguments as needed.
The shim on .NET is the mscoree.dll and is the responsible to assign you the correct .NET version when you host the CLR.