📄 udcfgbin.c
字号:
/* $Header: "%n Ver=%v %f LastEdit=%w Locker=%l" */
/* "UDCFGBIN.C Ver=2 20-Nov-97,17:36:02 LastEdit=JIMV Locker=***_NOBODY_***" */
/***********************************************************************\
* *
* Copyright Wonderware Software Development Corp. 1992-1997 *
* *
* ThisFileName="L:\ww\dde_serv\src\udsample\udcfgbin.c" *
* LastEditDate="1997 Nov 20 17:36:00" *
* *
\***********************************************************************/
/****************************************************************************\
These routines support reading and writing CFG files as binary structures
\****************************************************************************/
#include <windows.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stat.h>
#include "ntconv.h"
#include "hmemcpy.h"
#include "chainmgr.h"
#include "config.h"
#include "uddefs.h"
/***********************************************************************\
The routines in this section support storing and scanning a server
configuration file in the form of binary structures. Writing and
reading such structures is easy, although there are a few caveats.
1. When the binary image of a configuration structure is read from
or written to a file, differences can arise regarding alignment
and packing. This is an issue for Windows NT, where words must
be on even boundaries and longwords must be on longword (i.e.
multiple of 4) boundaries. Structure members may be in a different
order than specified, and there may be padding between the members.
One approach is to design the configuration structure to match
these requirements. However, the approach used here is less
susceptible to mistakes in alignment when a structure is changed.
Each individual structure member of the configuration item is
read from or written to the disk file, instead of transferring
the entire structure in a single block. Since this could lead
to major inefficiencies in disk access, a buffered file approach
is used, where blocks of a fixed size are transferred from and
to the disk, and the individual items are read or written using
the buffers. The BUFFERED_FILE structure and routines make this
buffering and flushing transparent to the programmer.
2. If the configuration structures change, the functions for
reading and writing those structures must also be updated.
In addition, for backward compatibility, the routines for reading
the structures should also be able to READ previous versions of
those structures, then convert the configuration to the new format.
When such a format change is made, the VERSION of the CFG file
should be updated, and functions such as ReadTopicCfgStruct()
and ReadBoardCfgStruct() should check the version of the file
that is being READ and use the corresponding format for input.
Once the old-format structure has been read in, the function
should then convert it to the current format -- either directly
or by daisy-chaining intermediate stages of conversion.
Handling changes to the VERSION of the CFG file saves the user
a lot of trouble; but it can be something of a software maintenance
headache. One way to reduce this maintenance problem is to use
routines that read and write CFG files in ASCII text format.
\***********************************************************************/
/********************************************************************
* External Variables *
********************************************************************/
extern BOOL bUsesComPorts; /* =TRUE if ComPorts are used */
extern BOOL bUsesBoards; /* =TRUE if Boards are used */
extern WW_CP_PARAMS comPort[]; /* array of comport configurations */
extern CHAIN BoardCfgList; /* linked list of board configurations */
extern CHAIN TopicCfgList; /* linked list of topic configurations */
/********************************************************************
* Prototypes *
********************************************************************/
static BOOL WINAPI ReadPortCfgStruct ( BUFFERED_FILE *SourceFile,
LPWW_CP_PARAMS lpCpParams, long lVersion );
static BOOL WINAPI ReadBoardCfgStruct( BUFFERED_FILE *SourceFile,
LPBOARD_CFG lpBoardCfg, long lVersion );
static BOOL WINAPI ReadTopicCfgStruct( BUFFERED_FILE *SourceFile,
LPTOPIC_CFG lpTopicCfg, long lVersion );
static BOOL WINAPI WritePortCfgStruct ( BUFFERED_FILE *DestFile, LPWW_CP_PARAMS lpCpParams );
static BOOL WINAPI WriteBoardCfgStruct( BUFFERED_FILE *DestFile, LPBOARD_CFG lpBoardCfg );
static BOOL WINAPI WriteTopicCfgStruct( BUFFERED_FILE *DestFile, LPTOPIC_CFG lpTopicCfg );
static UINT WINAPI ConvertOldBaud ( int iOldBaud );
static UINT WINAPI ConvertOldParity ( int iOldParity );
static UINT WINAPI ConvertOldStopbits ( int iOldStopbits );
/***********************************************************************
***********************************************************************
* Routines for reading CFG files as binary structures *
***********************************************************************
***********************************************************************/
/***********************************************************************/
/** read configuration from file as binary structures
return TRUE if successful **/
BOOL
WINAPI
ReadConfigsStruct (BUFFERED_FILE *SourceFile, long lVersion)
{
BOOL ok;
int i;
WORD bAnyMore;
BOARD_CFG BoardCfg;
LPBOARD_CFG lpBoardCfg;
TOPIC_CFG TopicCfg;
LPTOPIC_CFG lpTopicCfg;
/* initialize return value */
ok = TRUE;
if (bUsesComPorts) {
/* read the first 4 com ports first (old style) */
for( i=1; ok && (i<=4); i++) {
ok = ReadPortCfgStruct( SourceFile, &comPort[i-1], lVersion );
}
}
/* read the boards first */
if (bUsesBoards) {
if( ok ) {
do {
/* check whether any more boards are in file */
ok = ReadNextAnyMore( SourceFile, &bAnyMore );
if (ok && bAnyMore) {
/* read board structure from file */
ok = ReadBoardCfgStruct( SourceFile, (LPBOARD_CFG) &BoardCfg, lVersion );
if( ok ) {
/* create structure for new board */
lpBoardCfg = BoardCfgAlloc();
if (lpBoardCfg == (LPBOARD_CFG) NULL) {
ok = FALSE;
break;
}
/* copy board settings into structure */
*lpBoardCfg = BoardCfg;
/* add board to list */
BoardCfgAddToList( lpBoardCfg );
}
}
} while (ok && bAnyMore);
} /* end if - ok */
}
/* read the topics next */
if (ok) {
do {
/* check whether any more topics are in file */
ok = ReadNextAnyMore( SourceFile, &bAnyMore );
if (ok && bAnyMore) {
/* read topic structure from file */
ok = ReadTopicCfgStruct( SourceFile, (LPTOPIC_CFG) &TopicCfg, lVersion );
if( ok ) {
/* create structure for new topic */
lpTopicCfg = TopicCfgAlloc();
if (lpTopicCfg == (LPTOPIC_CFG) NULL) {
ok = FALSE;
break;
}
/* copy topic settings to structure */
*lpTopicCfg = TopicCfg;
/* add topic to list */
TopicCfgAddToList(lpTopicCfg);
}
}
} while (ok && bAnyMore);
} /* end if - ok */
if (bUsesComPorts) {
/* now read in ports 5 thru MAX_COMPORT, if they exist */
if ( ok && ReadNextAnyMore( SourceFile, &bAnyMore ) ) {
for ( i = 5; ok && bAnyMore && (i <= MAX_COMPORT); i++ ) {
ok = ReadPortCfgStruct( SourceFile, &comPort[i-1], lVersion );
if( ok ) {
ok = ReadNextAnyMore( SourceFile, &bAnyMore );
}
}
} /* end if - ok */
}
/* indicate success or failure */
return (ok);
} /* ReadConfigsStruct */
/***********************************************************************/
/* read the config COM port structure as a binary image;
return TRUE if successful */
static
BOOL
WINAPI
ReadPortCfgStruct( BUFFERED_FILE *SourceFile,
LPWW_CP_PARAMS lpCpParams,
long lVersion )
{
WW_CP_PARAMS vcur;
BOOL ok;
/* define version 1 config file port record structure */
typedef struct {
char cp_name[6];
short cp_baud;
short cp_stop;
short cp_parity;
short cp_replyTimeout;
} VER1_COMPORT_CFG;
/* initialize return value */
ok = TRUE;
/* handle according to version of configuration file */
switch( lVersion ) {
case 1: /* version 1 */
{
VER1_COMPORT_CFG v1;
/* clear contents of memory structure */
memset (&v1, 0, sizeof(v1));
/* attempt to read version 1 structure from file */
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_name, sizeof(v1.cp_name));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_baud, sizeof(v1.cp_baud));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_stop, sizeof(v1.cp_stop));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_parity, sizeof(v1.cp_parity));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_replyTimeout, sizeof(v1.cp_replyTimeout));
/* convert version 1 structure to current version */
SetupDefaultPortCfgParams (&vcur);
vcur.uBaud = ConvertOldBaud (v1.cp_baud);
vcur.uStopBits = ConvertOldStopbits (v1.cp_stop);
vcur.uParity = ConvertOldParity (v1.cp_parity);
vcur.uReplyTimeout = v1.cp_replyTimeout;
/* return contents of structure */
*lpCpParams = vcur;
break;
}
default: /* current version */
/* clear contents of memory structure */
memset (&vcur, 0, sizeof(vcur));
/* attempt to read current version structure from file */
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &vcur, sizeof(vcur));
/** Note: The WW_CP_PARAMS structure happens to be identically
aligned on both Win16 and Win32 platforms, so direct reads
and writes of the entire structure are OK. **/
/* return contents of structure */
*lpCpParams = vcur;
break;
} /* switch */
/* indicate success or failure */
return (ok);
} /* ReadPortCfgStruct */
/***********************************************************************/
/* read the config BOARD_CFG structure as a binary image;
return TRUE if successful */
static
BOOL
WINAPI
ReadBoardCfgStruct( BUFFERED_FILE *SourceFile,
LPBOARD_CFG lpBoardCfg,
long lVersion )
{
BOARD_CFG vcur;
BOOL ok;
/* define version 1 config file board record structure */
typedef struct {
void FAR *cp_next;
DWORD cp_channelID;
char cp_name[33];
WORD cp_memSegment;
WORD cp_ioAddr;
short cp_replyTimeout;
} VER1_BOARD_CFG;
/* initialize return value */
ok = TRUE;
/* handle according to version of configuration file */
switch( lVersion ) {
case 1: /* version 1 */
{
VER1_BOARD_CFG v1;
/* clear contents of memory structure */
memset (&v1, 0, sizeof(v1));
/* attempt to read version 1 structure from file */
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_next, sizeof(v1.cp_next));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_channelID, sizeof(v1.cp_channelID));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_name[0], sizeof(v1.cp_name));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_memSegment, sizeof(v1.cp_memSegment));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_ioAddr, sizeof(v1.cp_ioAddr));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &v1.cp_replyTimeout, sizeof(v1.cp_replyTimeout));
/* convert version 1 structure to current version */
memset (&vcur, 0, sizeof(vcur));
vcur.cp_channelID = v1.cp_channelID;
strncpy (vcur.cp_name, v1.cp_name, sizeof(vcur.cp_name)-1);
vcur.cp_replyTimeout = v1.cp_replyTimeout;
vcur.cp_memSegment = v1.cp_memSegment;
vcur.cp_ioAddr = v1.cp_ioAddr;
/* return contents of structure */
*lpBoardCfg = vcur;
break;
}
default: /* current version */
/* clear contents of memory structure */
memset (&vcur, 0, sizeof(vcur));
/* attempt to read current version structure from file */
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &vcur.cp_chainLink, sizeof(vcur.cp_chainLink));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &vcur.cp_channelID, sizeof(vcur.cp_channelID));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &vcur.cp_name, sizeof(vcur.cp_name));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &vcur.cp_memSegment, sizeof(vcur.cp_memSegment));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &vcur.cp_ioAddr, sizeof(vcur.cp_ioAddr));
if (ok)
ok = ReadNextBuffer( SourceFile, (char *) &vcur.cp_replyTimeout, sizeof(vcur.cp_replyTimeout));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -