|
|
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.