Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2550 lines
98 KiB

//____________________________________________________________________________
//
// (C) Copyright Seagate Software, Inc. 1994-1996
// © 1998 Seagate Software, Inc. All rights reserved.
//
// All Rights Reserved Worldwide.
//
//____________________________________________________________________________
//
// FILE NAME : mtf_api.c
//
// DESCRIPTION : mtf api implementation
//
// CREATED: 6/20/95
//
//____________________________________________________________________________
//
// $Revision: 1.35 $
// $Date: 02 Feb 1995 15:47:04 $
// $Modtime: 02 Feb 1995 15:37:38 $
//
//____________________________________________________________________________
// *****************************************************************************/
#include <assert.h>
#include <time.h>
#include <string.h>
#include <wchar.h>
#include "mtf_api.h"
/***********************************************************************************
************************************************************************************
************************************************************************************
**** MTF API Static Data Structures and Housekeeping
************************************************************************************
************************************************************************************
***********************************************************************************/
// see below
static UINT16 s_uAlignmentFactor = 0;
static size_t Align(size_t uSize, size_t uAlignment);
// when the api formats it's own strings (i.e. file names from the WIN32_FIND_DATA,
// we need to keep those strings somewhere so we can set the pointers to them in
// the info structs.
#define STRLEN 256
static wchar_t s_szDeviceName[STRLEN];
static wchar_t s_szVolumeName[STRLEN];
static wchar_t s_szMachineName[MAX_COMPUTERNAME_LENGTH+1];
static wchar_t s_szDirectoryName[STRLEN];
static wchar_t s_szFileName[STRLEN];
/* ==================================================================================
String Management
When reading blocks, the strings are not null terminated -- we would like to
pull them out and deliver them back in the ####_INFO structures in a civilized
(null terminated) way. Thus, just set up an array of malloc'ec strings.
Each call that uses strings should first call "ClearStrings" -- strings returned
to the user will only be good up until the next call...
================================================================================= */
#define iNUMSTRINGS 5
static wchar_t *s_aszStrings[iNUMSTRINGS] = {0}; // we keep an array of pointers to allocated strings
// this managed by ClearStrings() and MakeString()
static int s_iNumStrings = 0; // the number of strings currently allocated
// - returns the size of a wchar_t string
// and returns zero for a null pointer
static size_t wstrsize(wchar_t *s)
{
if (s)
return wcslen(s) * sizeof(wchar_t);
else
return 0;
}
// - frees all allocated pointers in s_aszStrings and sets
// s_iNumStrings to zero
static void ClearStrings()
{
int i;
for (i = 0; i < iNUMSTRINGS; ++i)
{
if (s_aszStrings[i])
free(s_aszStrings[i]);
s_aszStrings[i] = 0;
}
s_iNumStrings = 0;
}
// - allocates a string in s_aszStrings that is a copy of pString
// (pString need not be null terminated)
// (note -- iSize is the size of the string in bytes -- not the length!!!!!
static wchar_t * MakeString(wchar_t * pString, size_t iSize)
{
size_t i;
assert(s_iNumStrings < iNUMSTRINGS);
s_aszStrings[s_iNumStrings] = malloc(iSize + sizeof(wchar_t));
if (!s_aszStrings[s_iNumStrings])
return NULL;
for (i = 0; i < iSize / sizeof(wchar_t); ++i)
s_aszStrings[s_iNumStrings][i] = pString[i];
s_aszStrings[s_iNumStrings][i] = L'\0';
return s_aszStrings[s_iNumStrings++];
}
/* ==================================================================================
Other static data structures
================================================================================= */
#pragma pack(1)
/***********************************************************************************
************************************************************************************
************************************************************************************
**** MTF On Tape Structures
************************************************************************************
************************************************************************************
***********************************************************************************/
/* ==================================================================================
Tape Address
================================================================================== */
typedef struct {
UINT16 uSize; /* Size of the data */
UINT16 uOffset; /* Offset to the data */
} MTF_TAPE_ADDRESS;
/* ==================================================================================
Common DBLK Header
- The common dblk header exactly as it appears on tape in the head of the dblks
================================================================================== */
typedef struct {
UINT8 acBlockType[4]; /* 00h Unique identifier, see above */
UINT32 uBlockAttributes; /* 04h Common attributes for this block */
UINT16 uOffsetToFirstStream; /* 08h Offset to data associated with this */
/* DBLK, or offset to next DBLK or */
/* filemark if there is no associated */
/* data. */
UINT8 uOSID; /* 0Ah Machine/OS id where written, low byte */
UINT8 uOSVersion; /* 0Bh Machine/OS id where written, high byte */
UINT64 uDisplayableSize; /* 0Ch Displayable data size */
UINT64 uFormatLogicalAddress; /* 14h Logical blk address relative to SSET */
UINT16 uReservedForMBC; /* 1Ch Reserved for Media Based Catalog */
UINT16 uSoftwareCompression; /* 1Eh Software Compression Algorithm ***/
UINT8 acReserved1[4]; /* 20h reserved */
UINT32 uControlBlockId; /* 24h Used for error recovery */
UINT8 acReserved2[4]; /* 28h reserved */
MTF_TAPE_ADDRESS sOSSpecificData; /* 2Ch Size and offset of OS specific stuff */
UINT8 uStringType; /* 30h ASCII, Unicode, etc. */
UINT8 uReserved3; /* 31h for alignment purposes */
UINT16 uHeaderCheckSum; /* 32h Checksum of the block header. The */
/* algorithm is: XOR each word preceeding */
/* this one and store the result here. */
/* (When the checksum is verified the */
/* 'block_type' is also checked for a */
/* non-zero value. */
} MTF_DBLK_HDR;
/* ==================================================================================
DBLK TAPE Header
- The TAPE DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR)
================================================================================== */
typedef struct { /* MTF_DBLK_TAPE */
MTF_DBLK_HDR sBlockHeader;
UINT32 uTapeFamilyId;
UINT32 uTapeAttributes;
UINT16 uTapeSequenceNumber;
UINT16 uPasswordEncryptionAlgorithm;
UINT16 uSoftFilemarkBlockSize; /* Or ECC Algorithm */
UINT16 uTapeCatalogType;
MTF_TAPE_ADDRESS sTapeName;
MTF_TAPE_ADDRESS sTapeDescription;
MTF_TAPE_ADDRESS sTapePassword;
MTF_TAPE_ADDRESS sSoftware_name;
UINT16 uAlignmentFactor;
UINT16 uSoftwareVendorId;
MTF_DATE_TIME sTapeDate;
UINT8 uMTFMajorVersion;
} MTF_DBLK_TAPE;
/* ==================================================================================
Start of Set DBLK (SSET)
- The SSET DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR)
================================================================================== */
typedef struct {
MTF_DBLK_HDR sBlockHeader;
UINT32 uSSETAttributes;
UINT16 uPasswordEncryptionAlgorithm;
UINT16 uDataEncryptionAlgorithm; /* Or Software Compression Algorithm ***/
UINT16 uSoftwareVendorId;
UINT16 uDataSetNumber;
MTF_TAPE_ADDRESS sDataSetName;
MTF_TAPE_ADDRESS sDataSetDescription;
MTF_TAPE_ADDRESS sDataSetPassword;
MTF_TAPE_ADDRESS sUserName;
UINT64 uPhysicalBlockAddress;
MTF_DATE_TIME sMediaWriteDate;
UINT8 uSoftwareVerMjr;
UINT8 uSoftwareVerMnr;
UINT8 uTimeZone;
UINT8 uMTFMinorVer;
UINT8 uTapeCatalogVersion;
} MTF_DBLK_SSET;
/* ==================================================================================
Volume DBLK (VOLB)
- The VOLB DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR)
================================================================================== */
typedef struct {
MTF_DBLK_HDR sBlockHeader;
UINT32 uVolumeAttributes;
MTF_TAPE_ADDRESS sDeviceName;
MTF_TAPE_ADDRESS sVolumeName;
MTF_TAPE_ADDRESS sMachineName;
MTF_DATE_TIME sMediaWriteDate;
} MTF_DBLK_VOLB;
/* ==================================================================================
Directory DBLK (DIRB)
- The DIRB DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR)
================================================================================== */
typedef struct {
MTF_DBLK_HDR sBlockHeader;
UINT32 uDirectoryAttributes;
MTF_DATE_TIME sLastModificationDate;
MTF_DATE_TIME sCreationDate;
MTF_DATE_TIME sBackupDate;
MTF_DATE_TIME sLastAccessDate;
UINT32 uDirectoryId;
MTF_TAPE_ADDRESS sDirectoryName;
} MTF_DBLK_DIRB;
/* ==================================================================================
Directory DBLK (FILE)
- The FILE DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR)
================================================================================== */
typedef struct {
MTF_DBLK_HDR sBlockHeader;
UINT32 uFileAttributes;
MTF_DATE_TIME sLastModificationDate;
MTF_DATE_TIME sCreationDate;
MTF_DATE_TIME sBackupDate;
MTF_DATE_TIME sLastAccessDate;
UINT32 uDirectoryId;
UINT32 uFileId;
MTF_TAPE_ADDRESS sFileName;
} MTF_DBLK_FILE;
#pragma pack()
/* ==================================================================================
Corrupt File DBLK (CFIL)
- use MTF_DBLK_CFIL_INFO -- same structure
================================================================================== */
typedef MTF_DBLK_CFIL_INFO MTF_DBLK_CFIL;
/* ==================================================================================
End of Set Pad Block (ESPB)
================================================================================== */
// consists only of header
/* ==================================================================================
End of Set Block (ESET)
- use MTF_DBLK_ESET_INFO -- same structure
================================================================================== */
typedef MTF_DBLK_ESET_INFO MTF_DBLK_ESET;
/* ==================================================================================
End of Set Block (EOTM)
- use MTF_DBLK_EOTM_INFO -- same structure
================================================================================== */
typedef MTF_DBLK_EOTM_INFO MTF_DBLK_EOTM;
/* ==================================================================================
Soft Filemark (SFMB)
- use MTF_DBLK_SFMB_INFO -- same structure
================================================================================== */
typedef MTF_DBLK_SFMB_INFO MTF_DBLK_SFMB;
/* ==================================================================================
StreamHeader
- use MTF_STREAM_INFO -- same structure
================================================================================== */
typedef MTF_STREAM_INFO MTF_STREAM;
/***********************************************************************************
************************************************************************************
************************************************************************************
**** MTF Misc Data Types
************************************************************************************
************************************************************************************
***********************************************************************************/
/* ==================================================================================
Alignment Factor
================================================================================== */
/***********************************************************************************
* MTF_SetAlignmentFactor()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetAlignmentFactor(UINT16 uAF)
{
// store the user's alignment factor in a static variable
s_uAlignmentFactor = uAF;
}
/***********************************************************************************
* MTF_GetAlignmentFactor()
* ** MTF API FUNCTION **
***********************************************************************************/
UINT16 MTF_GetAlignmentFactor()
{
// make sure an alignment factor was stored,
// and return it
assert(s_uAlignmentFactor != 0);
return s_uAlignmentFactor;
}
/***********************************************************************************
* MTF_PadToNextAlignmentFactor()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_PadToNextAlignmentFactor(
BYTE *pBuffer,
size_t nBufUsed,
size_t nBufferSize,
size_t *pnSizeUsed)
{
size_t i;
size_t nAlignment;
MTF_STREAM_INFO sStream;
// figure out what the next alignment value is and then pad out the user's buffer
// with an SPAD, making sure the buffer is big enough
nAlignment = Align(nBufUsed + sizeof(MTF_STREAM_INFO), MTF_GetAlignmentFactor());
*pnSizeUsed = nAlignment;
if (nBufferSize < nAlignment)
return MTF_ERROR_BUFFER_TOO_SMALL;
MTF_SetSTREAMDefaults(&sStream, "SPAD");
sStream.uStreamLength = MTF_CreateUINT64(nAlignment - nBufUsed - sizeof(MTF_STREAM_INFO), 0);
MTF_WriteStreamHeader(&sStream,
pBuffer + nBufUsed,
nBufferSize - nBufUsed,
0);
for (i = nBufUsed + sizeof(MTF_STREAM_INFO); i < nAlignment; ++i)
pBuffer[i] = 0;
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_PadToNextPhysicalBlockBoundary() - (bmd)
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_PadToNextPhysicalBlockBoundary(
BYTE *pBuffer,
size_t nBlockSize,
size_t nBufUsed,
size_t nBufferSize,
size_t *pnSizeUsed)
{
size_t i;
size_t nAlignment;
MTF_STREAM_INFO sStream;
// figure out what the next alignment value is and then pad out the user's buffer
// with an SPAD, making sure the buffer is big enough
nAlignment = Align(nBufUsed + sizeof(MTF_STREAM_INFO), nBlockSize);
*pnSizeUsed = nAlignment;
if (nBufferSize < nAlignment)
return MTF_ERROR_BUFFER_TOO_SMALL;
MTF_SetSTREAMDefaults(&sStream, "SPAD");
sStream.uStreamLength = MTF_CreateUINT64(nAlignment - nBufUsed - sizeof(MTF_STREAM_INFO), 0);
MTF_WriteStreamHeader(&sStream, pBuffer + nBufUsed, nBufferSize - nBufUsed, 0);
for (i = nBufUsed + sizeof(MTF_STREAM_INFO); i < nAlignment; ++i)
pBuffer[i] = 0;
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_CreateUINT64()
* ** MTF API FUNCTION **
***********************************************************************************/
UINT64 MTF_CreateUINT64(UINT32 uLSB, UINT32 uMSB)
{
UINT64 uRet;
uRet = (UINT64) uMSB << 32;
uRet += uLSB;
return uRet;
}
/* ==================================================================================
Compressed date structure for storing dates in minimal space on tape:
BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4
76543210 76543210 76543210 76543210 76543210
yyyyyyyy yyyyyymm mmdddddh hhhhmmmm mmssssss
33333333 33222222 22221111 11111100 00000000
98765432 10987654 32109876 54321098 76543210
================================================================================== */
/***********************************************************************************
* MTF_CreateDateTime()
* ** MTF API FUNCTION **
***********************************************************************************/
MTF_DATE_TIME MTF_CreateDateTime(
int iYear,
int iMonth,
int iDay,
int iHour,
int iMinute,
int iSecond
)
{
MTF_DATE_TIME sDateTime = {0};
UINT16 temp ;
// pack the date time structure with the arguments as per the diagram above
temp = iYear << 2 ;
sDateTime.dt_field[0] = ((UINT8 *)&temp)[1] ;
sDateTime.dt_field[1] = ((UINT8 *)&temp)[0] ;
temp = iMonth << 6 ;
sDateTime.dt_field[1] |= ((UINT8 *)&temp)[1] ;
sDateTime.dt_field[2] = ((UINT8 *)&temp)[0] ;
temp = iDay << 1 ;
sDateTime.dt_field[2] |= ((UINT8 *)&temp)[0] ;
temp = iHour << 4 ;
sDateTime.dt_field[2] |= ((UINT8 *)&temp)[1] ;
sDateTime.dt_field[3] = ((UINT8 *)&temp)[0] ;
temp = iMinute << 6 ;
sDateTime.dt_field[3] |= ((UINT8 *)&temp)[1] ;
sDateTime.dt_field[4] = ((UINT8 *)&temp)[0] ;
temp = (UINT16)iSecond ;
sDateTime.dt_field[4] |= ((UINT8 *)&temp)[0] ;
return sDateTime;
}
/***********************************************************************************
* MTF_CreateDateTimeFromTM()
* ** MTF API FUNCTION **
***********************************************************************************/
MTF_DATE_TIME MTF_CreateDateTimeFromTM(
struct tm *pT
)
{
// translate call to MTF_CreateDateTime
return MTF_CreateDateTime(pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec);
}
/***********************************************************************************
* MTF_CreateDateTimeToTM()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_CreateDateTimeToTM(
MTF_DATE_TIME *pDT,
struct tm *pT
)
{
UINT8 temp[2] ;
// unpack the MTF_DATE_TIME structure and store the results
temp[0] = pDT->dt_field[1] ;
temp[1] = pDT->dt_field[0] ;
pT->tm_year = *((UINT16 *)temp) >> 2 ;
temp[0] = pDT->dt_field[2] ;
temp[1] = pDT->dt_field[1] ;
pT->tm_mon = (*((UINT16 *)temp) >> 6) & 0x000F ;
pT->tm_mday = (*((UINT16 *)temp) >> 1) & 0x001F ;
temp[0] = pDT->dt_field[3] ;
temp[1] = pDT->dt_field[2] ;
pT->tm_hour = (*((UINT16 *)temp) >> 4) & 0x001F ;
temp[0] = pDT->dt_field[4] ;
temp[1] = pDT->dt_field[3] ;
pT->tm_min = (*((UINT16 *)temp) >> 6) & 0x003F ;
pT->tm_sec = *((UINT16 *)temp) & 0x003F ;
}
/***********************************************************************************
* MTF_CreateDateNull()
* ** MTF API FUNCTION **
***********************************************************************************/
MTF_DATE_TIME MTF_CreateDateNull()
{
MTF_DATE_TIME sDateTime = {0};
return sDateTime;
}
/***********************************************************************************
* MTF_CreateDateTimeFromFileTime()
* ** MTF API FUNCTION **
***********************************************************************************/
MTF_DATE_TIME MTF_CreateDateTimeFromFileTime(
FILETIME sFileTime
)
{
SYSTEMTIME sSystemTime;
FileTimeToSystemTime(&sFileTime, &sSystemTime);
return MTF_CreateDateTime(sSystemTime.wYear,
sSystemTime.wMonth,
sSystemTime.wDay,
sSystemTime.wHour,
sSystemTime.wMinute,
sSystemTime.wSecond);
}
/***********************************************************************************
************************************************************************************
**** MTF static HELPER FUNCITONS
************************************************************************************
***********************************************************************************/
/***********************************************************************************
* StringToTapeAddress()
*
* Description: Used by the MTF_Write#### functions below. Given a Buffer, an
* MTF_TAPE_ADDRESS struct and the current end of the string storage
* area in the buffer, this function appends the string to the string
* storage area, fills in the MTF_TAPE_ADDRESS struct indicating where
* the string was stored and returns the new end of the string storage
* area accounting for the added string.
***********************************************************************************/
static size_t StringToTapeAddress(
MTF_TAPE_ADDRESS *pAd, // the mtf tape address structure to fill
BYTE *pBuffer, // the buffer that is being filled
wchar_t *str, // the string to store MTF style in the buffer
size_t uCurrentStorageOffset // the next available point in the buffer for string storage
)
{
// if we have a string,
// - put the size and offset in the MTF_TAPE_ADDRESS structure and then copy
// the string to the pBuffer at the uCurrentStorageOffset'th byte
// otherwise
// - put a zero size and offset in the MTF_TAPE_ADDRESS struct.
// return the new end of the string storage area
if (str)
{
pAd->uSize = (UINT16)wstrsize(str);
pAd->uOffset = (UINT16)uCurrentStorageOffset;
memcpy(pBuffer + uCurrentStorageOffset, str, pAd->uSize);
uCurrentStorageOffset += pAd->uSize;
}
else
{
pAd->uSize = 0;
pAd->uOffset = 0;
}
return uCurrentStorageOffset;
}
/***********************************************************************************
* Align()
*
* Description: Given uSize and an alignment factor, retuns the value
* of the uSize+ pad, where pad is the value necesary to
* get to the next alignment factor.
*
* Returns uSize + pad -- not just pad!
***********************************************************************************/
static size_t Align(
size_t uSize,
size_t uAlignment)
{
if (uSize % uAlignment)
return uSize - (uSize % uAlignment) + uAlignment;
else
return uSize;
}
/***********************************************************************************
* CalcChecksum()
*
* Description: returns the 16bit XOR sum of the nNum bytes starting at the UINT16
* pointed to by pStartPtr
*
***********************************************************************************/
static UINT16 CalcChecksum(
BYTE * pStartPtr,
int nNum )
{
UINT16 resultSoFar = 0;
UINT16 *pCur = (UINT16 *) pStartPtr;
while( nNum-- )
resultSoFar ^= *pCur++ ;
return( resultSoFar ) ;
}
/***********************************************************************************
* CalcChecksumOfStreamData() - (bmd)
*
* Description: returns the 32bit XOR sum of the nNum bytes starting at the UINT64
* pointed to by pStartPtr
*
***********************************************************************************/
static UINT32 CalcChecksumOfStreamData(
BYTE * pStartPtr,
int nNum )
{
UINT32 resultSoFar = 0;
UINT32 *pCur = (UINT32 *) pStartPtr;
while( nNum-- )
resultSoFar ^= *pCur++ ;
return( resultSoFar ) ;
}
/***********************************************************************************
************************************************************************************
************************************************************************************
**** MTF API STRUCTURE FUNCTIONS
************************************************************************************
************************************************************************************
***********************************************************************************/
/* ==================================================================================
=====================================================================================
Common DBLK: MTF_DBLK_HDR_INFO
=====================================================================================
================================================================================== */
// Calculates the room that will be taken up in the DBLK by strings and OS specific data
static size_t MTF_DBLK_HDR_INFO_CalcAddDataSize(
MTF_DBLK_HDR_INFO *pSTDInfo
)
{
return pSTDInfo->uOSDataSize;
}
/***********************************************************************************
* MTF_SetDblkHdrDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetDblkHdrDefaults(
MTF_DBLK_HDR_INFO * pStdInfo
)
{
int i;
for (i = 0; i < 5; ++i)
pStdInfo->acBlockType[i] = 0;
pStdInfo->uBlockAttributes = 0;
pStdInfo->uOSID = 0;
pStdInfo->uOSVersion = 0;
pStdInfo->uDisplayableSize = 0;
pStdInfo->uFormatLogicalAddress = 0;
pStdInfo->uReservedForMBC = 0;
pStdInfo->uSoftwareCompression = MTF_COMPRESS_NONE;
pStdInfo->uControlBlockId = 0;
pStdInfo->pvOSData = 0;
pStdInfo->uOSDataSize = 0;
pStdInfo->uStringType = MTF_STRING_UNICODE_STR;
}
/***********************************************************************************
* MTF_WriteDblkHdrToBuffer()
*
* Description: called by the MTF_Write#####() functions to format the common block
* header to the buffer
* - this also calculates the header check sum and fills it in
*
* Pre: - *puCurrentStorageOffset is the offset at where string and OS Data storage will
* begin in the buffer
* - the size of the buffer has been checked and can hold any info written to it
*
* Post: - *puCurrentStorageOffset is updated to reflect any added strings or storage
*
***********************************************************************************/
static void MTF_WriteDblkHdrToBuffer(
UINT8 acID[4], // four byte header id to write
UINT16 uOffsetToFirstStream, // the size of the DBLK for which this will be a header
MTF_DBLK_HDR_INFO *psHdrInfo, // the header info struct to use (filled in by client)
BYTE *pBuffer, // the buffer to format to
size_t *puCurrentStorage) // the point in the buffer where string and os data stroage begins
// (this will be updated upon return to reflect added data to storage)
{
MTF_DBLK_HDR *pHDR = 0;
UINT16 uCurrentStorageOffset = 0;
int i;
// - if no *puCurrentStorage, we assume storage starts at
// the end of the on tape MTF_DBLK_HDR structure
if (puCurrentStorage)
uCurrentStorageOffset = (UINT16)*puCurrentStorage;
else
uCurrentStorageOffset = (UINT16)sizeof(MTF_DBLK_HDR);
pHDR = (MTF_DBLK_HDR *) pBuffer;
// write in the four byte DBLK ID
for (i = 0; i < 4; ++i)
pHDR->acBlockType[i] = acID[i];
pHDR->uBlockAttributes = psHdrInfo->uBlockAttributes;
pHDR->uOffsetToFirstStream = uOffsetToFirstStream;
pHDR->uOSID = psHdrInfo->uOSID;
pHDR->uOSVersion = psHdrInfo->uOSVersion;
pHDR->uDisplayableSize = psHdrInfo->uDisplayableSize;
pHDR->uFormatLogicalAddress = psHdrInfo->uFormatLogicalAddress;
pHDR->uReservedForMBC = 0; // must be zero in backup set
pHDR->uSoftwareCompression = psHdrInfo->uSoftwareCompression;
pHDR->uControlBlockId = psHdrInfo->uControlBlockId;
pHDR->sOSSpecificData.uSize = psHdrInfo->uOSDataSize;
// write out the os specific data at the current storage offset and update it
if (psHdrInfo->uOSDataSize)
{
pHDR->sOSSpecificData.uOffset = uCurrentStorageOffset;
memcpy(pBuffer + uCurrentStorageOffset, psHdrInfo->pvOSData, psHdrInfo->uOSDataSize);
uCurrentStorageOffset += psHdrInfo->uOSDataSize;
}
else
{
pHDR->sOSSpecificData.uOffset = 0;
pHDR->sOSSpecificData.uSize = 0;
}
pHDR->uStringType = psHdrInfo->uStringType;
pHDR->uHeaderCheckSum = CalcChecksum(pBuffer, sizeof(MTF_DBLK_HDR) / sizeof(UINT16) - 1);
if (puCurrentStorage)
*puCurrentStorage = uCurrentStorageOffset;
}
void MTF_DBLK_HDR_INFO_ReadFromBuffer(
MTF_DBLK_HDR_INFO *psHdrInfo,
BYTE *pBuffer)
{
MTF_DBLK_HDR *pHDR = 0;
size_t uCurrentStorageOffset = 0;
int i;
pHDR = (MTF_DBLK_HDR *) pBuffer;
for (i = 0; i < 4; ++i)
psHdrInfo->acBlockType[i] = pHDR->acBlockType[i];
psHdrInfo->acBlockType[4] = 0;
psHdrInfo->uOffsetToFirstStream = pHDR->uOffsetToFirstStream;
psHdrInfo->uBlockAttributes = pHDR->uBlockAttributes ;
psHdrInfo->uOSID = pHDR->uOSID;
psHdrInfo->uOSVersion = pHDR->uOSVersion;
psHdrInfo->uDisplayableSize = pHDR->uDisplayableSize;
psHdrInfo->uFormatLogicalAddress= pHDR->uFormatLogicalAddress;
psHdrInfo->uSoftwareCompression = pHDR->uSoftwareCompression;
psHdrInfo->uControlBlockId = pHDR->uControlBlockId;
psHdrInfo->uOSDataSize = pHDR->sOSSpecificData.uSize;
psHdrInfo->pvOSData = (pBuffer + pHDR->sOSSpecificData.uOffset);
psHdrInfo->uStringType = pHDR->uStringType;
psHdrInfo->uHeaderCheckSum = pHDR->uHeaderCheckSum;
}
/* ==================================================================================
=====================================================================================
TAPE DBLK: MTF_DBLK_TAPE_INFO
=====================================================================================
================================================================================== */
// Calculates the room that will be taken up in the DBLK by strings and OS specific data
// **NOT INCLUDING THE COMMON DBLK HEADER additional info **
static size_t MTF_DBLK_TAPE_INFO_CalcAddDataSize(
MTF_DBLK_TAPE_INFO *pTapeInfo
)
{
return wstrsize(pTapeInfo->szTapeName) +
wstrsize(pTapeInfo->szTapeDescription) +
wstrsize(pTapeInfo->szTapePassword) +
wstrsize(pTapeInfo->szSoftwareName);
}
/***********************************************************************************
* MTF_SetTAPEDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetTAPEDefaults(
MTF_DBLK_TAPE_INFO *pTapeInfo
)
{
time_t tTime;
time(&tTime);
pTapeInfo->uTapeFamilyId = 0;
pTapeInfo->uTapeAttributes = 0;
pTapeInfo->uTapeSequenceNumber = 0;
pTapeInfo->uPasswordEncryptionAlgorithm = MTF_PW_ENCRYPT_NONE;
pTapeInfo->uSoftFilemarkBlockSize = 0;
pTapeInfo->uTapeCatalogType = MTF_OTC_NONE; // MTF_OTC_TYPE
pTapeInfo->szTapeName = 0 ;
pTapeInfo->szTapeDescription = 0 ;
pTapeInfo->szTapePassword = 0;
pTapeInfo->szSoftwareName = 0;
pTapeInfo->uAlignmentFactor = MTF_GetAlignmentFactor();
pTapeInfo->uSoftwareVendorId = 0;
pTapeInfo->sTapeDate = MTF_CreateDateTimeFromTM(gmtime(&tTime));
pTapeInfo->uMTFMajorVersion = MTF_FORMAT_VER_MAJOR;
}
/***********************************************************************************
* MTF_WriteTAPEDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteTAPEDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_TAPE_INFO *psTapeInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_TAPE) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) +
MTF_DBLK_TAPE_INFO_CalcAddDataSize(psTapeInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
//
// write the header and then fill in the stuff from this info struct
//
{
MTF_DBLK_TAPE *pTape = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_TAPE);
MTF_WriteDblkHdrToBuffer(
MTF_ID_TAPE,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
pTape = (MTF_DBLK_TAPE *) pBuffer;
pTape->uTapeFamilyId = psTapeInfo->uTapeFamilyId;
pTape->uTapeAttributes = psTapeInfo->uTapeAttributes;
pTape->uTapeSequenceNumber = psTapeInfo->uTapeSequenceNumber;
pTape->uPasswordEncryptionAlgorithm = psTapeInfo->uPasswordEncryptionAlgorithm;
pTape->uSoftFilemarkBlockSize = psTapeInfo->uSoftFilemarkBlockSize;
pTape->uTapeCatalogType = psTapeInfo->uTapeCatalogType;
uCurrentStorageOffset = StringToTapeAddress(&pTape->sTapeName, pBuffer, psTapeInfo->szTapeName, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&pTape->sTapeDescription, pBuffer, psTapeInfo->szTapeDescription, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&pTape->sTapePassword, pBuffer, psTapeInfo->szTapePassword, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&pTape->sSoftware_name, pBuffer, psTapeInfo->szSoftwareName, uCurrentStorageOffset);
pTape->uAlignmentFactor = psTapeInfo->uAlignmentFactor;
pTape->uSoftwareVendorId = psTapeInfo->uSoftwareVendorId;
pTape->sTapeDate = psTapeInfo->sTapeDate;
pTape->uMTFMajorVersion = psTapeInfo->uMTFMajorVersion;
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadTAPEDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadTAPEDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_TAPE_INFO *psTapeInfo,
BYTE *pBuffer)
{
MTF_DBLK_TAPE *pTape = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
pTape = (MTF_DBLK_TAPE *) pBuffer;
psTapeInfo->uTapeFamilyId = pTape->uTapeFamilyId;
psTapeInfo->uTapeAttributes = pTape->uTapeAttributes;
psTapeInfo->uTapeSequenceNumber = pTape->uTapeSequenceNumber;
psTapeInfo->uPasswordEncryptionAlgorithm = pTape->uPasswordEncryptionAlgorithm;
psTapeInfo->uSoftFilemarkBlockSize = pTape->uSoftFilemarkBlockSize;
psTapeInfo->uTapeCatalogType = pTape->uTapeCatalogType;
psTapeInfo->uAlignmentFactor = pTape->uAlignmentFactor;
psTapeInfo->uSoftwareVendorId = pTape->uSoftwareVendorId;
psTapeInfo->sTapeDate = pTape->sTapeDate;
psTapeInfo->uMTFMajorVersion = pTape->uMTFMajorVersion;
psTapeInfo->szTapeName = MakeString((wchar_t *) (pBuffer + pTape->sTapeName.uOffset), pTape->sTapeName.uSize);
psTapeInfo->szTapeDescription = MakeString((wchar_t *) (pBuffer + pTape->sTapeDescription.uOffset), pTape->sTapeDescription.uSize);
psTapeInfo->szTapePassword = MakeString((wchar_t *) (pBuffer + pTape->sTapePassword.uOffset), pTape->sTapePassword.uSize);
psTapeInfo->szSoftwareName = MakeString((wchar_t *) (pBuffer + pTape->sSoftware_name.uOffset), pTape->sSoftware_name.uSize);
if ( !psTapeInfo->szTapeName || !psTapeInfo->szTapeDescription || !psTapeInfo->szTapePassword || !psTapeInfo->szSoftwareName)
return MTF_OUT_OF_MEMORY;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
SSET DBLK: MTF_DBLK_SSET_INFO
=====================================================================================
================================================================================== */
// Calculates the room that will be taken up in the DBLK by strings and OS specific data
// **NOT INCLUDING THE COMMON DBLK HEADER additional info **
static size_t MTF_DBLK_SSET_INFO_CalcAddDataSize(
MTF_DBLK_SSET_INFO *pSSETInfo
)
{
return wstrsize(pSSETInfo->szDataSetName)
+ wstrsize(pSSETInfo->szDataSetDescription)
+ wstrsize(pSSETInfo->szDataSetPassword)
+ wstrsize(pSSETInfo->szUserName);
}
/***********************************************************************************
* MTF_SetSSETDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetSSETDefaults(
MTF_DBLK_SSET_INFO *pSSETInfo
)
{
time_t tTime;
time(&tTime);
pSSETInfo->uSSETAttributes = 0;
pSSETInfo->uPasswordEncryptionAlgorithm = MTF_PW_ENCRYPT_NONE;
pSSETInfo->uDataEncryptionAlgorithm = MTF_DATA_ENCRYPT_NONE;
pSSETInfo->uSoftwareVendorId = 0;
pSSETInfo->uDataSetNumber = 0;
pSSETInfo->szDataSetName = 0 ;
pSSETInfo->szDataSetDescription = 0 ;
pSSETInfo->szDataSetPassword = 0 ;
pSSETInfo->szUserName = 0 ;
pSSETInfo->uPhysicalBlockAddress = 0;
pSSETInfo->sMediaWriteDate = MTF_CreateDateTimeFromTM(gmtime(&tTime));
pSSETInfo->uSoftwareVerMjr = 0;
pSSETInfo->uSoftwareVerMnr = 0;
pSSETInfo->uTimeZone = MTF_LOCAL_TZ;
pSSETInfo->uMTFMinorVer = MTF_FORMAT_VER_MINOR;
pSSETInfo->uTapeCatalogVersion = MTF_OTC_NONE; // MTF_OTC_VERSION
}
/***********************************************************************************
* MTF_WriteSSETDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteSSETDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_SSET_INFO *psSSETInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_SSET) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) +
MTF_DBLK_SSET_INFO_CalcAddDataSize(psSSETInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_SSET *psSSET = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_SSET);
MTF_WriteDblkHdrToBuffer(
MTF_ID_SSET,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psSSET = (MTF_DBLK_SSET *) pBuffer;
psSSET->uSSETAttributes = psSSETInfo->uSSETAttributes;
psSSET->uPasswordEncryptionAlgorithm = psSSETInfo->uPasswordEncryptionAlgorithm;
psSSET->uDataEncryptionAlgorithm = psSSETInfo->uDataEncryptionAlgorithm;
psSSET->uSoftwareVendorId = psSSETInfo->uSoftwareVendorId;
psSSET->uDataSetNumber = psSSETInfo->uDataSetNumber;
uCurrentStorageOffset = StringToTapeAddress(&psSSET->sDataSetName, pBuffer, psSSETInfo->szDataSetName, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&psSSET->sDataSetDescription, pBuffer, psSSETInfo->szDataSetDescription, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&psSSET->sDataSetPassword, pBuffer, psSSETInfo->szDataSetPassword, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&psSSET->sUserName, pBuffer, psSSETInfo->szUserName, uCurrentStorageOffset);
psSSET->uPhysicalBlockAddress = psSSETInfo->uPhysicalBlockAddress;
psSSET->sMediaWriteDate = psSSETInfo->sMediaWriteDate;
psSSET->uSoftwareVerMjr = psSSETInfo->uSoftwareVerMjr;
psSSET->uSoftwareVerMnr = psSSETInfo->uSoftwareVerMnr;
psSSET->uTimeZone = psSSETInfo->uTimeZone;
psSSET->uMTFMinorVer = psSSETInfo->uMTFMinorVer;
psSSET->uTapeCatalogVersion = psSSETInfo->uTapeCatalogVersion;
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadSSETDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadSSETDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_SSET_INFO *psSSETInfo,
BYTE *pBuffer)
{
MTF_DBLK_SSET *psSSET = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psSSET = (MTF_DBLK_SSET *) pBuffer;
psSSETInfo->uSSETAttributes = psSSET->uSSETAttributes;
psSSETInfo->uPasswordEncryptionAlgorithm = psSSET->uPasswordEncryptionAlgorithm;
psSSETInfo->uDataEncryptionAlgorithm = psSSET->uDataEncryptionAlgorithm;
psSSETInfo->uSoftwareVendorId = psSSET->uSoftwareVendorId;
psSSETInfo->uDataSetNumber = psSSET->uDataSetNumber;
psSSETInfo->uPhysicalBlockAddress = psSSET->uPhysicalBlockAddress;
psSSETInfo->sMediaWriteDate = psSSET->sMediaWriteDate;
psSSETInfo->uSoftwareVerMjr = psSSET->uSoftwareVerMjr;
psSSETInfo->uSoftwareVerMnr = psSSET->uSoftwareVerMnr;
psSSETInfo->uTimeZone = psSSET->uTimeZone;
psSSETInfo->uMTFMinorVer = psSSET->uMTFMinorVer;
psSSETInfo->uTapeCatalogVersion = psSSET->uTapeCatalogVersion;
psSSETInfo->szDataSetName = MakeString((wchar_t *) (pBuffer + psSSET->sDataSetName.uOffset), psSSET->sDataSetName.uSize);
psSSETInfo->szDataSetDescription = MakeString((wchar_t *) (pBuffer + psSSET->sDataSetDescription.uOffset), psSSET->sDataSetDescription.uSize);
psSSETInfo->szDataSetPassword = MakeString((wchar_t *) (pBuffer + psSSET->sDataSetPassword.uOffset), psSSET->sDataSetPassword.uSize);
psSSETInfo->szUserName = MakeString((wchar_t *) (pBuffer + psSSET->sUserName.uOffset), psSSET->sUserName.uSize);
if ( !psSSETInfo->szDataSetName || !psSSETInfo->szDataSetDescription || !psSSETInfo->szDataSetPassword || !psSSETInfo->szUserName )
return MTF_OUT_OF_MEMORY;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
VOLB DBLK: MTF_DBLK_VOLB_INFO
=====================================================================================
================================================================================== */
// Calculates the room that will be taken up in the DBLK by strings and OS specific data
// **NOT INCLUDING THE COMMON DBLK HEADER additional info **
static size_t MTF_DBLK_VOLB_INFO_CalcAddDataSize(
MTF_DBLK_VOLB_INFO *pVOLBInfo
)
{
return wstrsize(pVOLBInfo->szDeviceName) +
wstrsize(pVOLBInfo->szVolumeName) +
wstrsize(pVOLBInfo->szMachineName);
}
/***********************************************************************************
* MTF_SetVOLBDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetVOLBDefaults(MTF_DBLK_VOLB_INFO *pVOLBInfo)
{
time_t tTime;
time(&tTime);
pVOLBInfo->uVolumeAttributes = 0;
pVOLBInfo->szDeviceName = 0 ;
pVOLBInfo->szVolumeName = 0 ;
pVOLBInfo->szMachineName = 0 ;
pVOLBInfo->sMediaWriteDate = MTF_CreateDateTimeFromTM(gmtime(&tTime));;
}
/***********************************************************************************
* MTF_SetVOLBForDevice()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetVOLBForDevice(MTF_DBLK_VOLB_INFO *pVOLBInfo, wchar_t *szDevice)
{
int nBufSize = MAX_COMPUTERNAME_LENGTH + 1;
wchar_t tempDeviceName[STRLEN+4];
wcscpy(s_szDeviceName, szDevice);
MTF_SetVOLBDefaults(pVOLBInfo); // initialize
// Determine the format and set the appropriate bit in the VOLB attributes.
if (*(s_szDeviceName+1) == L':') {
// drive letter w/colon format
pVOLBInfo->uVolumeAttributes |= MTF_VOLB_DEV_DRIVE;
}
else if (0 == wcsncmp( s_szDeviceName, L"UNC", 3 )) {
// UNC format
pVOLBInfo->uVolumeAttributes |= MTF_VOLB_DEV_UNC;
}
else {
// operating system specific format
pVOLBInfo->uVolumeAttributes |= MTF_VOLB_DEV_OS_SPEC;
}
// need to prepend \\?\ for the GetVolumeInformation call
wcscpy(tempDeviceName, L"\\\\?\\");
wcscat(tempDeviceName, s_szDeviceName);
GetVolumeInformationW(tempDeviceName, s_szVolumeName, STRLEN, 0, 0, 0, 0, 0);
GetComputerNameW(s_szMachineName, &nBufSize);
pVOLBInfo->szDeviceName = s_szDeviceName;
pVOLBInfo->szVolumeName = s_szVolumeName;
pVOLBInfo->szMachineName = s_szMachineName;
}
/***********************************************************************************
* MTF_WriteVOLBDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteVOLBDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_VOLB_INFO *psVOLBInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_VOLB) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) +
MTF_DBLK_VOLB_INFO_CalcAddDataSize(psVOLBInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_VOLB *psVOLB = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_VOLB);
MTF_WriteDblkHdrToBuffer(
MTF_ID_VOLB,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psVOLB = (MTF_DBLK_VOLB *) pBuffer;
psVOLB->uVolumeAttributes = psVOLBInfo->uVolumeAttributes;
uCurrentStorageOffset = StringToTapeAddress(&psVOLB->sDeviceName, pBuffer, psVOLBInfo->szDeviceName, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&psVOLB->sVolumeName, pBuffer, psVOLBInfo->szVolumeName, uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&psVOLB->sMachineName, pBuffer, psVOLBInfo->szMachineName, uCurrentStorageOffset);
psVOLB->sMediaWriteDate = psVOLBInfo->sMediaWriteDate;
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadVOLBDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadVOLBDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_VOLB_INFO *psVOLBInfo,
BYTE *pBuffer)
{
MTF_DBLK_VOLB *psVOLB = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psVOLB = (MTF_DBLK_VOLB *) pBuffer;
psVOLBInfo->uVolumeAttributes = psVOLB->uVolumeAttributes;
psVOLBInfo->sMediaWriteDate = psVOLB->sMediaWriteDate;
psVOLBInfo->szDeviceName = MakeString((wchar_t *) (pBuffer + psVOLB->sDeviceName.uOffset), psVOLB->sDeviceName.uSize);
psVOLBInfo->szVolumeName = MakeString((wchar_t *) (pBuffer + psVOLB->sVolumeName.uOffset), psVOLB->sVolumeName.uSize);
psVOLBInfo->szMachineName = MakeString((wchar_t *) (pBuffer + psVOLB->sMachineName.uOffset), psVOLB->sMachineName.uSize);
if ( !psVOLBInfo->szDeviceName || !psVOLBInfo->szVolumeName || !psVOLBInfo->szMachineName )
return MTF_OUT_OF_MEMORY;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
DIRB DBLK: MTF_DBLK_DIRB_INFO
=====================================================================================
================================================================================== */
// Calculates the room that will be taken up in the DBLK by strings and OS specific data
// **NOT INCLUDING THE COMMON DBLK HEADER additional info **
static size_t MTF_DBLK_DIRB_INFO_CalcAddDataSize(MTF_DBLK_DIRB_INFO *pDIRBInfo)
{
return wstrsize(pDIRBInfo->szDirectoryName);
}
/***********************************************************************************
* MTF_SetDIRBDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetDIRBDefaults(
MTF_DBLK_DIRB_INFO *pDIRBInfo
)
{
pDIRBInfo->uDirectoryAttributes = 0;
pDIRBInfo->sLastModificationDate = MTF_CreateDateNull();
pDIRBInfo->sCreationDate = MTF_CreateDateNull();
pDIRBInfo->sBackupDate = MTF_CreateDateNull();
pDIRBInfo->sLastAccessDate = MTF_CreateDateNull();
pDIRBInfo->uDirectoryId = 0;
pDIRBInfo->szDirectoryName = 0 ;
}
/***********************************************************************************
* MTF_SetDIRBFromFindData()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetDIRBFromFindData(
MTF_DBLK_DIRB_INFO *pDIRBInfo,
wchar_t *szDirectoryName,
WIN32_FIND_DATAW *pFindData
)
{
MTF_SetDIRBDefaults(pDIRBInfo); // initialize
if ( wcslen( szDirectoryName ) < STRLEN ) {
wcscpy(s_szDirectoryName, szDirectoryName);
pDIRBInfo->szDirectoryName = s_szDirectoryName;
}
else {
pDIRBInfo->uDirectoryAttributes |= MTF_DIRB_PATH_IN_STREAM;
pDIRBInfo->szDirectoryName = 0;
}
if (pFindData)
{
pDIRBInfo->uDirectoryAttributes |=
pFindData->dwFileAttributes & FILE_ATTRIBUTE_READONLY ? MTF_DIRB_READ_ONLY : 0
| pFindData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? MTF_DIRB_HIDDEN : 0
| pFindData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? MTF_DIRB_SYSTEM : 0
| pFindData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? MTF_DIRB_MODIFIED : 0;
pDIRBInfo->sLastModificationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastWriteTime);
pDIRBInfo->sCreationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftCreationTime);
pDIRBInfo->sLastAccessDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastAccessTime);
}
pDIRBInfo->uDirectoryId = 0;
}
/***********************************************************************************
* MTF_WriteDIRBDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteDIRBDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_DIRB_INFO *psDIRBInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_DIRB) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) +
MTF_DBLK_DIRB_INFO_CalcAddDataSize(psDIRBInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_DIRB *psDIRB = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_DIRB);
MTF_WriteDblkHdrToBuffer(
MTF_ID_DIRB,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psDIRB = (MTF_DBLK_DIRB *) pBuffer;
psDIRB->uDirectoryAttributes = psDIRBInfo->uDirectoryAttributes;
psDIRB->sLastModificationDate = psDIRBInfo->sLastModificationDate;
psDIRB->sCreationDate = psDIRBInfo->sCreationDate;
psDIRB->sBackupDate = psDIRBInfo->sBackupDate;
psDIRB->sLastAccessDate = psDIRBInfo->sLastAccessDate;
psDIRB->uDirectoryId = psDIRBInfo->uDirectoryId;
//
// here, we need to turn the slashes (L'\\') to zeros (L'\0')in the directory name string...
//
{
int i, iLen;
wchar_t *szDirectoryName = (wchar_t *) (pBuffer + uCurrentStorageOffset);
uCurrentStorageOffset = StringToTapeAddress(&psDIRB->sDirectoryName, pBuffer, psDIRBInfo->szDirectoryName, uCurrentStorageOffset);
iLen = wstrsize(psDIRBInfo->szDirectoryName);
for (i = 0; i < iLen; ++i)
if (szDirectoryName[i] == L'\\')
szDirectoryName[i] = L'\0';
}
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadDIRBDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadDIRBDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_DIRB_INFO *psDIRBInfo,
BYTE *pBuffer)
{
MTF_DBLK_DIRB *psDIRB = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psDIRB = (MTF_DBLK_DIRB *) pBuffer;
psDIRBInfo->uDirectoryAttributes = psDIRB->uDirectoryAttributes;
psDIRBInfo->sLastModificationDate = psDIRB->sLastModificationDate;
psDIRBInfo->sCreationDate = psDIRB->sCreationDate;
psDIRBInfo->sBackupDate = psDIRB->sBackupDate;
psDIRBInfo->sLastAccessDate = psDIRB->sLastAccessDate;
psDIRBInfo->uDirectoryId = psDIRB->uDirectoryId;
psDIRBInfo->szDirectoryName = NULL;
//
// we need to turn the zeros in the directory name back to slashes
// (there are no terminating \0's in the string -- all \0's are really \\'s
//
{
wchar_t *pTmpBuffer;
int i;
pTmpBuffer = (wchar_t *) malloc(psDIRB->sDirectoryName.uSize);
if (pTmpBuffer) {
memmove(pTmpBuffer, pBuffer + psDIRB->sDirectoryName.uOffset, psDIRB->sDirectoryName.uSize);
for (i = 0; i < psDIRB->sDirectoryName.uSize; ++i)
if (pTmpBuffer[i] == L'\0')
pTmpBuffer[i] = L'\\';
psDIRBInfo->szDirectoryName = MakeString(pTmpBuffer, psDIRB->sDirectoryName.uSize);
free(pTmpBuffer);
}
}
if ( !psDIRBInfo->szDirectoryName )
return MTF_OUT_OF_MEMORY;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
FILE DBLK: MTF_DBLK_FILE_INFO
=====================================================================================
================================================================================== */
// Calculates the room that will be taken up in the DBLK by strings and OS specific data
// **NOT INCLUDING THE COMMON DBLK HEADER additional info **
static size_t MTF_DBLK_FILE_INFO_CalcAddDataSize(MTF_DBLK_FILE_INFO *pFILEInfo)
{
return wstrsize(pFILEInfo->szFileName);
}
/***********************************************************************************
* MTF_SetFILEDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetFILEDefaults(MTF_DBLK_FILE_INFO *pFILEInfo)
{
pFILEInfo->uFileAttributes = 0;
pFILEInfo->sLastModificationDate = MTF_CreateDateNull();
pFILEInfo->sCreationDate = MTF_CreateDateNull();
pFILEInfo->sBackupDate = MTF_CreateDateNull();
pFILEInfo->sLastAccessDate = MTF_CreateDateNull();
pFILEInfo->uDirectoryId = 0;
pFILEInfo->uFileId = 0;
pFILEInfo->szFileName = 0;
}
/***********************************************************************************
* MTF_SetFILEFromFindData()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetFILEFromFindData(MTF_DBLK_FILE_INFO *pFILEInfo, WIN32_FIND_DATAW *pFindData)
{
time_t tTime;
time(&tTime);
MTF_SetFILEDefaults(pFILEInfo); // initialize
wcscpy(s_szFileName, pFindData->cFileName);
pFILEInfo->uFileAttributes =
(pFindData->dwFileAttributes & FILE_ATTRIBUTE_READONLY ? MTF_FILE_READ_ONLY : 0)
| (pFindData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? MTF_FILE_HIDDEN : 0)
| (pFindData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? MTF_FILE_SYSTEM : 0)
| (pFindData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? MTF_FILE_MODIFIED : 0) ;
pFILEInfo->sLastModificationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastWriteTime);
pFILEInfo->sCreationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftCreationTime);
pFILEInfo->sLastAccessDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastAccessTime);
pFILEInfo->uDirectoryId = 0;
pFILEInfo->uFileId = 0;
pFILEInfo->szFileName = s_szFileName;
pFILEInfo->uDisplaySize = MTF_CreateUINT64(pFindData->nFileSizeLow, pFindData->nFileSizeHigh);
}
/***********************************************************************************
* MTF_WriteFILEDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteFILEDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_FILE_INFO *psFILEInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_FILE) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) +
MTF_DBLK_FILE_INFO_CalcAddDataSize(psFILEInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_FILE *psFILE = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_FILE);
psHdrInfo->uDisplayableSize = psFILEInfo->uDisplaySize;
MTF_WriteDblkHdrToBuffer(
MTF_ID_FILE,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psFILE = (MTF_DBLK_FILE *) pBuffer;
psFILE->uFileAttributes = psFILEInfo->uFileAttributes;
psFILE->sLastModificationDate = psFILEInfo->sLastModificationDate;
psFILE->sCreationDate = psFILEInfo->sCreationDate;
psFILE->sBackupDate = psFILEInfo->sBackupDate;
psFILE->sLastAccessDate = psFILEInfo->sLastAccessDate;
psFILE->uDirectoryId = psFILEInfo->uDirectoryId;
psFILE->uFileId = psFILEInfo->uFileId;
uCurrentStorageOffset = StringToTapeAddress(&psFILE->sFileName, pBuffer, psFILEInfo->szFileName, uCurrentStorageOffset);
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadFILEDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadFILEDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_FILE_INFO *psFILEInfo,
BYTE *pBuffer)
{
MTF_DBLK_FILE *psFILE = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psFILE = (MTF_DBLK_FILE *) pBuffer;
psFILEInfo->uFileAttributes = psFILE->uFileAttributes;
psFILEInfo->sLastModificationDate = psFILE->sLastModificationDate;
psFILEInfo->sCreationDate = psFILE->sCreationDate;
psFILEInfo->sBackupDate = psFILE->sBackupDate;
psFILEInfo->sLastAccessDate = psFILE->sLastAccessDate;
psFILEInfo->uDirectoryId = psFILE->uDirectoryId;
psFILEInfo->uFileId = psFILE->uFileId;
psFILEInfo->szFileName = MakeString((wchar_t *) (pBuffer + psFILE->sFileName.uOffset), psFILE->sFileName.uSize);
if ( !psFILEInfo->szFileName )
return MTF_OUT_OF_MEMORY;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
CFIL DBLK: MTF_DBLK_CFIL_INFO
=====================================================================================
================================================================================== */
/***********************************************************************************
* MTF_SetCFILDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetCFILDefaults(
MTF_DBLK_CFIL_INFO *pCFILInfo
)
{
pCFILInfo->uCFileAttributes = MTF_CFIL_UNREADABLE_BLK;
pCFILInfo->uDirectoryId = 0;
pCFILInfo->uFileId = 0;
pCFILInfo->uStreamOffset = 0;
pCFILInfo->uCorruptStreamNumber = 0;
}
/***********************************************************************************
* MTF_WriteCFILDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteCFILDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_CFIL_INFO *psCFILInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_HDR) +
sizeof(MTF_DBLK_CFIL) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_CFIL_INFO *psCFIL = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_HDR) + sizeof(MTF_DBLK_CFIL);
MTF_WriteDblkHdrToBuffer(
MTF_ID_CFIL,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psCFIL = (MTF_DBLK_CFIL_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR));
*psCFIL = *psCFILInfo;
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadCFILDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadCFILDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_CFIL_INFO *psCFILInfo,
BYTE *pBuffer)
{
MTF_DBLK_CFIL *psCFIL = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psCFIL = (MTF_DBLK_CFIL_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR));
*psCFILInfo = *psCFIL;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
ESPB DBLK
=====================================================================================
================================================================================== */
/***********************************************************************************
* MTF_WriteESPBDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteESPBDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_HDR) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream) {
if (pnSizeUsed) {
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
MTF_WriteDblkHdrToBuffer(
MTF_ID_ESPB,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
0);
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadESPBDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadESPBDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
BYTE *pBuffer)
{
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
End of Set DBLK (ESET)
=====================================================================================
================================================================================== */
/***********************************************************************************
* MTF_SetESETDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetESETDefaults(MTF_DBLK_ESET_INFO *pESETInfo)
{
time_t tTime;
time(&tTime);
pESETInfo->uESETAttributes = 0;
pESETInfo->uNumberOfCorrupFiles = 0;
pESETInfo->uSetMapPBA = 0;
pESETInfo->uFileDetailPBA = 0;
pESETInfo->uFDDTapeSequenceNumber = 0;
pESETInfo->uDataSetNumber = 0;
pESETInfo->sMediaWriteDate = MTF_CreateDateTimeFromTM(gmtime(&tTime));
}
/***********************************************************************************
* MTF_WriteESETDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteESETDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_ESET_INFO *psESETInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_ESET) +
sizeof(MTF_DBLK_HDR) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_ESET_INFO *psESET = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_ESET) + sizeof(MTF_DBLK_HDR);
MTF_WriteDblkHdrToBuffer(
MTF_ID_ESET,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psESET = (MTF_DBLK_ESET_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR));
*psESET = *psESETInfo;
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadESETDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadESETDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_ESET_INFO *psESETInfo,
BYTE *pBuffer)
{
MTF_DBLK_ESET *psESET = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psESET = (MTF_DBLK_ESET_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR));
*psESETInfo = *psESET;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
End of Set DBLK (EOTM)
=====================================================================================
================================================================================== */
/***********************************************************************************
* MTF_SetEOTMDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetEOTMDefaults(MTF_DBLK_EOTM_INFO *pEOTMInfo)
{
pEOTMInfo->uLastESETPBA = 0;
}
/***********************************************************************************
* MTF_WriteEOTMDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteEOTMDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_EOTM_INFO *psEOTMInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
//
// Figure the size of the entire DBLK & make sure we have room
//
uOffsetToFirstStream = sizeof(MTF_DBLK_EOTM_INFO) +
sizeof(MTF_DBLK_HDR) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_EOTM_INFO *psEOTM = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_HDR) + sizeof(MTF_DBLK_EOTM);
MTF_WriteDblkHdrToBuffer(
MTF_ID_EOTM,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psEOTM = (MTF_DBLK_EOTM_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR));
*psEOTM = *psEOTMInfo;
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadEOTMDblk()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadEOTMDblk( MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_EOTM_INFO *psEOTMInfo,
BYTE *pBuffer)
{
MTF_DBLK_EOTM *psEOTM = 0;
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psEOTM = (MTF_DBLK_EOTM_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR));
*psEOTMInfo = *psEOTM;
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
Soft Filemark (SFMB)
=====================================================================================
================================================================================== */
/***********************************************************************************
* MTF_CreateSFMB() - (bmd)
* ** MTF API FUNCTION **
***********************************************************************************/
size_t MTF_GetMaxSoftFilemarkEntries(size_t nBlockSize)
{
size_t n;
if (0 == nBlockSize || nBlockSize % 512) {
return 0;
}
// The SFMB fills the entire block.
// Calculate the total number of entries that fit within a block
// such that MTF_DBLK_HDR + MTF_DBLK_SFMB + (n-1 elements) < nBlockSize
n = (nBlockSize - sizeof(MTF_DBLK_HDR) - sizeof(MTF_DBLK_SFMB) + sizeof(UINT32))/sizeof(UINT32);
return n;
}
/***********************************************************************************
* MTF_InsertSoftFilemark() - (bmd)
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_InsertSoftFilemark(MTF_DBLK_SFMB_INFO *psSoftInfo,
UINT32 pba)
{
size_t n;
size_t bytesToShift;
// We insert a filemark entry by shifting all the entries down. The one closest BOM
// eventually drop out of the array.
if (psSoftInfo) {
n = psSoftInfo->uNumberOfFilemarkEntries;
bytesToShift = psSoftInfo->uFilemarkEntriesUsed * sizeof(UINT32);
// So we don't overwrite memory.
bytesToShift -= (psSoftInfo->uFilemarkEntriesUsed < psSoftInfo->uNumberOfFilemarkEntries) ? 0 : sizeof(UINT32);
memmove(&psSoftInfo->uFilemarkArray[1], &psSoftInfo->uFilemarkArray[0], bytesToShift);
psSoftInfo->uFilemarkArray[0] = pba;
if (psSoftInfo->uFilemarkEntriesUsed < psSoftInfo->uNumberOfFilemarkEntries) {
psSoftInfo->uFilemarkEntriesUsed++;
}
}
}
/***********************************************************************************
* MTF_WriteSFMBDblk() - (bmd)
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteSFMBDblk(MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_SFMB_INFO *psSoftInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
UINT16 uOffsetToFirstStream;
size_t sizeOfSFMB;
if (NULL == psHdrInfo || NULL == psSoftInfo || NULL == pBuffer || NULL == pnSizeUsed || 0 == nBufferSize) {
return ERROR_INVALID_PARAMETER;
}
// Code assumes sizeof(MTF_DBLK_SFMB_INFO) == sizeof(MTF_DBLK_SFMB)
if (sizeof(MTF_DBLK_SFMB_INFO) != sizeof(MTF_DBLK_SFMB)) {
return ERROR_INVALID_FUNCTION;
}
//
// Figure the size of the entire DBLK & make sure we have room
//
sizeOfSFMB = sizeof(MTF_DBLK_SFMB) + (psSoftInfo->uNumberOfFilemarkEntries-1)*sizeof(UINT32);
uOffsetToFirstStream = sizeOfSFMB +
sizeof(MTF_DBLK_HDR) +
MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo);
uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4);
if (nBufferSize < uOffsetToFirstStream)
{
if (pnSizeUsed)
*pnSizeUsed = uOffsetToFirstStream;
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToFirstStream);
{
MTF_DBLK_SFMB_INFO *psSFMB = 0;
size_t uCurrentStorageOffset = 0;
uCurrentStorageOffset = sizeof(MTF_DBLK_HDR) + sizeOfSFMB;
MTF_WriteDblkHdrToBuffer(
MTF_ID_SFMB,
uOffsetToFirstStream,
psHdrInfo,
pBuffer,
&uCurrentStorageOffset);
psSFMB = (MTF_DBLK_SFMB *) (pBuffer + sizeof(MTF_DBLK_HDR));
// Need a deep copy since MTF_DBLK_SFMB_INFO holds a placeholder for the array.
memcpy(psSFMB, psSoftInfo, sizeOfSFMB);
if (pnSizeUsed) {
*pnSizeUsed = uOffsetToFirstStream;
}
}
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadSFMBDblk() - (bmd)
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadSFMBDblk(MTF_DBLK_HDR_INFO *psHdrInfo,
MTF_DBLK_SFMB_INFO *psSoftInfo,
BYTE *pBuffer)
{
MTF_DBLK_SFMB *psSFMB = 0;
size_t sizeOfSFMB;
if (NULL == psHdrInfo || NULL == psSoftInfo || NULL == pBuffer) {
return ERROR_INVALID_PARAMETER;
}
// Code assumes sizeof(MTF_DBLK_SFMB_INFO) == sizeof(MTF_DBLK_SFMB)
if (sizeof(MTF_DBLK_SFMB_INFO) != sizeof(MTF_DBLK_SFMB)) {
return ERROR_INVALID_FUNCTION;
}
ClearStrings();
MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer);
psSFMB = (MTF_DBLK_SFMB *) (pBuffer + sizeof(MTF_DBLK_HDR));
// Need a deep copy since MTF_DBLK_SFMB_INFO holds a placeholder for the array.
sizeOfSFMB = sizeof(MTF_DBLK_SFMB) + (psSFMB->uNumberOfFilemarkEntries-1)*sizeof(UINT32);
memcpy(psSoftInfo, psSFMB, sizeOfSFMB);
return MTF_ERROR_NONE;
}
/* ==================================================================================
=====================================================================================
STREAM HEADER
=====================================================================================
================================================================================== */
/***********************************************************************************
* MTF_SetSTREAMDefaults()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetSTREAMDefaults(MTF_STREAM_INFO *pSTREAMInfo, char *szId)
{
memcpy(pSTREAMInfo->acStreamId, szId, 4);
pSTREAMInfo->uStreamFileSystemAttributes = 0;
pSTREAMInfo->uStreamTapeFormatAttributes = 0;
pSTREAMInfo->uStreamLength = 0;
pSTREAMInfo->uDataEncryptionAlgorithm = 0;
pSTREAMInfo->uDataCompressionAlgorithm = 0;
pSTREAMInfo->uCheckSum = 0;
}
/***********************************************************************************
* MTF_SetSTREAMFromStreamId()
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetSTREAMFromStreamId(
MTF_STREAM_INFO *pSTREAMInfo,
WIN32_STREAM_ID *pStreamId,
size_t nIDHeaderSize
)
{
// From Steve DeVos, Seagate:
// > BACKUP_INVALID and BACKUP_LINK will never be returned from BackupRead.
// >
// > -Steve
//
// TODO: MTF_NT_ENCRYPTED_STREAM "NTED"; These retrieved by NT Encyption APIs
// TODO: MTF_NT_QUOTA_STREAM "NTQU"; These retrieved by NT Quota APIs
MTF_SetSTREAMDefaults(pSTREAMInfo, "UNKN");
if (pStreamId->dwStreamId == BACKUP_DATA)
memcpy(pSTREAMInfo->acStreamId, "STAN", 4);
else if (pStreamId->dwStreamId == BACKUP_EA_DATA)
memcpy(pSTREAMInfo->acStreamId, "NTEA", 4);
else if (pStreamId->dwStreamId == BACKUP_SECURITY_DATA)
memcpy(pSTREAMInfo->acStreamId, "NACL", 4);
else if (pStreamId->dwStreamId == BACKUP_ALTERNATE_DATA)
memcpy(pSTREAMInfo->acStreamId, "ADAT", 4);
else if (pStreamId->dwStreamId == BACKUP_OBJECT_ID)
memcpy(pSTREAMInfo->acStreamId, "NTOI", 4);
else if (pStreamId->dwStreamId == BACKUP_REPARSE_DATA)
memcpy(pSTREAMInfo->acStreamId, "NTRP", 4);
else if (pStreamId->dwStreamId == BACKUP_SPARSE_BLOCK)
memcpy(pSTREAMInfo->acStreamId, "SPAR", 4);
else {
pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_IS_NON_PORTABLE;
}
if (pStreamId->dwStreamAttributes & STREAM_MODIFIED_WHEN_READ)
pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_MODIFIED_BY_READ;
if (pStreamId->dwStreamAttributes & STREAM_CONTAINS_SECURITY)
pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_CONTAINS_SECURITY;
if (pStreamId->dwStreamAttributes & STREAM_SPARSE_ATTRIBUTE)
pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_IS_SPARSE;
pSTREAMInfo->uStreamTapeFormatAttributes = 0;
pSTREAMInfo->uStreamLength = MTF_CreateUINT64(pStreamId->Size.LowPart, pStreamId->Size.HighPart) + nIDHeaderSize;
pSTREAMInfo->uDataEncryptionAlgorithm = 0;
pSTREAMInfo->uDataCompressionAlgorithm = 0;
pSTREAMInfo->uCheckSum = 0;
}
/***********************************************************************************
* MTF_SetStreamIdFromSTREAM() - (bmd)
* ** MTF API FUNCTION **
***********************************************************************************/
void MTF_SetStreamIdFromSTREAM(
WIN32_STREAM_ID *pStreamId,
MTF_STREAM_INFO *pSTREAMInfo,
size_t nIDHeaderSize
)
{
memset( pStreamId, 0, sizeof( WIN32_STREAM_ID ) );
if (0 == memcmp(pSTREAMInfo->acStreamId, "STAN", 4))
pStreamId->dwStreamId = BACKUP_DATA;
else if (0 == memcmp(pSTREAMInfo->acStreamId, "NTEA", 4))
pStreamId->dwStreamId = BACKUP_EA_DATA;
else if (0 == memcmp(pSTREAMInfo->acStreamId, "NACL", 4))
pStreamId->dwStreamId = BACKUP_SECURITY_DATA;
else if (0 == memcmp(pSTREAMInfo->acStreamId, "ADAT", 4))
pStreamId->dwStreamId = BACKUP_ALTERNATE_DATA;
else if (0 == memcmp(pSTREAMInfo->acStreamId, "NTOI", 4))
pStreamId->dwStreamId = BACKUP_OBJECT_ID;
else if (0 == memcmp(pSTREAMInfo->acStreamId, "NTRP", 4))
pStreamId->dwStreamId = BACKUP_REPARSE_DATA;
else if (0 == memcmp(pSTREAMInfo->acStreamId, "SPAR", 4))
pStreamId->dwStreamId = BACKUP_SPARSE_BLOCK;
else {
pStreamId->dwStreamId = BACKUP_INVALID;
}
pStreamId->dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE;
if (pSTREAMInfo->uStreamFileSystemAttributes & MTF_STREAM_MODIFIED_BY_READ)
pStreamId->dwStreamAttributes |= STREAM_MODIFIED_WHEN_READ;
if (pSTREAMInfo->uStreamFileSystemAttributes & MTF_STREAM_CONTAINS_SECURITY)
pStreamId->dwStreamAttributes |= STREAM_CONTAINS_SECURITY;
if (pSTREAMInfo->uStreamFileSystemAttributes & MTF_STREAM_IS_SPARSE)
pStreamId->dwStreamAttributes |= STREAM_SPARSE_ATTRIBUTE;
// TODO: Handle named data streams (size of name and in MTF stream)
// ? How do I know ?
pStreamId->Size.LowPart = (DWORD)((pSTREAMInfo->uStreamLength << 32) >>32);
pStreamId->Size.HighPart = (DWORD)(pSTREAMInfo->uStreamLength >> 32);
}
/***********************************************************************************
* MTF_WriteStreamHeader()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteStreamHeader(MTF_STREAM_INFO *psStreamInfo,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
psStreamInfo->uCheckSum = CalcChecksum((BYTE *) psStreamInfo, sizeof(MTF_STREAM_INFO) / sizeof(UINT16) - 1);
if (nBufferSize < sizeof(MTF_STREAM_INFO))
{
if (pnSizeUsed)
*pnSizeUsed = sizeof(MTF_STREAM_INFO);
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, sizeof(MTF_STREAM_INFO));
*((MTF_STREAM_INFO *) pBuffer) = *psStreamInfo;
if (pnSizeUsed)
*pnSizeUsed = sizeof(MTF_STREAM_INFO);
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_WriteNameStream() - (bmd)
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_WriteNameStream(
char *szType,
wchar_t *szName,
BYTE *pBuffer,
size_t nBufferSize,
size_t *pnSizeUsed)
{
MTF_STREAM_INFO sStream;
UINT16 uOffsetToCSUMStream;
UINT16 uOffsetToNextStream;
size_t nBufUsed;
UINT16 nameSize;
UINT32 nameChecksum;
//
// Figure the size of the entire Name stream including trailing CSUM and make sure we have room.
//
nameSize = (UINT16)wstrsize(szName); // including terminating '\0'
uOffsetToCSUMStream = sizeof(MTF_STREAM_INFO) + nameSize;
uOffsetToCSUMStream = (UINT16)Align(uOffsetToCSUMStream, 4);
uOffsetToNextStream = uOffsetToCSUMStream;
uOffsetToNextStream += sizeof(MTF_STREAM_INFO) + 4; // includes 4 byte CSUM data
uOffsetToNextStream = (UINT16)Align(uOffsetToNextStream, 4);
if (nBufferSize < uOffsetToNextStream) {
return MTF_ERROR_BUFFER_TOO_SMALL;
}
memset(pBuffer, 0, uOffsetToNextStream);
MTF_SetSTREAMDefaults(&sStream, szType);
sStream.uStreamLength = nameSize;
sStream.uStreamTapeFormatAttributes |= MTF_STREAM_CHECKSUMED;
MTF_WriteStreamHeader(&sStream, pBuffer, nBufferSize, &nBufUsed);
memcpy(pBuffer + nBufUsed, szName, nameSize);
if ( 0 == memcmp(sStream.acStreamId, "PNAM", 4) ) {
//
// here, we need to turn the slashes (L'\\') to zeros (L'\0')in the directory name string...
//
int i, iLen;
wchar_t *szDirectoryName = (wchar_t *) (pBuffer + nBufUsed);
iLen = wstrsize(szDirectoryName);
for (i = 0; i < iLen; ++i)
if (szDirectoryName[i] == L'\\')
szDirectoryName[i] = L'\0';
}
// For Name streams, we always tack on a CSUM
nameChecksum = CalcChecksumOfStreamData(pBuffer + nBufUsed, nameSize / sizeof(UINT32) + 1);
MTF_SetSTREAMDefaults(&sStream, MTF_CHECKSUM_STREAM);
sStream.uStreamLength = sizeof(nameChecksum);
MTF_WriteStreamHeader(&sStream, pBuffer + uOffsetToCSUMStream, nBufferSize, &nBufUsed);
memcpy(pBuffer + uOffsetToCSUMStream + nBufUsed, &nameChecksum, sizeof(nameChecksum));
if (pnSizeUsed)
*pnSizeUsed = uOffsetToNextStream;
return MTF_ERROR_NONE;
}
/***********************************************************************************
* MTF_ReadStreamHeader()
* ** MTF API FUNCTION **
***********************************************************************************/
DWORD MTF_ReadStreamHeader(MTF_STREAM_INFO *psStreamInfo,
BYTE *pBuffer)
{
*psStreamInfo = *((MTF_STREAM_INFO *) pBuffer);
return MTF_ERROR_NONE;
}