// 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 (c) Microsoft Corporation. All rights reserved. /**************************************************************************** Microsoft RPC picklp Example FILE: picklpc.c USAGE: picklpc -f filename (file to write to/read from) -d (serialization direction: decode) -e (serialization direction: encode) -i (incremental serialization on) PURPOSE: The only side of RPC application FUNCTIONS: main() - serializes data to or from a file COMMENTS: Data procedure serialization is demonstrated here ****************************************************************************/ #include #include #include "picklp.h" // header file generated by MIDL compiler #define PURPOSE \ "This Microsoft RPC Version 2.0 sample program demonstrates\n\ the use of the [encode,decode] attributes. For more information\n\ about the attributes and RPC API functions, see the RPC programming\n\ guide and reference.\n\n" /* Used for incremental style only. */ void __RPC_USER PicAlloc( void * pState, char ** ppBuf, unsigned int * pCount); void __RPC_USER PicWrite( void * pState, char * pBuf, unsigned int Count); void __RPC_USER PicRead ( void * pState, char ** pBuf, unsigned int * pCount); typedef struct PickleControlBlock { unsigned char * pMemBuffer; unsigned char * pBufferStart; unsigned long LastSize; } PickleControlBlock; static PickleControlBlock UserState; static PickleControlBlock * pUserState = &UserState; void Usage(char * pszProgramName) { fprintf_s(stderr, "%s", PURPOSE); fprintf_s(stderr, "Usage: %s\n", pszProgramName); fprintf_s(stderr, " -d\n"); fprintf_s(stderr, " -e\n"); fprintf_s(stderr, " -ffilename\n"); fprintf_s(stderr, " -i \n"); exit(1); } void DumpData( char * pszComment, char * pszText, OBJECT1 * pObject1, OBJECT2 * pObject2 ) { int i; printf_s( "\n%s\n", pszComment ); printf_s( "\tString\n\t\t%s\n", pszText ); printf_s( "\tObject1"); for (i=0; i < ARR_SIZE; i++) { if ( (i % 5) == 0 ) printf_s( "\n\t\t"); printf_s( "%08xl ", pObject1->al[i] ); } printf_s( "\n\t\t%x\n", pObject1->s ); printf_s( "\tObject2"); printf_s( "\n\t\t%x", pObject2->sSize ); for (i=0; i < ARR_SIZE; i++) { if ( (i % 10) == 0 ) printf_s( "\n\t\t"); printf_s( "%04x ", pObject2->as[i] ); } printf_s( "\n" ); } void WriteDataToFile( char * pszFileName, char * pbBuffer, unsigned long ulSizeToWrite ) { FILE * pFile; size_t Count; if ( pszFileName ) { fopen_s(&pFile,pszFileName, "w+b" ); if ( pFile == NULL ) { printf_s("Cannot open the file for writing\n"); exit(1); } Count = sizeof(long); if ( fwrite( &ulSizeToWrite, sizeof(byte), Count, pFile) != Count ) { printf_s("Cannot write1 to the file\n"); exit(1); } Count = (size_t) ulSizeToWrite; if ( fwrite( pbBuffer, sizeof(byte), Count, pFile) != Count ) { printf_s("Cannot write2 to the file\n"); exit(1); } if ( fclose( pFile ) != 0) { printf_s("Failed to close the file\n"); exit(1); } } } void ReadDataFromFile( char * pszFileName, char * pbBuffer, unsigned long ulBufferSize ) { FILE * pFile; size_t Count; unsigned long ulWrittenSize; if ( pszFileName ) { fopen_s(&pFile, pszFileName, "r+b" ); if ( pFile == NULL ) { printf_s("Cannot open the file for reading\n"); exit(1); } Count = sizeof(long); if ( fread( &ulWrittenSize, sizeof(byte), Count, pFile) != Count ) { printf_s("Cannot read1 from the file\n"); exit(1); } Count = (size_t)ulWrittenSize; if ( fread( pbBuffer, sizeof(byte), Count, pFile) != Count ) { printf_s("Cannot read2 from the file\n"); exit(1); } if ( fclose( pFile ) != 0) { printf_s("Failed to close the file\n"); exit(1); } } } void __cdecl main(int argc, char **argv) { RPC_STATUS status; unsigned char * pbPicklingBuffer = NULL; char * pszStyle = NULL; char * pszFileName = "pickle.dat"; int i; int fEncode = 1; int fFixedStyle = 1; /* allow the user to override settings with command line switches */ for (i = 1; i < argc; i++) { if ((*argv[i] == '-') || (*argv[i] == '/')) { switch (tolower(*(argv[i]+1))) { case 'd': fEncode = 0; break; case 'e': fEncode = 1; break; case 'i': fFixedStyle = 0; break; case 'f': pszFileName = argv[i] + 2; break; case 'h': case '?': default: Usage(argv[0]); } } else Usage(argv[0]); } /* Fixed buffer style: the buffer should be big enough. */ /* Please note that the buffer has to be aligned at 8. */ pbPicklingBuffer = (unsigned char *) midl_user_allocate( BUFSIZE * sizeof(unsigned char)); if ( pbPicklingBuffer == NULL ) { printf_s("Cannot allocate the pickling buffer\n"); exit(1); } else memset( pbPicklingBuffer, 0xdd, BUFSIZE ); /* Set the pickling handle that will be used for data serialization. The global ImplicitPicHandle is used, but it has to be set up. */ if ( fEncode ) { unsigned char * pszNameId; OBJECT1 Object1; OBJECT2 * pObject2; unsigned long ulEncodedSize = 0; printf_s("\nEncoding run: use -d for decoding\n\n"); if ( fFixedStyle ) { printf_s("Creating a fixed buffer encoding handle\n"); status = MesEncodeFixedBufferHandleCreate( pbPicklingBuffer, BUFSIZE, & ulEncodedSize, & ImplicitPicHandle ); printf_s("MesEncodeFixedBufferHandleCreate returned 0x%x\n", status); if (status) { exit(status); } } else { pUserState->LastSize = 0; pUserState->pMemBuffer = (char *)pbPicklingBuffer; pUserState->pBufferStart = (char *)pbPicklingBuffer; printf_s("Creating an incremental encoding handle\n"); status = MesEncodeIncrementalHandleCreate( pUserState, PicAlloc, PicWrite, & ImplicitPicHandle ); printf_s("MesEncodeIncrementalHandleCreate returned 0x%x\n", status); if (status) { exit(status); } } /* Creating objects to manipulate */ pszNameId = "Procedure pickling sample"; for (i = 0; i < ARR_SIZE; i++) Object1.al[i] = 0x37370000 + i; Object1.s = 0x4646; pObject2 = midl_user_allocate( sizeof(OBJECT2) + ARR_SIZE*sizeof(short) ); if (pObject2 == NULL ) { printf_s("Out of memory for Object2\n"); exit(1); } pObject2->sSize = ARR_SIZE; for (i = 0; i < ARR_SIZE; i++) pObject2->as[i] = 0x7700 + i; DumpData( "Data to be encoded", pszNameId, &Object1, pObject2 ); printf_s("\nEncoding all the arguments to the buffer\n\n"); ProcPickle( pszNameId, & Object1, pObject2 ); printf_s("Writing the data to the file: %s\n", pszFileName); WriteDataToFile( pszFileName, pbPicklingBuffer, fFixedStyle ? ulEncodedSize : pUserState->LastSize); midl_user_free( pObject2 ); } else { char acNameBuffer[50]; OBJECT1 Object1; OBJECT2 * pObject2; printf_s("\nDecoding run: use -e for encoding\n\n"); printf_s("Reading the data from the file: %s\n\n", pszFileName ); ReadDataFromFile( pszFileName, pbPicklingBuffer, BUFSIZE ); if ( fFixedStyle ) { printf_s("Creating a decoding handle\n"); status = MesDecodeBufferHandleCreate( pbPicklingBuffer, BUFSIZE, & ImplicitPicHandle ); printf_s("MesDecodeFixedBufferHandleCreate returned 0x%x\n", status); if (status) { exit(status); } } else { pUserState->LastSize = 0; pUserState->pMemBuffer = (char *)pbPicklingBuffer; pUserState->pBufferStart = (char *)pbPicklingBuffer; printf_s("Creating an incremental decoding handle\n"); status = MesDecodeIncrementalHandleCreate( pUserState, PicRead, & ImplicitPicHandle ); printf_s("MesDecodeIncrementalHandleCreate returned 0x%x\n", status); if (status) { exit(status); } } /* Creating objects to manipulate */ pObject2 = midl_user_allocate( sizeof(OBJECT2) + ARR_SIZE*sizeof(short)); if (pObject2 == NULL ) { printf_s("Out of memory for Object2\n"); exit(1); } printf_s("\nDecoding all the arguments from the buffer\n"); ProcPickle( acNameBuffer, & Object1, pObject2 ); DumpData( "Decoded data", acNameBuffer, &Object1, pObject2 ); midl_user_free( pObject2 ); } printf_s("\nData serialization done.\n"); midl_user_free( pbPicklingBuffer ); printf_s("\nFreeing the serialization handle.\n"); status = MesHandleFree( ImplicitPicHandle ); printf_s("MesHandleFree returned 0x%x\n", status); exit(0); } // end main() /*********************************************************************/ /* MIDL allocate and free */ /*********************************************************************/ /* A pickling buffer has to be aligned at 8. malloc() doesn't guarantee that, so some gimmick has to be done. */ #define ALIGN_TO8( p) (char *)((ULONG_PTR)((char *)p + 7) & ~7) void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t s) { unsigned char * pcAllocated; unsigned char * pcUserPtr; pcAllocated = (unsigned char *) malloc( s + 15 ); pcUserPtr = ALIGN_TO8( pcAllocated ); if ( pcUserPtr == pcAllocated ) pcUserPtr = pcAllocated + 8; *(pcUserPtr - 1) = (char) (pcUserPtr - pcAllocated); return( pcUserPtr ); } void __RPC_USER MIDL_user_free(void __RPC_FAR *f) { unsigned char * pcAllocated; unsigned char * pcUserPtr; pcUserPtr = (unsigned char *) f; pcAllocated = pcUserPtr - *(pcUserPtr - 1); free( pcAllocated ); } /*********************************************************************/ /* Incremental style helper routines */ /*********************************************************************/ void __RPC_USER PicAlloc( void * pState, char ** ppBuf, unsigned int * pCount ) { /* This routines "allocates" the next part from the preallocated buffer. It could call midl_user_allocate, too. */ PickleControlBlock * pPic = (PickleControlBlock *)pState; if ( (pPic->pMemBuffer - pPic->pBufferStart) + *pCount <= BUFSIZE ) *ppBuf = (char *)pPic->pMemBuffer; else { printf_s(" Buffer too small\n"); exit(1); } } void __RPC_USER PicWrite( void * pState, char * pBuf, unsigned int Count ) { /* This routine just marks how much of the preallocated buffer is used. */ PickleControlBlock * pPic = (PickleControlBlock *)pState; if ( pPic->pMemBuffer != pBuf ) { printf_s(" Buffer poiner corrupted\n"); exit(1); } pPic->pMemBuffer += Count; pPic->LastSize += Count; } void __RPC_USER PicRead( void * pState, char ** ppBuf, unsigned int * pCount ) { /* This routine returns another portion of the preread buffer. */ PickleControlBlock * pPic = (PickleControlBlock *)pState; *ppBuf = (char *)pPic->pMemBuffer; pPic->pMemBuffer += *pCount; } /* end picklpc.c */