📄 os_spec.h
字号:
/****************************************************************************
* *
* cryptlib OS-Specific Defines Header File *
* Copyright Peter Gutmann 1992-2005 *
* *
****************************************************************************/
#ifndef _OSSPEC_DEFINED
#define _OSSPEC_DEFINED
/* To build the static .LIB under Win32, uncomment the following define (this
it not recommended since the init/shutdown is no longer completely thread-
safe). In theory it should be possible to detect the build of a DLL vs.a
LIB with the _DLL define which is set when the /MD (multithreaded DLL)
option is used, however VC++ only defines _DLL when /MD is used *and*
it's linked with the MT DLL runtime. If it's linked with the statically
linked runtime, _DLL isn't defined, which would result in the unsafe LIB
version being built as a DLL */
/* #define STATIC_LIB */
/* os_spec.h performs OS and compiler detection that's used by config.h, so
this file must be applied before config.h */
#ifdef _CONFIG_DEFINED
#error "os_spec.h must be included before config.h"
#endif /* _CONFIG_DEFINED */
/****************************************************************************
* *
* OS Detection *
* *
****************************************************************************/
/* Try and figure out if we're running under Windows and Win16/Win32/WinCE.
We have to jump through all sorts of hoops later on, not helped by the
fact that the method of detecting Windows at compile time changes with
different versions of Visual C (it's different for each of VC 2.0, 2.1,
4.0, and 4.1. It actually remains the same after 4.1) */
#if !defined( __WINDOWS__ ) && ( defined( _Windows ) || defined( _WINDOWS ) )
#define __WINDOWS__
#endif /* Win16 */
#if !defined( __WIN32__ ) && ( defined( WIN32 ) || defined( _WIN32 ) )
#ifndef __WINDOWS__
#define __WINDOWS__ /* Win32 or WinCE */
#endif /* __WINDOWS__ */
#ifdef _WIN32_WCE
#define __WINCE__
#else
#define __WIN32__
#endif /* WinCE vs. Win32 */
#endif /* Win32 or WinCE */
#if defined( __WINDOWS__ ) && \
!( defined( __WIN32__ ) || defined( __WINCE__ ) )
#define __WIN16__
#endif /* Windows without Win32 or WinCE */
/* If we're using a DOS compiler and it's not a 32-bit one, record this.
__MSDOS__ is predefined by a number of compilers, so we use __MSDOS16__
for stuff that's 16-bit DOS specific, and __MSDOS32__ for stuff that's
32-bit DOS specific */
#if defined( __MSDOS__ ) && !defined( __MSDOS32__ )
#define __MSDOS16__
#endif /* 16-bit DOS */
/* Make the Tandem, Macintosh, AS/400, and PalmOS defines look a bit more
like the usual ANSI defines used to identify the other OS types */
#ifdef __TANDEM
#if defined( _OSS_TARGET )
#define __TANDEM_OSS__
#elif defined( _GUARDIAN_TARGET )
#define __TANDEM_NSK__
#else
#error "Can't determine Tandem OS target type (NSK or OSS)"
#endif /* Tandem OSS vs. NSK */
#endif /* Tandem */
#if defined( __MWERKS__ ) || defined( SYMANTEC_C ) || defined( __MRC__ )
#define __MAC__
#endif /* Macintosh */
#if defined( __OS400__ ) || defined( __ILEC400__ )
#define __AS400__
#endif /* AS/400 */
#ifdef __PALMSOURCE__
#define __PALMOS__
#endif /* Palm OS */
/* In some cases we're using a DOS or Windows system as a cross-development
platform, if we are we add extra defines to turn off some Windows-
specific features */
#ifdef _SCCTK
#define __IBM4758__
#endif /* IBM 4758 cross-compiled under Windows */
/****************************************************************************
* *
* OS-Specific Compiler Configuration *
* *
****************************************************************************/
/* If we're compiling under VC++ with the maximum level of warnings, turn
off some of the more irritating warnings */
#if defined( _MSC_VER )
/* Warning level 3 */
#pragma warning( disable: 4018 ) /* Comparing signed <-> unsigned value */
#pragma warning( disable: 4127 ) /* Conditional is constant: while( TRUE ) */
/* Warning level 4. The function <-> data pointer cast warnings are
orthogonal and impossible to disable (they override the universal
'void *' pointer type), the signed/unsigned and size warnings are
more compiler peeves as for the level 3 warnings, and the struct
initialisation warnings are standards extensions that the struct
STATIC_INIT macros manage for us */
#pragma warning( disable: 4054 ) /* Cast from fn.ptr -> generic (data) ptr.*/
#pragma warning( disable: 4055 ) /* Cast from generic (data) ptr. -> fn.ptr.*/
#pragma warning( disable: 4057 ) /* char vs.unsigned char use */
#pragma warning( disable: 4204 ) /* Struct initialised with non-const value */
#pragma warning( disable: 4221 ) /* Struct initialised with addr.of auto.var */
#pragma warning( disable: 4244 ) /* int <-> unsigned char/short */
#pragma warning( disable: 4245 ) /* int <-> unsigned long */
/* gcc -wall type warnings. The highest warning level generates large
numbers of spurious warnings (including ones in VC++ headers), so it's
best to only enable them for one-off test builds requiring manual
checking for real errors. The used-before-initialised is particularly
common during the code generation phase, when the compiler flags all
values initialised in conditional code blocks as potential problems */
#if 1
#pragma warning( disable: 4100 ) /* Unreferenced parameter */
#pragma warning( disable: 4201 ) /* Nameless struct/union in VC++ header */
#pragma warning( disable: 4701 ) /* Variable used before initialised */
#endif /* 1 */
#endif /* Visual C++ */
/* All Windows CE functions are Unicode-only, this was an attempt to clean
up the ASCII vs. Unicode kludges in Win32 but unfortunately was made just
before UTF8 took off. Because UTF8 allows everyone to keep using their
old ASCII stuff while being nominally Unicode-aware, it's unlikely that
any new Unicode-only systems will appear in the future, leaving WinCE's
Unicode-only API an orphan. The easiest way to handle this is to convert
all strings to ASCII/8 bit as they come in from the external cryptlib API
and convert them back to Unicode as required when they're passed to WinCE
OS functions. In other words Unicode is treated just like EBCDIC and
pushed out to the edges of cryptlib. This requires the minimum amount of
conversion and special-case handling internally */
#ifdef __WINCE__
#define UNICODE_CHARS
#endif /* WinCE */
/* If we're compiling on the AS/400, make enums a fixed size rather than
using the variable-length values that IBM compilers default to, and force
strings into a read-only segment (by default they're writeable) */
#ifdef __AS400__
#pragma enumsize( 4 )
#pragma strings( readonly )
#define EBCDIC_CHARS
#endif /* AS/400 */
/* If we're compiling under MVS or VM/CMS, make enums a fixed size rather
than using the variable-length values that IBM compilers default to */
#if defined( __MVS__ ) || defined( __VMCMS__ )
#pragma enum( 4 )
#define USE_ETOA /* Use built-in ASCII <-> EBCDIC conversion */
#define EBCDIC_CHARS
#endif /* __MVS__ */
/* If we're compiling under QNX, make enums a fixed size rather than using
the variable-length values that the Watcom compiler defaults to */
#if defined( __QNX__ ) && defined( __WATCOMC__ )
#pragma enum int
#endif /* QNX and Watcom C */
/* PalmOS is a bit more picky than other OSes about what has to be in which
header, in particular shared data segments can't be easily exported from
libraries so the isXYZ() macros (which use lookup tables) that are
generally available elsewhere have to be explicitly enabled via ctype.h,
and the native strcpy()/memcpy() used by most compilers may not be
available in some cases either so we have to explicitly pull them in via
string.h */
#ifdef __PALMOS__
#include <ctype.h>
#include <string.h>
#endif /* __PALMOS__ */
/* Some encryption algorithms that rely on longints having 32 bits won't
work on 64- or 128-bit machines due to problems with sign extension and
whatnot. The following define can be used to enable special handling for
processors with a > 32 bit word size */
#include <limits.h>
#if ULONG_MAX > 0xFFFFFFFFUL
#define _BIG_WORDS
#endif /* 64-bit system */
/* Useful data types */
typedef unsigned char BYTE;
#if defined( __WIN32__ ) || defined( __WINCE__ )
#define BOOLEAN int
#else
typedef int BOOLEAN;
#endif /* __WIN32__ || __WINCE__ */
/* If we're building the Win32 kernel driver version, include the DDK
headers */
#if defined( __WIN32__ ) && defined( NT_DRIVER )
#include <ntddk.h>
#endif /* NT kernel driver */
/* In 16-bit environments the BSS data is large enough that it overflows the
(64K) BSS segment. Because of this we move as much of it as possible into
its own segment with the following define */
#if defined( __WIN16__ )
#define FAR_BSS far
#else
#define FAR_BSS
#endif /* 16-bit systems */
/* If we're using DOS or Windows as a cross-development platform, we need
the OS-specific values defined initially to get the types right but don't
want it defined later on since the target platform won't really be
running DOS or Windows, so we undefine them after the types have been
sorted out */
#ifdef __IBM4758__
#undef __MSDOS__
#undef __WINDOWS__
#undef __WIN32__
#endif /* IBM 4758 */
/* Some systems (typically 16-bit or embedded ones) have rather limited
amounts of memory available, if we're building on one of these we limit
the size of some of the buffers that we use */
#if defined( __MSDOS16__ ) || defined( __uClinux__ )
#define CONFIG_CONSERVE_MEMORY
#endif /* Memory-starved systems */
/* Win32 consists of Win95/98/ME and WinNT/2000/XP, Win95 doesn't have a
number of the functions and services that exist in NT so we need to adapt
the code based on the Win32 variant. The following flag records which OS
variant we're crawling under */
#ifdef __WIN32__
extern BOOLEAN isWin95;
#endif /* Win32 */
/* Since the Win32 randomness-gathering uses a background randomness polling
thread, we can't build a Win32 version with NO_THREADS */
#if defined( __WIN32__ ) && defined( NO_THREADS )
#error The Win32 version of cryptlib must have threading enabled
#endif /* Win32 without threading */
/* Boolean constants */
#ifndef TRUE
#define FALSE 0
#define TRUE !FALSE
#endif /* Boolean values */
/* cryptlib contains a few forward declarations for static data. Compiler
opinions on this vary. Some compile it as is, some don't allow the
'static', some allow both variants, and some produce warnings with both
but allow them anyway (there are probably more variants with further
compilers). To get around this, we use the following define and then
vary it for broken compilers (the following is the minimum required to
get it to compile, other broken compilers will still produce warnings) */
#if ( defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) ) || \
defined( __VMCMS__ ) || defined( __MVS__ ) || defined( __MRC__ ) || \
defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \
( defined( __UNIX__ ) && defined( _MPRAS ) )
#define STATIC_DATA
#else
#define STATIC_DATA static
#endif /* Fn.prototyping workarounds for borken compilers */
/* A few compilers won't allow initialisation of a struct at runtime, so
we have to kludge the init with macros. This is rather ugly since
instead of saying "struct = { a, b, c }" we have to set each field
individually by name. The real reason for doing this though is that
if the compiler can initialise the struct directly, we can make the
fields const for better usage checking by the compiler.
There are two forms of this, one for simple structs and one for arrays
of structs. At the moment the only use for the array-init is for the
situation where the array represents a sequence of search options with
the last one being a terminator entry, so we provide a simplified form
that only sets the required fields */
#if ( defined( __hpux ) && !defined( __GNUC__ ) ) || \
( defined( __QNX__ ) && ( OSVERSION <= 4 ) ) || \
defined( __SUNPRO_C ) || defined( __SCO_VERSION__ ) || \
defined( _CRAY )
#define CONST_INIT
#define CONST_INIT_STRUCT_3( decl, init1, init2, init3 ) \
decl
#define CONST_INIT_STRUCT_4( decl, init1, init2, init3, init4 ) \
decl
#define CONST_INIT_STRUCT_5( decl, init1, init2, init3, init4, init5 ) \
decl
#define CONST_SET_STRUCT( init ) \
init
#define CONST_INIT_STRUCT_A2( decl, init1, init2 ) \
decl
#define CONST_SET_STRUCT_A( init ) \
init
#else
#define CONST_INIT const
#define CONST_INIT_STRUCT_3( decl, init1, init2, init3 ) \
decl = { init1, init2, init3 }
#define CONST_INIT_STRUCT_4( decl, init1, init2, init3, init4 ) \
decl = { init1, init2, init3, init4 }
#define CONST_INIT_STRUCT_5( decl, init1, init2, init3, init4, init5 ) \
decl = { init1, init2, init3, init4, init5 }
#define CONST_SET_STRUCT( init )
#define CONST_INIT_STRUCT_A2( decl, init1, init2 ) \
const decl = { { init1, 0 }, { init2, 0 } }
#define CONST_SET_STRUCT_A( init )
#endif /* Watcom C || SunPro C || SCO C */
/* gcc provides extra parameter checking for printf-like functions, which
we enable for the extended-return functions */
#ifdef __GNUC__
#define PRINTF_FN __attribute__ (( format( printf, 3, 4 ) ))
#define PRINTF_FN_EX __attribute__ (( format( printf, 4, 5 ) ))
#else
#define PRINTF_FN
#define PRINTF_FN_EX
#endif /* gcc */
/* The Tandem mktime() is broken and can't convert dates beyond 2023, so we
replace it with our own version which can */
#if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )
#define mktime my_mktime
#endif /* __TANDEM_NSK__ || __TANDEM_OSS__ */
/* Support for vsnprintf() (used for assembling the
CRYPT_ATTRIBUTE_INT_ERRORMESSAGE value) is a bit hit-and-miss on non-Unix
systems and also on older Unixen, if it's not available we alias it to
vsprintf() */
#if defined( __ITRON__ ) || \
defined( __UNIX__ ) && \
( ( defined( __SCO_VERSION__ ) && OSVERSION < 5 ) || \
( defined( sun ) && OSVERSION < 5 ) || \
defined( __SYMBIAN32__ ) )
#define vsnprintf( buf, count, format, arg ) vsprintf( buf, format, arg )
#elif defined( __WINDOWS__ )
/* Microsoft provides vsnprintf() in all VC++ and eVC++ libraries, but
it's given as _vsnprintf() since it's not an ANSI/ISO C (pre-C99)
function */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -