|
|
1.1 ! root 1: /**************************************************************************** ! 2: Microsoft RPC Version 1.0 ! 3: Copyright Microsoft Corp. 1992 ! 4: xmit Example ! 5: ! 6: FILE: xmitc.c ! 7: USAGE: xmitc -n network_address ! 8: -p protocol_sequence ! 9: -e endpoint ! 10: -o options ! 11: -u uuid ! 12: -c count of elements in linked list ! 13: -v value of first element in linked list ! 14: -d delta between values in linked list ! 15: ! 16: PURPOSE: Client side of RPC distributed application. ! 17: This sample demonstrates the transmit_as example. ! 18: A doubly-linked list is transmitted over the network ! 19: as a sized array. ! 20: ! 21: RELATED: xmits.c - server main ! 22: xmitp.c - remote procedures ! 23: ! 24: FUNCTIONS: main() - bind to server and call remote procedure ! 25: PDOUBLE_LINK_TYPE_to_xmit - convert list to array ! 26: PDOUBLE_LINK_TYPE_from_xmit - convert array to list ! 27: PDOUBLE_LINK_TYPE_free_inst - free linked list memory ! 28: PDOUBLE_LINK_TYPE_free_xmit - free array memory ! 29: MIDL_user_allocate - user-supplied memory allocator ! 30: MIDL_user_free - user-supplied routine to free memory ! 31: ! 32: ArrayWalkProc - utility to display the array ! 33: ListWalkProc - utility to display the linked list ! 34: InsertNewNode - utility to add a node to the list ! 35: ! 36: COMMENTS: This sample program generates a linked list to ! 37: demonstrate how the list can be transmitted over ! 38: the network more efficiently as a sized array. ! 39: The pointers are rebuilt on the server side. ! 40: ! 41: The [transmit_as] attribute (used in the typedef of ! 42: PDOUBLE_LINK_TYPE in the file XMIT.IDL) requires the ! 43: four user-supplied functions whose names start with ! 44: the name of the presented type, PDOUBLE_LINK_TYPE. ! 45: ! 46: The [in, out] attributes applied to remote procedure ! 47: parameters require the two user-supplied functions ! 48: MIDL_user_allocate and MIDL_user_free. ! 49: ! 50: The other functions are utilities that are used to ! 51: build or display the data structures. ! 52: ! 53: ! 54: ****************************************************************************/ ! 55: #include <stdio.h> ! 56: #include <string.h> ! 57: #include <stdlib.h> ! 58: #include <rpc.h> // RPC API functions, types ! 59: #include "xmit.h" // header file generated by MIDL compiler ! 60: ! 61: #define PURPOSE \ ! 62: "This Microsoft RPC Version 1.0 sample program demonstrates\n\ ! 63: the use of the [transmit_as] attribute. For more information\n\ ! 64: about the attributes and the RPC API functions, see the\n\ ! 65: RPC programming guide and reference.\n\n" ! 66: ! 67: #define MAX_ELEMENTS 50 ! 68: ! 69: void Usage(char * pszProgramName) ! 70: { ! 71: fprintf(stderr, "%s", PURPOSE); ! 72: fprintf(stderr, "Usage: %s\n", pszProgramName); ! 73: fprintf(stderr, " -p protocol_sequence\n"); ! 74: fprintf(stderr, " -n network_address\n"); ! 75: fprintf(stderr, " -e endpoint\n"); ! 76: fprintf(stderr, " -o options\n"); ! 77: fprintf(stderr, " -u uuid\n"); ! 78: fprintf(stderr, " -c count_of_elements\n"); ! 79: fprintf(stderr, " -v value\n"); ! 80: fprintf(stderr, " -d delta\n"); ! 81: ! 82: exit(1); ! 83: } ! 84: ! 85: DOUBLE_LINK_TYPE * InsertNewNode(short sValue, DOUBLE_LINK_TYPE * pPrevious) ! 86: { ! 87: DOUBLE_LINK_TYPE * pNew; ! 88: ! 89: pNew = (DOUBLE_LINK_TYPE *) malloc(sizeof(DOUBLE_LINK_TYPE)); ! 90: if (pNew != NULL) { ! 91: pNew->sNumber = sValue; /* insert b between a and c */ ! 92: pNew->pPrevious = pPrevious; /* prev(b) = a */ ! 93: if (pPrevious != NULL) { ! 94: pNew->pNext = pPrevious->pNext; /* next(b) = c */ ! 95: pPrevious->pNext = pNew; /* next(a) = b */ ! 96: if (pNew->pNext != NULL) ! 97: (pNew->pNext)->pPrevious = pNew; /* prev(c) = b */ ! 98: } ! 99: else ! 100: pNew->pNext = NULL; ! 101: } ! 102: return(pNew); ! 103: } ! 104: ! 105: void ArrayWalkProc(DOUBLE_XMIT_TYPE * pArray) ! 106: { ! 107: int i; ! 108: printf("Display contents of transmitted array:\n"); ! 109: ! 110: for (i = 0; i < pArray->sSize; i++) ! 111: printf("pArray->asNumber[%d] = %d\n", i, pArray->asNumber[i]); ! 112: } ! 113: ! 114: void ListWalkProc(DOUBLE_LINK_TYPE * pList) ! 115: { ! 116: printf("Display contents of doubly linked list:\n"); ! 117: while (pList != NULL) { ! 118: printf("pList @0x%x = %d, Next = 0x%x\n", pList, pList->sNumber, pList->pNext); ! 119: pList = pList->pNext; ! 120: } ! 121: } ! 122: ! 123: void * MIDL_user_allocate(size_t len) ! 124: { ! 125: return(malloc(len)); ! 126: } ! 127: ! 128: void MIDL_user_free(void * ptr) ! 129: { ! 130: free(ptr); ! 131: } ! 132: ! 133: /* free the doubly linked list */ ! 134: void DOUBLE_LINK_TYPE_free_inst (DOUBLE_LINK_TYPE * pList) ! 135: { ! 136: while (pList->pNext != NULL) /* go to end of list */ ! 137: pList = pList->pNext; ! 138: for (pList = pList->pPrevious; pList != NULL; pList = pList->pPrevious) ! 139: free(pList->pNext); ! 140: } ! 141: ! 142: /* free the array structure */ ! 143: void DOUBLE_LINK_TYPE_free_xmit (DOUBLE_XMIT_TYPE * pSizedArray) ! 144: { ! 145: free(pSizedArray); ! 146: } ! 147: ! 148: ! 149: /* convert from linked list to array */ ! 150: void DOUBLE_LINK_TYPE_to_xmit (DOUBLE_LINK_TYPE * pList, ! 151: DOUBLE_XMIT_TYPE ** ppArray) ! 152: { ! 153: short cCount = 0; ! 154: DOUBLE_LINK_TYPE * pHead = pList; /* save pointer to start */ ! 155: DOUBLE_XMIT_TYPE * pArray; ! 156: ! 157: /* count the number of elements to allocate memory */ ! 158: for (; pList != NULL; pList = pList->pNext) ! 159: cCount++; ! 160: ! 161: /* allocate the memory for the array */ ! 162: pArray = (DOUBLE_XMIT_TYPE *) malloc(sizeof(DOUBLE_XMIT_TYPE) + (cCount * sizeof(short))); ! 163: pArray->sSize = cCount; ! 164: ! 165: /* copy the linked list contents into the array */ ! 166: cCount = 0; ! 167: for (pList = pHead; pList != NULL; pList = pList->pNext) ! 168: pArray->asNumber[cCount++] = pList->sNumber; ! 169: ! 170: /* return the address of the pointer to the array */ ! 171: *ppArray = pArray; ! 172: } ! 173: ! 174: /* convert from array to linked list */ ! 175: void DOUBLE_LINK_TYPE_from_xmit (DOUBLE_XMIT_TYPE * pArray, ! 176: DOUBLE_LINK_TYPE * pDblLinkedList) ! 177: { ! 178: PDOUBLE_LINK_TYPE pCurrent, pNew; ! 179: ! 180: int i; ! 181: ! 182: pCurrent = pDblLinkedList; ! 183: pCurrent->sNumber = pArray->asNumber[0]; ! 184: ! 185: DOUBLE_LINK_TYPE_free_inst(pCurrent); ! 186: pCurrent->pNext = NULL; /* wipe out pointer to old list */ ! 187: ! 188: for (i = 1; i < pArray->sSize; i++) { ! 189: pNew = InsertNewNode(pArray->asNumber[i], pCurrent); ! 190: pCurrent = pNew; ! 191: } ! 192: return; ! 193: } ! 194: ! 195: ! 196: /* main: establish the binding to the server, call the remote procedure */ ! 197: void main(int argc, char **argv) ! 198: { ! 199: RPC_STATUS status; // returned by RPC API function ! 200: unsigned char * pszUuid = "12345678-1234-1234-1234-123456789ABC"; ! 201: unsigned char * pszProtocolSequence = "ncacn_np"; ! 202: unsigned char * pszNetworkAddress = NULL; ! 203: unsigned char * pszEndpoint = "\\pipe\\xmit"; ! 204: unsigned char * pszOptions = NULL; ! 205: unsigned char * pszStringBinding = NULL; ! 206: int i; ! 207: int cElements = 10; ! 208: short sValue = 100; ! 209: short sDelta = 10; ! 210: ! 211: DOUBLE_LINK_TYPE * pFirst; ! 212: DOUBLE_LINK_TYPE * pCurrent, * pNew; ! 213: ! 214: // allow the user to override settings with command line switches ! 215: for (i = 1; i < argc; i++) { ! 216: if ((*argv[i] == '-') || (*argv[i] == '/')) { ! 217: switch (tolower(*(argv[i]+1))) { ! 218: case 'p': // protocol sequence ! 219: pszProtocolSequence = argv[++i]; ! 220: break; ! 221: case 'n': // network address ! 222: pszNetworkAddress = argv[++i]; ! 223: break; ! 224: case 'e': ! 225: pszEndpoint = argv[++i]; ! 226: break; ! 227: case 'o': ! 228: pszOptions = argv[++i]; ! 229: break; ! 230: case 'u': ! 231: pszUuid = argv[++i]; ! 232: break; ! 233: case 'c': ! 234: cElements = atoi(argv[++i]); ! 235: if (cElements > MAX_ELEMENTS) ! 236: cElements = MAX_ELEMENTS; ! 237: break; ! 238: case 'v': ! 239: sValue = (short)atoi(argv[++i]); ! 240: break; ! 241: case 'd': ! 242: sDelta = (short)atoi(argv[++i]); ! 243: break; ! 244: ! 245: case 'h': ! 246: case '?': ! 247: default: ! 248: Usage(argv[0]); ! 249: } ! 250: } ! 251: else ! 252: Usage(argv[0]); ! 253: } ! 254: /* initialize a list with a number of elements */ ! 255: pFirst = InsertNewNode(sValue, NULL); ! 256: pCurrent = pFirst; /* assign some values to the list nodes */ ! 257: sValue += sDelta; /* make them different values */ ! 258: ! 259: for (i = 1; i < cElements; i++) { ! 260: pNew = InsertNewNode(sValue, pCurrent); ! 261: pCurrent = pNew; ! 262: sValue += sDelta; ! 263: } ! 264: printf("Client main: "); ! 265: ListWalkProc(pFirst); ! 266: ! 267: /* Use a convenience function to concatenate the elements of the string */ ! 268: /* binding into the syntax needed by RpcBindingFromStringBinding. */ ! 269: ! 270: status = RpcStringBindingCompose(pszUuid, ! 271: pszProtocolSequence, ! 272: pszNetworkAddress, ! 273: pszEndpoint, ! 274: pszOptions, ! 275: &pszStringBinding); ! 276: printf("RpcStringBindingCompose returned 0x%x\n", status); ! 277: printf("pszStringBinding = %s\n", pszStringBinding); ! 278: if (status) ! 279: exit(2); ! 280: ! 281: /* Set the binding handle that will be used to bind to the server. */ ! 282: ! 283: status = RpcBindingFromStringBinding(pszStringBinding, ! 284: &hXmit); ! 285: printf("RpcBindingFromStringBinding returned 0x%x\n", status); ! 286: if (status) ! 287: exit(2); ! 288: ! 289: printf("Calling the remote procedure 'ModifyListProc'\n"); ! 290: ! 291: ModifyListProc(pFirst); // call the remote procedure ! 292: ! 293: printf("Calling the remote procedure 'Shutdown'\n"); ! 294: Shutdown(); // shut down the server side ! 295: ! 296: printf("After ModifyListProc, the list appears as follows:\n"); ! 297: ListWalkProc(pFirst); // call the utility that displays the list ! 298: ! 299: /* The calls to the remote procedures are complete. */ ! 300: /* Free the string and the binding handle using RPC API calls. */ ! 301: ! 302: status = RpcStringFree(&pszStringBinding); // remote calls done; unbind ! 303: printf("RpcStringFree returned 0x%x\n", status); ! 304: if (status) ! 305: exit(2); ! 306: ! 307: status = RpcBindingFree(&hXmit); // remote calls done; unbind ! 308: printf("RpcBindingFree returned 0x%x\n", status); ! 309: if (status) ! 310: exit(2); ! 311: ! 312: exit(0); /* successful completion */ ! 313: } ! 314: /* end \xmitc.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.