midl.exe does not accept function definition

I was able to compile this code with idltojava (without the uuid info), but it gives me syntax errors when I use midl.exe.  am I missing something in the beginning of the code?

// here is my code
[ uuid (53D5C100-25F6-11D1-B64C-000012df6b3e),
interface Hello
    struct A {short field;};
    const float pi = 3.14;
    void f();
    void q(in long s); // it fails in this line

//here's the error message
error MIDL2025 : syntax error : expecting a type specification near "in"
Who is Participating?
WynConnect With a Mentor Commented:
Microsoft Interface Definition Language (MIDL): 64-Bit
Porting Guide

Microsoft Corporation

Last updated: August 1999

Summary: This technical white paper discusses
Microsoft?Interface Definition Language (MIDL)
and Remote Procedure Call (RPC) issues related to
64-bit porting efforts. Both old techniques and new
64-bit features that can facilitate porting
applications from 32-bit environments are described.


Tips for Modifying RPC Interfaces
MIDL64—New Features for 64-Bit Windows
Frequently Asked Questions
Open Issues
For More Information


This technical white paper discusses Microsoft?
Interface Definition Language (MIDL) compiler and
Procedure Call (RPC) issues related to 64-bit porting
efforts. Both old techniques and new 64-bit features
that can facilitate porting applications from 32-bit
environments are described.


With the coming availability of 64-bit Windows?there
is a need for a MIDL/RPC guide outlining what can
and cannot be done with regards to porting legacy

   Terminology Note   There is some confusion among IT
staff regarding the terms local, inproc and
   remote. An inproc call in RPC means an RPC call
that is executed within the same process. For
   example, different DCOM apartments can execute as
separate threads in a process. RPC is optimized
   for in-process calls; however, the arguments of the
call still go through the marshaler. Therefore, all
   the usual restrictions of RPC calls, such as no
void *, apply. The inproc call category has been
   introduced for performance reasons, as some handles
make sense on both sides of the call. Remote
   call usually refers to a non-inproc call, because
there is not a much difference between executing an
   RPC call from process to process or from machine to
machine. Both cases involve two different address
   spaces requiring marshaling of all the arguments.
Sometimes, especially in contrast to a local call, a
   remote call means any call that goes through RPC
and so requires marshaling and unmarshaling of
   arguments. In RPC context, a local call means a
call within the same process where RPC is actually not
   used at all—the call goes directly from client
layer to server layer of the application. In
particular, a
   [local] attribute of RPC means that the procedure
or interface flagged with it is never used in a remote
   call. Sometimes an interface is specified as
[local] just to get its C definition in a convenient
..h file.

   Also note, that when more information about
specific MIDL attributes is desired, MSDN is the best
   to date source for pre-64-bit functionality RPC


This section focuses on 64-bit specific problems;
discussion of 32-bit specifics has been added where

Backward Wire Compatibility

When porting an RPC application, the key feature to
consider is the backward wire compatibility; that is,
the ability of the original and the ported versions to
talk in the same wire format or protocol, in this case
the NDR (see Endnote 1) wire representation of
transmitted data. Backward wire compatibility may be
issue whenever one of the following happens:

     Methods are added to an interface.

     New data types are introduced.

     Old data types are changed in some way.

Usually, methods are added to the interface as a
result of expanding the server's functionality for a
release of a product. The wire incompatibility may
happen if the new client is not prevented from calling
old server. This type of wire incompatibility is the
most obvious one, and this issue is not really a
issue; see the section "Nonissues" for a more detailed

Introducing a new data type or modifying an existing
data type is the most frequent source of wire
incompatibility problems. The core reason for all of
these problems is that the OSF/DCE RPC paradigm
assumes that the receiving party has preexisting
knowledge about the nature of the data coming in; that
is, the data is sent without a generic data
description. Therefore, whenever a receiver expects a
data type than the sender has put on the wire, the
most likely outcome is a bad stub data exception.

The cleanest way of adding new data types to an
interface is to use them only in new methods. This
doesn't create any problems other than the ones
introduced by adding the new methods themselves.
Changing data types used in existing methods creates
incompatibilities. Typically, there are two ways to
add types to an existing interface that can create
problems. The explicit way is to change one of the
unions controlling data flow by defining a new branch
that takes a new type, such as a new info level in
some methods returning server information. This is
usually a situation that is easy to control. The
however, may be concealed when an application hides a
data type from RPC or cheats on the RPC
marshaler. An example of hiding is when an application
sends an array of bytes that, in fact, is structured
data. An example of cheating is when an application
sends a long that means something else. Hiding is
actually a form of cheating, and application writers
usually encounter trouble when the application talks
a big-endian machine for the first time.

Porting from the 32-bit version of Windows to Win64?
does not create RPC problems in itself. The
abstract data type model established for porting (that
is, LLP64) has a great advantage for porting RPC
applications. Essentially, in this model, all of the
integral data types used in the 32-bit world stay at
same size in the 64-bit world, and only the pointer
size changes from 32-bit to 64-bit. The RPC
programming model has always relied on data sizes
being well defined, with all of the integral types
the same size on both sides of the connection. Because
the size of the integral types doesn't change,
there is no wire incompatibility. On the other hand,
pointers are local to each side of the RPC
and typically go on the wire only as null or nonnull
markers. Thus, marshaler is able to handle different
pointer sizes on both ends of a connection in a manner
that is transparent to the user.


Pointers, when specified

Changing the size of the pointer itself is not an
issue if the interface in question has a pointer
specified as
an argument. On the wire, pointers are represented by
4-byte markers. When making an RPC, whether it
is truly remote or within the same machine, pointers
are typically recreated from scratch at the other
based on the marker. The MIDL and RPC marshaler handle
this transparently. For 64-bit porting, this
transparent handling is at the expense of performance.
Performance extensions to the MIDL compiler and
the corresponding marshaler engine are planned for the

Also note that a typical pointer for an [in] argument,
such as the one shown below:

   long  Foo( [in] long * Bar );

is a [ref] pointer that does not have any wire
representation at all. In the above example,
only a long would be sent from client to server.

Context handles

The context handle is a special RPC concept introduced
solely for the purpose of giving a client an opaque
handle to a server context held on behalf of the
client. Typically, it is a void * pointer marked as a
handle. The type is defined with the [context_handle]
attribute and implies the following semantics. A
handle must be obtained from the server first,
typically by means of a call with handle as an [out]
argument. The client indicates the context whenever
handle is an [in] argument. At the end, the handle
must be closed to clean up the server context. This is
done by means of a call with an [in,out] context
handle argument when the handle comes back as null. An
added bonus is that a context handle can be
cleaned up automatically by the RPC runtime when the
connection breaks.

Each context is identified by a globally unique
identifier (GUID) generated on the fly by the RPC
when the handle is created. Context handles are
represented on the wire by 20 bytes that include the
GUID to identify the context. On the client, the
application is handed a handle to a dictionary storing
context handle GUIDs. On the server, the pointer to
the context is retrieved from a similar dictionary
based on the GUID. No pointer is sent across, and this
process works completely transparently across the
32-bit/64-bit boundary.

For example:

typedef [context_handle] void * MyContext;

void OpenContext( <some other args>,  [out] MyContext
* pHandle );
void UseContext( [in] MyContext  Handle, <some other
args>  );
void CloseContext( [in,out] MyContext * pHandle );  //
null when [out]

One important part of context handle semantics is that
a context handle is related to the
server that generated it. In particular, when there is
no explicit binding handle argument
of a call, the context handle argument directs the
binding, meaning that the call is
directed to the server that originated the handle. If
an explicit binding handle is used, the
binding implied by the context handle must agree with
the one indicated by the binding
handle, and must resolve to the same server. If there
is a disagreement—for example, if
different servers are implied by context handle(s) and
the binding handle—the call fails by

In addition, there is a group of attributes related to
context handles that can force a better granularity of
the context checking or some particular type of a
context handle; this is outside of the scope of this
discussion. For example, a programmer can specify a
[strict_context_handle] type, where the context
handle is valid only when used with the same server
and interface that created it.

Handle Types

Binding handles, handle_t type

These handles are RPC handles indicating the server to
connect to. They are indicated by the application
configuration file (ACF) attributes, such as
[implicit_handle], [explicit_handle], and
[auto_handle]. These
handles are internal RPC handles that are never
represented as arguments on the wire. They are
manipulated by means of RPC runtime application
programming interfaces (APIs), and not by remote
Typically, a handle must be well-defined before a
remote call can be executed and doesn't change during
the call. Other internal RPC handles of a similar
nature are pickling handles and async handles.

Generic [handle] handles

A generic handle is a special type of binding handle
that is a cross between a binding handle and a generic
data type remotable by means of RPC. When this type of
handle is used in a call, special binding semantics
are implied (on the client side only) by the stub
before and after the proper remote call. A typical
declaration may look like this:

typedef [handle] wchar_t *STRING_HANDLE;

It's used in a call like this:

   [in, string, unique] STRING_HANDLE pPrinterName,
   [out] PRINTER_HANDLE *pHandle,
   [in, string, unique] wchar_t * pDatatype,
   [in] DWORD AccessRequired

The special binding semantics consist of the client
stub calling a STRING_HANDLE_bind()
routine to establish a binding before the stub
marshals arguments, then calling a
STRING_HANDLE_unbind() routine after the stub
unmarshals the reply. The application
writer provides the routines. The bind and unbind
calls are performed each time the client
application executes a call using a STRING_HANDLE
argument as a binding argument.

When data is marshaled for the call, the generic
handle argument is represented by the data it has been
specified with. Therefore, it is undistinguishable on
the wire from the same data being sent in the usual
way. As far as the data itself is concerned, it is
treated like other data arguments for the purposes of
marshaling and unmarshaling. In the above example, a
Unicode character string would be marshaled as
usual for a STRING_HANDLE argument.


Each of these is a polymorphic integral type that has
a different size on 32-bit and 64-bit Windows NT?
platforms to guarantee that a pointer value can be
stored in it. The data types are defined in the public
file, basetsd.h. Each has a size of 4 bytes on 32-bit
systems and 8 bytes on 64-bit systems. On 32-bit
platforms, INT_PTR maps to int and LONG_PTR maps to
long. On 64-bit platforms, both the types map to
__int64. Types such as these cannot be supported in a
satisfactory way in RPC. In fact, if not for the
porting, a type like this would never be supported and
should be seen only as a means of facilitating the
32-bit-to-64-bit porting effort. The reason these
types are supported by MIDL is to address a situation
where a pointer needs to be kept in an integral field
for some reason. Typically, a remote application
programming interface (API) would send a handle across
the wire disguised as a DWORD.

Please note however, that sending a pointer or handle
this way could never really work with RPC. That is,
either the argument didn't mean a pointer, it went
unused, or the pointer or handle value was sent out
only to be sent back and used at the server. In other
words, this was another case of cheating on RPC. As
described in this document, one way to avoid cheating
is to use a context handle or an IUnknown interface

MIDL supports the 32-bit/64-bit polymorphism by means
of the __int3264 intrinsic integral type described
later in this document. However, this type should not
be introduced to a remoted interface unless it is
unavoidable because of porting. New interfaces should
never use it. You should make up your mind as to
the nature of data manipulated remotely and specify
either an __int32 (a long) or an __int64 (a hyper) as
appropriate. If the field or argument is really
designed to hold a pointer, an appropriate pointer or
handle type should be used.

For the porting, you should not use the new intrinsic.
Instead, you should use the types defined in
public\sdk\inc\basetsd.h directly: INT_PTR, LONG_PTR,
DWORD_PTR, and so forth, can be used as
appropriate. The file contains all the mappings needed
for MIDL and C/C++ compilation of the types.

The polymorphic types should not be used
automatically, just because they are available. For
clarity of
design and implementation, it is worth reworking the
application so that you use clean types and thereby
avoid side effects, such as the performance penalty
inherent to polymorphic types.

For example, in RPC's own code, there was a case where
a BufferLength field was assigned a pointer
because the marshaler was using a sizing routine
(which increments a value of the BufferLength field by
object size according to the object type) to increment
the pointer by the size of the pointee. At first, it
seemed that this field needed to be converted from
unsigned long to UINT_PTR. Some alignment issues
had to be taken care of, but eliminating the usage was
fairly simple; therefore, modifying the application
removed the need to use the polymorphism at all.

Examples of Problems with Cheating

In summary, at the core of each RPC porting problem is
always an application not sticking to the RPC
specification and cheating on the stubs and marshaler
in some way.

Problems may typically arise when:

     A remoted data type changes for some reason. For
example, a field was a long and
     now needs to be __int64. See the LONG_PTR
description above for a discussion.

     Some kind of cheating on the core RPC marshaling
was taking place, and typically
     some side effects were used to send simplified
data for performance or other reasons.

Example 1. Sending a server pointer context back as a
DWORD in a standard interface

Typically, this is a design problem that should have
been solved by using context handles in the first

For example:

    [in]                     handle_t hBinding,
    [in]                     ULONG    hRecipient,
    [in,size_is(ulSize)]     LPBYTE  
    [in]                     ULONG    ulSize,
    [in]                     DWORD    Flags,
    [out]                    PULONG   Context,
    [in]                     ULONG    hProcess

    [in]                     handle_t hBinding,
    [in]                     ULONG    Context

This is an excerpt from a standard (raw) RPC
interface, as opposed to an object or DCOM

Apparently ULONG sent as a context is intended to be a
pointer. Hence, that would not work when
sending back and forth from a 32-bit to a 64-bit
environment. Also note, that changing the type of the
Context argument from ULONG to __int64 or similar will
break the wire compatibility, and that using
__int3264, as described later, would keep wire
compatibility intact but would not work (the cheating
is not
good enough).

From what we know, the ULONG manipulated here is
really a server context handle—the handle is obtained
in the Register call and released in the Unregister
call above. We are not interested in details of the
usage. However, notice that this design has an
inherent problem in that it is not clear what happens
the server context when the client dies or goes away
without unregistering first. This functionality should
have been mapped to a context handle solution. In
other words, the design is flawed because a shortcut
is used when sending context pointers instead of a
clean context handle.

When looking at a problem like this in the context of
porting, it is important to consider whether wire
compatibility is an issue. Your solution choice
depends on whether the interface has been made public;
if it
has, it generally cannot be changed. On the other
hand, if the interface was used only within a single
machine by a component that cannot have different
versions on the same machine, it typically can be
changed freely.

In many situations, it is possible that backward
compatibility problems can be ignored or the interface
reworked so that a context handle is used. If this is
possible, it is the best solution. To use context
handles, the interface could be changed to take the

typedef [context_handle] void * NOTIFICATION_CONTEXT;

    [in]                     handle_t hBinding,
    [in]                     ULONG    hRecipient,
    [in,size_is(ulSize)]     LPBYTE  
    [in]                     ULONG    ulSize,
    [in]                     DWORD    Flags,
    [out]                    NOTIFICATION_CONTEXT *
    [in]                     ULONG    hProcess

    [in]                     handle_t hBinding,
    [in,out]                 NOTIFICATION_CONTEXT *

The user needs to provide a rundown routine to clean
up the server context when the
connection between client and server breaks. The
routine would have the following


Please see description of context handles in the
context handle section for more
information about the Context_rundown routine.

Example 2. Sending a server pointer context back as a
DWORD in a DCOM interface

Typically, this is another design problem. Possibly,
IUnknown * should have been used. For example, let's
look at IConnectionPoint interface.

interface IConnectionPoint : IUnknown
    < snip, snip >

    HRESULT Advise(
                [in] IUnknown * pUnkSink,
                [out] DWORD * pdwCookie );

    HRESULT Unadvise(
                [in] DWORD dwCookie );


This is similar to the previous example in that, as
far as we know, the intention here was
to have the cookie be a polymorphic type that would
make it possible to send DWORDs as
well as pointers across the wire.

First, note that the interface is a public interface
released with Windows NT 4.0; therefore, backward wire
compatibility is required. For that reason, changing
the interface is not an option. If the interface
to be changed, the only solution would be to introduce
another interface and phase out this one over

Even if the backward compatibility requirement didn't
preclude changing the interface, the context handle
approach could not be used here. This is because DCOM
provides a context_handle-like functionality by its
nature. Therefore, context handles are not needed in
DCOM interfaces and MIDL would not allow using
one. One way of looking at this is that server
contexts correspond to objects in DCOM. So, instead of
creating a context handle, you pass an interface
pointer indicating the object. Instead of passing the
context handle to indicate the server context, you can
either call methods directly through the interface
pointer or you can put that interface pointer in some
other calls. Lastly, to release a server object the
client can simply call the Release() method, present
in every interface, through the interface pointer.
This is
the essence of object programming in DCOM—the contexts
(objects) are indicated by interface pointers
and reference counting dictates their life span.

Therefore, in DCOM, the typical solution is, in a way,
symmetrical to context handles in raw RPC, or, if you
prefer, context handles emulate an object behavior.
For this reason, the cookie should have been defined
as an IUnknown * pointer and the interface could have

                [in] IUnknown * pUnkSink,
        [out] IUnknown ** ppCookie );

Note that the Unadvise method isn't needed at all; to
release the context it would be
enough to call:


As mentioned earlier, every interface has a Release()
method by virtue of inheriting from
the IUnknown interface.

Example 3. Sending a pointer as a DWORD

Continuing the previous example, whatever can be said
about errors of the original design, there may also
be a legacy problem. That is, there may be a situation
where a pointer was sent as a long, nothing can be
done without breaking wire compatibility, and some
other fix is needed. In this case, the solution would
to stick to the wrong design; that is, keep sending
the long, but do an auxiliary mapping between pointers
and DWORDs as necessary.

For example, the methods from the previous example
could be fixed by introducing a simple RPC wrapper
by means of using [call_as] attribute. (If your
application uses the standard RPC interface, see the
discussion of the [call_as] feature and the example of
usage with a standard RPC interface).

    [in]  IUnknown * pUnkSink,
    [out] DWORD_PTR * pdwCookie );

  HRESULT Unadvise(
    [in] DWORD_PTR dwCookie );

HRESULT NewRemoteAdvise(
    [in] IUnknown * pUnkSink,
    [out] DWORD *   pdwCookie );

HRESULT NewRemoteUnadvise(
            [in] DWORD  dwCookie );

Note that the application interface has the same
methods, Advise and Unadvise, except
that they have to take an ULONG_PTR or DWORD_PTR
instead of DWORD to be able to
keep a pointer. As explained in the [call_as] section,
the call still goes through Advise and
Unadvise for application API compatibility, except
that the remote call is now executed
using the NewRemote* methods. For this particular
case, the new remote methods are
designed to have exactly the same wire layout. What
you get from the [call_as] scheme is
simply the introduction of hand-written wrappers on
both sides. The server side wrapper
for Advise needs to introduce mapping between the
returned pointers and DWORDs by
keeping an appropriate dictionary. A server wrapper
for Unadvise needs to map back from a
DWORD to pointer using the same dictionary. The client
side wrapper does not have to do
anything except pass the arguments without any
changes. Therefore, the wrappers could
look like this:

// server side wrappers
    IConnectionPoint * This,
IUnknown * pUnkSink,
DWORD * pdwCookie )
  LONG_PTR * UnmappedCookie = 0;
  HRESULT hr =
     This->lpVtbl->Advise( This, pUnkSink, &
UnmappedCookie );
  *pdwCookie = MapPointertoDWORD( UnmappedCookie );
  return hr; // add a better error control

IConnectionPoint_Unadvise_Stub (
    IconnectionPoint * This,
DWORD dwCookie )
  LONG_PTR Cookie = MapDWORDtoPointer( dwCookie);
  return This->lpVtbl->Unadvise( This, Cookie );

// client side wrappers
    IConnectionPoint * This,
IUnknown * pUnkSink,
DWORD_PTR * pdwCookie )
  return IConnectionPoint_NewRemoteAdvise_Proxy( This,
                             (DWORD *)pdwCookie );

IconnectionPoint_Unadvise_Proxy (
    IConnectionPoint * This,
DWORD_PTR dwCookie )
  return IConnectionPoint_NewRemoteUnadvise_Proxy(
This, (DWORD)dwCookie );

Note that this is a porting solution; namely, in this
solution, we always do mapping
between cookies and DWORDs and we always send DWORDs
out. For 64-bit-to-64-bit
communications with better performance, a clean way to
cheat would be to simply define
another interface, one that would send an __int64 on
the wire.

Remoting Handles

In this section we discuss general issues related to
remoting handles as opposed to pointers. Please look
at the next section to see how to deal with Win32
system handles.

The essential difference here is that while a pointer
directly indicates a datum, a handle may be seen as a
key to data. That is, some level of indirection is
implied by the handle, some other special values of
handle can exist besides NULL, etc. If so, then the
implementor of the handle package may choose to
restrict the handle value range of 64b package to be
the same as the range of the 32b package, most
likely to be 32b key values. As 4GB range implies a
lot of handles, this is most likely a perfectly
solution for 64b porting. At the same time, it is
typical that handles are defined as a void * type, and
following the definition their size should follow the
size of the pointer to minimize impact on the related

This boils down to a solution where the handle has the
size of a pointer, that is 4 or 8 bytes depending on
a platform, but the lower 32b are enough to identify
the handle correctly by the package. There are 2
choices for the upper 32b: they either should always
be set to 0, or should always be sign extended by
the package. The choice is difficult as both
approaches have similar advantages and disadvantages.
deciding factor is the pattern of usage by the
customers of the package under discussion.

When the handle values are sign-extended, handling of
all the special values, like ?, is easy. Hence, the
client code requires a minimal facelift. It also
agrees well with using handles in remote RPC calls via
a long
argument. However, when remoting the handle via a
DWORD, a care has to be applied at the 64b side to
sign extend the handle properly. Otherwise the handle
looses sign extension and a comparison like h1 ==
h2 is unreliable (the handles may differ only on upper
32 bits).

When the handle values are zero extended, the special
values like -1 have to be redefined as constants
with appropriate casts and client code modified as
appropriate. This approach agrees very nicely with RPC
remoting via DWORD arguments, which is a typical hack
people use. However, if RPC calls use a long to
represent handle, the care has to be taken to cast the
value properly. Also, if special handle values have
been defined in terms of values perceived as unsigned,
like 0xFFFFFFFF, the user may end up with
comparing a handle with a sign extended 0xFFFFFF
try [in] instead of in and see if that works
Try void q([in] long s);
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

at least we agree!!
tekelAuthor Commented:
okay, using [in] works when i use midl.exe,
but when I use idltojava it gives me a syntax error in the same line.  I thought IDL was suppose to be language-independent?
midl is microsoft specific.
tekelAuthor Commented:
thanks a lot,
All Courses

From novice to tech pro — start learning today.