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 */