RPCSVC.IDL

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright 1995 - 1998 Microsoft Corporation. All Rights Reserved.
//
// MODULE: rpcsvc.idl
//
// PURPOSE: Simple RPC service .idl file. This defines the wire
// "contract" between a client and server using this
// interface. All data types and functions (methods,
// operations) that go over the wire must be defined here.
//
//
[
uuid(15cd3850-28ca-11ce-a4e8-00aa006116cb),
version(1.0)
]
interface RpcServiceSample
{

error_status_t
Ping(
[in] handle_t Binding
);


error_status_t
CheckSecurity(
[in] handle_t Binding
);


// Sending a buffer (writing) to the server.

//
// BufferIn1 and BufferIn2 both use length_is() and size_is().
// This slows performance, because a larger buffer must be
// allocated on the sever and the data copied into this larger
// buffer.
//
// BufferIn2 has the most problems because it forces a 16K
// allocation which may be much larger then needed and requires
// and extra data copy. It also limits clients to writing 16K
// at a time.
//
// The BufferIn3() function saves the allocation and copy
// and gives the client complete control of the size.
//
// Notes: Avoid length_is() on [in] parameters. Usually
// size_is() is all that is really needed.

const unsigned long BUFFER_SIZE = 100;

error_status_t
BufferIn1(
[in] handle_t Binding,
[length_is(BufferLength), size_is(BufferSize),
in ] byte Buffer[],
[in] unsigned long BufferLength,
[in] unsigned long BufferSize
);

error_status_t
BufferIn2(
[in] handle_t Binding,
[length_is(BufferLength), in ] byte Buffer[16*1024],
[in] unsigned long BufferLength
);

error_status_t
BufferIn3(
[in] handle_t Binding,
[size_is(BufferLength), in ] byte Buffer[],
[in] unsigned long BufferLength
);

// Getting a buffer (reading) from the server.
//
// In BufferOut1 the size of the output is limited to 16K,
// which will force extra round trips when more then 16K
// is being returned. This requires the client to supply a
// 16K buffer and the stub to allocate 16K on the server side.
//
// In BufferOut2 the client decides how big the buffer
// should be and only as much as the client wants is
// allocated in the server. Similar to BufferOut4
// which is better.
//
// In BufferOut3 the server allocates a buffer exactly
// as large as it wants. This results in two allocations,
// one in the server manager and one in the client. This
// is best if the clients have no idea how much data the
// server will give them.
//
// In BufferOut4 the client decides how big the buffer
// should be. The server can shorten (this should
// be uncommon) the buffer if needed.
//
// Notes: Consider how the client and server interact
// in your application when choosing a "read" style
// interface.


error_status_t
BufferOut1(
[in] handle_t Binding,
[length_is(*pBufferLength)] byte Buffer[16*1024],
[out] unsigned long *pBufferLength
);

error_status_t
BufferOut2(
[in] handle_t Binding,
[size_is(BufferSize), length_is(*pBufferLength),
out] byte Buffer[],
[in] unsigned long BufferSize,
[out] unsigned long *pBufferLength
);

typedef struct {
unsigned long BufferLength;
[unique, size_is(BufferLength)] byte *Buffer;
} BUFFER;

error_status_t
BufferOut3(
[in] handle_t Binding,
[out] BUFFER *pBuffer
);

error_status_t
BufferOut4(
[in] handle_t Binding,
[out, size_is(*pBufferLength)] byte Buffer[],
[in, out] unsigned long *pBufferLength
);

// Structures and Enums.
//
// Use -Zp8 (or higher). (Default on Win32 platforms)
//
// Make sure the structure ends on a 0 mod 4 address.
//
// Use [v1_enum] on all enumerated types.
//
// Following these rules will result in structures (and
// arrays of structures) which can be memcpy()'ed to and from
// the wire. Otherwise the structures will be copied
// member-by-member. (ouch!)
//

typedef enum {
A = 1,
B,
C,
D
} BAD_ENUM;

typedef [v1_enum] enum {
E = 5,
F,
G,
H
} GOOD_ENUM;

struct BAD1 {
long l;
short s; // Ends on 6 % 4 = 2 byte address.
};

struct BAD2 {
BAD_ENUM e; // 16bits on the wire, 32bits in memory!
long l; // How big is it?
};

struct GOOD {
GOOD_ENUM e; // v1_enum 32bits on wire and in memory.
long l;
long l2; // Ends on 12 % 4 = 0 byte address.
};

error_status_t
StructsIn1(
[in] handle_t Binding,
[in] struct BAD1 array[50]
);

error_status_t
StructsIn2(
[in] handle_t Binding,
[in] struct BAD2 array[50]
);

error_status_t
StructsIn3(
[in] handle_t Binding,
[in] struct GOOD array[50]
);
// Linked list examples
//
// Follow the rules for structs when defining your linked
// list nodes.
//
// ListIn and ListOut1 are the basic linked list functions,
// ListOut1 is more expensive because each node must be copied
// into nodes on the client. (In ListIn the list pointers
// are fixed up in one big buffer.)
//
// ListOut2 is identical to ListOut1 except that it turns
// on the RPC allocator in the server.
//
// Linked lists are not very efficient for RPC because the
// often require many memory allocations. When possible,
// replace linked lists with variably sized arrays of structures.
//

const unsigned long LIST_SIZE = 50;

typedef struct LIST {
[unique] struct LIST *pNext;
unsigned long data;
} LIST;

typedef [unique] LIST *PLIST;

error_status_t
ListIn(
[in] handle_t Binding,
[in] PLIST pList
);

error_status_t
ListOut1(
[in] handle_t Binding,
[out] LIST *pListHead
);

// [enable_allocate] in .acf.
error_status_t
ListOut2(
[in] handle_t Binding,
[out] LIST *pListHead
);

// Unions
//
// Avoid using very many unions. For example, don't pass an array in
// which each element contains a union with several arms. Instead,
// define several different structures and define a union with several
// arms each being an array of one of the different types of structures.
//
// Do NOT define a [default] arm for your unions. This way a future
// version of the union can include new arms and still interoperate
// with older versions of the interface.
//
// Avoid passing unions by value.
//

const unsigned long UNION_ARRAY_LEN = 50;

typedef struct BAD_UNION {
unsigned long Tag;
[switch_is(Tag)] union
{
[case(1)]
unsigned long ulData;
[case(2)]
unsigned hyper uhData;
[default]
// The default arm here prevents the addition of
// another case in future versions.
;
} u;
} BAD_UNION;

typedef struct ONE {
unsigned long DataLength;
[size_is(DataLength)] unsigned long *Data;
} ARM_ONE;

typedef struct TWO {
unsigned long DataLength;
[size_is(DataLength)] unsigned hyper *Data;
} ARM_TWO;

typedef struct {
unsigned long Tag;
[switch_is(Tag)] union
{
[case (1)]
[unique] ARM_ONE *pOne;
[case (2)]
[unique] ARM_TWO *pTwo;

// May add [case(3)] in a future version.
//
// When calling a down level server with Tag == 3 the
// error RPC_S_INVALID_TAG will get returned. Values
// 1 and 2 will continue to work.
//
// If there was a [default] arm this wouldn't work.

} u;
} GOOD_UNION;

error_status_t
UnionCall1(
[in] handle_t Binding,
[in] unsigned long Length,
[in, size_is(Length)] BAD_UNION ArrayOfUnions[]
);

error_status_t
UnionCall2(
[in] handle_t Binding,
[in] GOOD_UNION *pUnionContainingArrays
);

}