459 lines
13 KiB
C
459 lines
13 KiB
C
// 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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#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 */
|
|
|
|
|