XMITU.C

/**************************************************************************** 
Microsoft RPC Version 2.0
Copyright Microsoft Corp. 1992, 1993, 1994- 1996
xmit Example

FILE: xmitu.c

PURPOSE: Utility functions used by both client and server
sides of the RPC distributed application.
This sample demonstrates the transmit_as example.
A doubly-linked list is transmitted over the network
as a sized array.

RELATED: xmits.c - server main
xmitp.c - remote procedures
xmitc.c - client main

FUNCTIONS: DOUBLE_LINK_TYPE_to_xmit - convert list to array
DOUBLE_LINK_TYPE_from_xmit - convert array to list
DOUBLE_LINK_TYPE_free_inst - free linked list memory
DOUBLE_LINK_TYPE_free_xmit - free array memory
midl_user_allocate - user-supplied memory allocator
midl_user_free - user-supplied routine to free memory

ArrayWalkProc - utility to display the array
ListWalkProc - utility to display the linked list
InsertNewNode - utility to add a node to the list

COMMENTS: This sample program generates a linked list to
demonstrate how a list with aliasing can be transmitted
using the transmit_as attribute as a sized array.
The pointers are rebuilt on the server side.

****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include "xmit.h" // header file generated by MIDL compiler
#include "xmitu.h"


/***************************************************************************/

void ArrayWalkProc(DOUBLE_XMIT_TYPE * pArray)
{
int i;

printf("Display contents of transmitted array:\n");
for (i = 0; i < pArray->sSize; i++)
printf("pArray->asNumber[%d] = %d\n", i, pArray->asNumber[i]);
}

void ListWalkProc(DOUBLE_LINK_TYPE * pList)
{
printf("Display contents of doubly linked list:\n");
while (pList != NULL) {
printf("pList @0x%lx = %d, Next = 0x%lx\n",
pList, pList->sNumber, pList->pNext);
pList = pList->pNext;
}
}

DOUBLE_LINK_TYPE * InsertNewNode(short sValue, DOUBLE_LINK_TYPE * pPrevious)
{
DOUBLE_LINK_TYPE * pNew;

do {
pNew = (DOUBLE_LINK_TYPE *)midl_user_allocate(sizeof(DOUBLE_LINK_TYPE));
} while (pNew == pPrevious);

pNew->pNext = NULL; // initialize
pNew->pPrevious = NULL; // initialize
pNew->sNumber = sValue; // insert b between a and c

pNew->pPrevious = pPrevious; // prev(b) = a
if (pPrevious == NULL)
pNew->pNext = NULL;
else {
pNew->pNext = pPrevious->pNext; // next(b) = c
pPrevious->pNext = pNew; // next(a) = b
if (pNew->pNext != NULL)
(pNew->pNext)->pPrevious = pNew; // prev(c) = b
}

return(pNew);
}


/***************************************************************************/

void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
{
return(malloc(len));
}

void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
free(ptr);
}


/***************************************************************************/

/* convert from linked list to array */
void __RPC_USER
DOUBLE_LINK_TYPE_to_xmit(
DOUBLE_LINK_TYPE __RPC_FAR * pList,
DOUBLE_XMIT_TYPE __RPC_FAR * __RPC_FAR * ppArray)
{
short cCount = 0;
DOUBLE_LINK_TYPE * pHead = pList; // save pointer to start
DOUBLE_XMIT_TYPE * pArray;

/* count the number of elements to allocate memory */
for (; pList != NULL; pList = pList->pNext)
cCount++;

/* allocate the memory for the array */
pArray = (DOUBLE_XMIT_TYPE *) midl_user_allocate
(sizeof(DOUBLE_XMIT_TYPE) + (cCount * sizeof(short)));
pArray->sSize = cCount;

/* copy the linked list contents into the array */
for (cCount = 0, pList = pHead; pList != NULL; pList = pList->pNext)
pArray->asNumber[cCount++] = pList->sNumber;

/* return the address of the pointer to the array */
*ppArray = pArray;
}

/* convert from array to linked list */
void __RPC_USER
DOUBLE_LINK_TYPE_from_xmit(
DOUBLE_XMIT_TYPE __RPC_FAR * pArray,
DOUBLE_LINK_TYPE __RPC_FAR * pList)
{
DOUBLE_LINK_TYPE *pCurrent;
int i;

if (pArray->sSize <= 0) { // error checking
pList = NULL;
return;
}

if (pList == NULL)
pList = InsertNewNode(pArray->asNumber[0], NULL);
else {
DOUBLE_LINK_TYPE_free_inst(pList); // free all other nodes
pList->sNumber = pArray->asNumber[0];
pList->pNext = NULL;
}

pCurrent = pList;
for (i = 1; i < pArray->sSize; i++) // write new values
pCurrent = InsertNewNode(pArray->asNumber[i], pCurrent);
}


/* free the doubly linked list */
/* move forward through list, freeing the previous entry */
void __RPC_USER
DOUBLE_LINK_TYPE_free_inst(
DOUBLE_LINK_TYPE __RPC_FAR * pList)
{
while (pList->pNext != NULL) // go to end of list
pList = pList->pNext;

pList = pList->pPrevious;
while (pList != NULL) { // back through list
midl_user_free(pList->pNext);
pList = pList->pPrevious;
}
}

/* free the array structure */
void __RPC_USER
DOUBLE_LINK_TYPE_free_xmit(
DOUBLE_XMIT_TYPE __RPC_FAR * pArray)
{
midl_user_free(pArray);
}

/* end file xmitu.c */