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.
1347 lines
30 KiB
1347 lines
30 KiB
/* File: D:\WACKER\tdll\sf.c (Created: 27-Nov-1993)
|
|
*
|
|
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 16 $
|
|
* $Date: 3/15/02 12:27p $
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <shlobj.h>
|
|
#pragma hdrstop
|
|
|
|
#include <stdio.h>
|
|
#include <sys\types.h>
|
|
#include <sys\stat.h>
|
|
|
|
#include "stdtyp.h"
|
|
#include "tdll.h"
|
|
#include "htchar.h"
|
|
#include "sf.h"
|
|
#include "mc.h"
|
|
|
|
typedef int int32;
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
*
|
|
* DATA SECTION
|
|
*
|
|
* This section contains all of the static data that the DLL uses. Once this
|
|
* data is exhausted, the DLL can do no more. It just returns errors. This
|
|
* means that it is important to close or release any and all session files
|
|
* that get opened.
|
|
*
|
|
*/
|
|
|
|
struct stDllSessionFileIndexItem
|
|
{
|
|
int32 uIndex; /* Index of the item */
|
|
int32 dwSize; /* Size of the item */
|
|
int32 dwOffset; /* Offset into data block of the item */
|
|
};
|
|
|
|
typedef struct stDllSessionFileIndexItem stDSII;
|
|
typedef stDSII *pstDSII;
|
|
|
|
struct stDllSessionFilePointer
|
|
{
|
|
int uBusy; /* TRUE means item is in use */
|
|
int fOpen; /* TRUE means open session file */
|
|
int uChanged; /* TRUE means something is different */
|
|
|
|
TCHAR *hFilename; /* Memory containing the file name */
|
|
|
|
/* These make up the index */
|
|
int uItemCount; /* Current items in the index */
|
|
int uItemsAlloc; /* Max items in current space */
|
|
pstDSII hIndex; /* Memory allocated for index */
|
|
|
|
/* This is the data segment */
|
|
int dwDataUsed; /* Amount used in data block */
|
|
int dwDataSize; /* Current sizeof the data block */
|
|
BYTE *hData; /* Memory allocated for file data */
|
|
};
|
|
|
|
typedef struct stDllSessionFilePointer stDSFP;
|
|
typedef stDSFP *pstDSFP;
|
|
|
|
#define ROUND_UP(x) ((x+0xFFFL)&(~0x0FFFL))
|
|
|
|
// used for testing #define ROUND_UP(x) ((x+0x3F)&(~0x03F))
|
|
|
|
#define SESS_FILE_MAX 64
|
|
|
|
static stDSFP asSessionFiles[SESS_FILE_MAX];
|
|
|
|
#define HDR_SIZE 256
|
|
|
|
TCHAR pszHdr[HDR_SIZE] =
|
|
{
|
|
TEXT("HyperTerminal 1.0 -- HyperTerminal data file\r\n")
|
|
TEXT("Please do not attempt to modify this file directly.\r\n")
|
|
TEXT("\r\n\r\n")
|
|
TEXT("\x1A")
|
|
};
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfAddToIndex
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* ARGUEMENTS:
|
|
*
|
|
* RETURNS:
|
|
* The offset of the item in the index array, or -1.
|
|
*/
|
|
int32 sfAddToIndex(const int uNdx,
|
|
const int32 sID,
|
|
const int32 dwSZ,
|
|
const int32 dwOffset)
|
|
{
|
|
int nRv = -1;
|
|
int nCnt;
|
|
int low, mid, high;
|
|
int found;
|
|
pstDSFP pD;
|
|
pstDSII pI;
|
|
pstDSII pIx;
|
|
pstDSII pIy;
|
|
|
|
pD = &asSessionFiles[uNdx];
|
|
|
|
if (pD->uItemCount >= pD->uItemsAlloc)
|
|
{
|
|
#if defined(DEBUG_OUTPUT)
|
|
OutputDebugString("Index expanded\r\n");
|
|
#endif
|
|
/*
|
|
* We need to get a bigger chunk of memory
|
|
*/
|
|
if (pD->hIndex == 0)
|
|
{
|
|
pD->uItemsAlloc = 64;
|
|
pD->hIndex = (pstDSII)malloc(sizeof(stDSII) * 64);
|
|
}
|
|
else
|
|
{
|
|
int newSize = pD->uItemsAlloc * 2;
|
|
stDSII * pTemphIndex = (pstDSII)
|
|
realloc(pD->hIndex, (size_t)newSize * sizeof(stDSII));
|
|
|
|
if (pTemphIndex == NULL)
|
|
{
|
|
return SF_ERR_MEMORY_ERROR;
|
|
}
|
|
else
|
|
{
|
|
pD->uItemsAlloc = newSize;
|
|
pD->hIndex = pTemphIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pD->hData == 0)
|
|
{
|
|
pD->hData = (BYTE *)malloc(ROUND_UP(4096));
|
|
memset(pD->hData, 0, HDR_SIZE);
|
|
pD->dwDataSize = ROUND_UP(4096);
|
|
pD->dwDataUsed = HDR_SIZE;
|
|
}
|
|
|
|
/*
|
|
* Find where the item goes
|
|
*/
|
|
pI = pD->hIndex;
|
|
|
|
found = FALSE;
|
|
pIx = 0;
|
|
low = 0;
|
|
high = pD->uItemCount - 1;
|
|
mid = high/2;
|
|
|
|
if (pD->uItemCount > 0)
|
|
{
|
|
while (low <= high)
|
|
{
|
|
mid = (low + high) / 2;
|
|
pIx = pI + mid;
|
|
|
|
if (sID < pIx->uIndex)
|
|
{
|
|
high = mid - 1;
|
|
}
|
|
else if (sID > pIx->uIndex)
|
|
{
|
|
low = mid + 1;
|
|
}
|
|
else
|
|
{
|
|
/* found a match */
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
if (dwSZ != 0)
|
|
{
|
|
/*
|
|
* Special case. Preserve the old values so that we can
|
|
* adjust the data section for the replacement value.
|
|
*/
|
|
pIx->dwSize = dwSZ;
|
|
pIx->dwOffset = dwOffset;
|
|
}
|
|
nRv = mid;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The problem with a binary search is that it is unclear where
|
|
* you are if no match occurs. So we do it the old way.
|
|
*/
|
|
pIx = pI;
|
|
nCnt = 0;
|
|
for (;;)
|
|
{
|
|
/* TODO: switch to binary search */
|
|
if (nCnt >= pD->uItemCount)
|
|
{
|
|
/*
|
|
* We have gone past the end of the list
|
|
*/
|
|
pIx->uIndex = sID;
|
|
pIx->dwSize = dwSZ;
|
|
pIx->dwOffset = dwOffset;
|
|
nRv = nCnt;
|
|
break;
|
|
}
|
|
else if (pIx->uIndex >= sID)
|
|
{
|
|
if (pIx->uIndex > sID)
|
|
{
|
|
/*
|
|
* Slide the remaining items down by one
|
|
*/
|
|
|
|
pIy = pI + pD->uItemCount;
|
|
while (pIy > pIx)
|
|
{
|
|
*pIy = *(pIy - 1);
|
|
pIy -= 1;
|
|
}
|
|
|
|
#if 0
|
|
/* Don, would this work better? */
|
|
|
|
_fmemmove(pIx+1, pIx,
|
|
(pD->uItemCount - nCnt) * sizeof(stDSII));
|
|
|
|
#endif
|
|
|
|
pIx->uIndex = sID;
|
|
pIx->dwSize = dwSZ;
|
|
pIx->dwOffset = dwOffset;
|
|
}
|
|
else /* == */
|
|
{
|
|
if (dwSZ != 0)
|
|
{
|
|
/*
|
|
* Special case. Preserve the old values so that we can
|
|
* adjust the data section for the replacement value.
|
|
*/
|
|
pIx->dwSize = dwSZ;
|
|
pIx->dwOffset = dwOffset;
|
|
}
|
|
pD->uItemCount -= 1;
|
|
}
|
|
|
|
nRv = (int)(pIx - pI);
|
|
break;
|
|
}
|
|
pIx += 1;
|
|
nCnt += 1;
|
|
}
|
|
pD->uItemCount += 1;
|
|
}
|
|
|
|
return nRv;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* CreateSysFileHdl
|
|
*
|
|
* DESCRIPTION:
|
|
* Creates a session file handle
|
|
*
|
|
* ARGUMENTS:
|
|
* none
|
|
*
|
|
* RETURNS:
|
|
* SF_HANDLE or < 0 for error
|
|
*
|
|
*/
|
|
SF_HANDLE CreateSysFileHdl(void)
|
|
{
|
|
int uNdx;
|
|
|
|
for (uNdx = 0; uNdx < SESS_FILE_MAX; uNdx += 1)
|
|
{
|
|
/*
|
|
* See if an unused slot is available
|
|
*/
|
|
if (asSessionFiles[uNdx].uBusy == 0)
|
|
{
|
|
memset(&asSessionFiles[uNdx], 0, sizeof(stDSFP));
|
|
asSessionFiles[uNdx].uBusy = TRUE;
|
|
return (uNdx + 1);
|
|
}
|
|
}
|
|
|
|
return SF_ERR_BAD_PARAMETER;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfOpenSessionFile
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to build an in memory data structure that
|
|
* represents the data currently in a session file. If the file specified
|
|
* is not a valid session file, an error is returned.
|
|
*
|
|
* ARGUEMENTS:
|
|
* TCHAR *pszName -- the name of the session file.
|
|
*
|
|
* RETURNS:
|
|
* 0 or an error code < 0;
|
|
*/
|
|
int sfOpenSessionFile(const SF_HANDLE sF, const TCHAR *pszName)
|
|
{
|
|
int uRv = 0;
|
|
int uNdx = sF - 1;
|
|
unsigned long uSize, uSize1;
|
|
TCHAR *pszStr = NULL;
|
|
TCHAR *pszPtr = NULL;
|
|
HANDLE hFile;
|
|
int sID, sOldID;
|
|
int32 dwSZ;
|
|
int nOrderOK;
|
|
DWORD dw;
|
|
|
|
if (uNdx >= SESS_FILE_MAX)
|
|
{
|
|
uRv = SF_ERR_BAD_PARAMETER;
|
|
goto OSFexit;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].uBusy == 0)
|
|
{
|
|
uRv = SF_ERR_BAD_PARAMETER;
|
|
goto OSFexit;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].fOpen)
|
|
{
|
|
uRv = SF_ERR_FILE_ACCESS;
|
|
goto OSFexit;
|
|
}
|
|
|
|
if (pszName && (StrCharGetStrLength(pszName) > 0))
|
|
{
|
|
int nRv = -1;
|
|
pstDSFP pD;
|
|
pstDSII pI;
|
|
pstDSII pIx;
|
|
|
|
/*
|
|
* Do everything that can be done with a name
|
|
*/
|
|
asSessionFiles[uNdx].hFilename = (TCHAR *)malloc(FNAME_LEN * sizeof(TCHAR));
|
|
|
|
if (asSessionFiles[uNdx].hFilename == NULL)
|
|
goto OSFexit;
|
|
|
|
pszStr = asSessionFiles[uNdx].hFilename;
|
|
|
|
TCHAR_Fill(pszStr, TEXT('\0'), FNAME_LEN);
|
|
StrCharCopyN(pszStr, (LPTSTR)pszName, FNAME_LEN);
|
|
pszStr = NULL;
|
|
|
|
/*
|
|
* Try to open file. If we can then proceed
|
|
*/
|
|
hFile = CreateFile(pszName, GENERIC_READ, 0, NULL,
|
|
OPEN_EXISTING, 0, NULL);
|
|
|
|
/*
|
|
* Get the size of the file
|
|
*/
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
asSessionFiles[uNdx].fOpen = TRUE;
|
|
uRv = SF_ERR_FILE_ACCESS;
|
|
return uRv;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Allocate a data block
|
|
*/
|
|
asSessionFiles[uNdx].fOpen = TRUE;
|
|
|
|
uSize = GetFileSize(hFile, &dw);
|
|
uSize = ROUND_UP(uSize);
|
|
asSessionFiles[uNdx].dwDataSize = (int)uSize;
|
|
asSessionFiles[uNdx].dwDataUsed = 0;
|
|
asSessionFiles[uNdx].hData = (BYTE *)malloc(uSize);
|
|
|
|
if (asSessionFiles[uNdx].hData == 0)
|
|
{
|
|
uRv = SF_ERR_MEMORY_ERROR;
|
|
goto OSFexit;
|
|
}
|
|
|
|
pszStr = (TCHAR *)asSessionFiles[uNdx].hData;
|
|
pszPtr = pszStr;
|
|
memset(pszStr, 0, uSize * sizeof(TCHAR));
|
|
|
|
/*
|
|
* Read in the header and check it
|
|
*/
|
|
//fread(pszPtr, 1, HDR_SIZE, f);
|
|
if(HDR_SIZE > uSize)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_FORMAT;
|
|
goto OSFexit;
|
|
}
|
|
if (ReadFile(hFile, pszPtr, HDR_SIZE * sizeof(TCHAR), &dw, 0) == FALSE)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_ACCESS;
|
|
goto OSFexit;
|
|
}
|
|
|
|
if (memcmp(pszPtr, pszHdr, 10 * sizeof(TCHAR)) != 0)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_FORMAT;
|
|
goto OSFexit;
|
|
}
|
|
|
|
pszPtr += HDR_SIZE;
|
|
asSessionFiles[uNdx].dwDataUsed += HDR_SIZE;
|
|
|
|
/*
|
|
* Initialize the index
|
|
*/
|
|
asSessionFiles[uNdx].uItemCount = 0;
|
|
asSessionFiles[uNdx].uItemsAlloc = 64;
|
|
uSize1 = sizeof(stDSII) * 64;
|
|
asSessionFiles[uNdx].hIndex = (pstDSII)malloc(uSize1);
|
|
|
|
if (asSessionFiles[uNdx].hIndex == (pstDSII)0)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_MEMORY_ERROR;
|
|
goto OSFexit;
|
|
}
|
|
|
|
/*
|
|
* Read in the data items and add them to to structure
|
|
* The file is in the format:
|
|
*
|
|
* USHORT index
|
|
* DWORD dwSize
|
|
* CHAR * size
|
|
*/
|
|
|
|
pD = &asSessionFiles[uNdx];
|
|
|
|
pI = pD->hIndex;
|
|
|
|
nOrderOK = TRUE;
|
|
sOldID = 0;
|
|
|
|
for (;;)
|
|
{
|
|
sID = 0;
|
|
dwSZ = -1;
|
|
|
|
if (ReadFile(hFile, &sID, sizeof(SHORT), &dw, 0) == FALSE)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_ACCESS;
|
|
goto OSFexit;
|
|
}
|
|
if (ReadFile(hFile, &dwSZ, sizeof(DWORD), &dw, 0) == FALSE)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_ACCESS;
|
|
goto OSFexit;
|
|
}
|
|
|
|
if ((sID == 0) && (dwSZ == -1))
|
|
break;
|
|
|
|
if ((sID == 0) && (dwSZ == 0))
|
|
continue;
|
|
|
|
if (sOldID > sID)
|
|
{
|
|
nOrderOK = FALSE;
|
|
pI = (pstDSII)0;
|
|
pszStr = NULL;
|
|
}
|
|
|
|
sOldID = sID; /* For next time around */
|
|
|
|
#if defined(DEBUG_OUTPUT)
|
|
wsprintf(acBuffer,
|
|
"r %c %d(0x%x) %d\r\n",
|
|
nOrderOK ? 'a' : 'i',
|
|
sID, sID, dwSZ);
|
|
OutputDebugString(acBuffer);
|
|
#endif
|
|
|
|
if (nOrderOK)
|
|
{
|
|
// Do it inline
|
|
|
|
if (pD->uItemCount >= pD->uItemsAlloc)
|
|
{
|
|
#if defined(DEBUG_OUTPUT)
|
|
OutputDebugString("Index expanded\r\n");
|
|
#endif
|
|
/*
|
|
* We need to get a bigger chunk of memory
|
|
*/
|
|
if (pD->hIndex == (pstDSII)0)
|
|
{
|
|
pD->uItemsAlloc = 64;
|
|
pD->hIndex = (pstDSII)malloc(sizeof(stDSII) * 64);
|
|
}
|
|
else
|
|
{
|
|
int newSize = pD->uItemsAlloc * 2;
|
|
stDSII * pTemphIndex = NULL;
|
|
|
|
pTemphIndex = (pstDSII)
|
|
realloc(pD->hIndex, (size_t)newSize * sizeof(stDSII));
|
|
|
|
if (pTemphIndex == NULL)
|
|
{
|
|
uRv = SF_ERR_MEMORY_ERROR;
|
|
goto OSFexit;
|
|
}
|
|
else
|
|
{
|
|
pD->uItemsAlloc = newSize;
|
|
pD->hIndex = pTemphIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pD->hData == 0)
|
|
{
|
|
pD->hData = (BYTE *)malloc(ROUND_UP(4096));
|
|
pD->dwDataSize = ROUND_UP(4096);
|
|
pD->dwDataUsed = 0;
|
|
}
|
|
|
|
/*
|
|
* Add the item at the end of the list
|
|
*/
|
|
nRv = pD->uItemCount;
|
|
|
|
pIx = pI;
|
|
pIx += nRv;
|
|
|
|
pIx->uIndex = sID;
|
|
pIx->dwSize = dwSZ;
|
|
pIx->dwOffset = (DWORD)(pszPtr - pszStr);
|
|
|
|
pD->uItemCount += 1;
|
|
|
|
//fread(pszPtr, sSZ, 1, f);
|
|
if( (DWORD)dwSZ > uSize )
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_FORMAT;
|
|
goto OSFexit;
|
|
}
|
|
if (ReadFile(hFile, pszPtr, (DWORD)dwSZ, &dw, 0) == FALSE)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_ACCESS;
|
|
goto OSFexit;
|
|
}
|
|
|
|
pszPtr += dwSZ;
|
|
asSessionFiles[uNdx].dwDataUsed += dwSZ;
|
|
}
|
|
else
|
|
{
|
|
TCHAR acBuffer[FNAME_LEN];
|
|
|
|
//fread(acBuffer, dwSZ, 1, f);
|
|
if( (DWORD)dwSZ > sizeof(acBuffer) )
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_FORMAT;
|
|
goto OSFexit;
|
|
}
|
|
|
|
if (ReadFile(hFile, acBuffer, (DWORD)dwSZ, &dw, 0) == FALSE)
|
|
{
|
|
CloseHandle(hFile);
|
|
uRv = SF_ERR_FILE_ACCESS;
|
|
goto OSFexit;
|
|
}
|
|
sfPutSessionItem(uNdx + 1, (unsigned int)sID,
|
|
(unsigned long)dwSZ, acBuffer);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Free things up
|
|
*/
|
|
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
return SF_OK;
|
|
}
|
|
|
|
OSFexit:
|
|
if (uNdx != SESS_FILE_MAX)
|
|
{
|
|
/*
|
|
* General cleanup
|
|
*/
|
|
if (asSessionFiles[uNdx].hFilename)
|
|
{
|
|
free(asSessionFiles[uNdx].hFilename);
|
|
asSessionFiles[uNdx].hFilename = NULL;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].hData)
|
|
{
|
|
free(asSessionFiles[uNdx].hData);
|
|
asSessionFiles[uNdx].hData = NULL;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].hIndex)
|
|
{
|
|
free(asSessionFiles[uNdx].hIndex);
|
|
asSessionFiles[uNdx].hIndex = NULL;
|
|
}
|
|
|
|
memset(&asSessionFiles[uNdx], 0, sizeof(stDSFP));
|
|
}
|
|
|
|
return uRv;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfFlushSessionFile
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to write all of the data in a session file out to
|
|
* disk and release any and all memory associated with the session file handle.
|
|
* It will not do anything if the session file does not have a file name
|
|
* associated with it.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
*
|
|
* RETURNS:
|
|
* ZERO if the file is written, an error code < 0 if there is and error.
|
|
*/
|
|
int sfFlushSessionFile(const SF_HANDLE sF)
|
|
{
|
|
int nRv = 0;
|
|
int uNdx = sF - 1;
|
|
int x;
|
|
USHORT usIndex;
|
|
TCHAR *pszName;
|
|
TCHAR *pszPtr;
|
|
pstDSII pI;
|
|
HANDLE hFile;
|
|
DWORD dw;
|
|
|
|
if (uNdx >= SESS_FILE_MAX)
|
|
{
|
|
nRv = SF_ERR_BAD_PARAMETER;
|
|
goto CSFexit;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].uBusy == 0)
|
|
{
|
|
nRv = SF_ERR_BAD_PARAMETER;
|
|
goto CSFexit;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].fOpen == 0)
|
|
{
|
|
nRv = SF_ERR_FILE_ACCESS;
|
|
goto CSFexit;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].uChanged != 0)
|
|
{
|
|
if (asSessionFiles[uNdx].hFilename == NULL)
|
|
{
|
|
nRv = SF_ERR_FILE_ACCESS;
|
|
goto CSFexit;
|
|
}
|
|
|
|
pszName = asSessionFiles[uNdx].hFilename;
|
|
|
|
/* TODO: put in code to create directorys as necessary */
|
|
|
|
//f = fopen(pszName, "wb");
|
|
|
|
hFile = CreateFile(pszName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
nRv = SF_ERR_FILE_ACCESS;
|
|
goto CSFexit;
|
|
}
|
|
|
|
pszPtr = (TCHAR *)asSessionFiles[uNdx].hData;
|
|
|
|
/*
|
|
* Write out the header first
|
|
*/
|
|
if (StrCharGetStrLength(pszPtr) == 0)
|
|
{
|
|
/*
|
|
* Write out an empty header
|
|
*/
|
|
WriteFile(hFile, pszHdr, HDR_SIZE * sizeof(TCHAR), &dw, 0);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Write out the current header
|
|
*/
|
|
WriteFile(hFile, pszPtr, HDR_SIZE * sizeof(TCHAR), &dw, 0);
|
|
}
|
|
|
|
pszPtr += HDR_SIZE;
|
|
|
|
|
|
pI = asSessionFiles[uNdx].hIndex;
|
|
|
|
/*
|
|
* We loop thru the index and write out all of the stuff
|
|
*/
|
|
for (x = 0; x < asSessionFiles[uNdx].uItemCount; x += 1)
|
|
{
|
|
if (pI->dwSize != 0)
|
|
{
|
|
#if defined(DEBUG_OUTPUT)
|
|
unsigned char acBuffer[64];
|
|
|
|
wsprintf(acBuffer,
|
|
"w %d(0x%x) %d\r\n",
|
|
pI->uIndex, pI->uIndex, pI->dwSize);
|
|
OutputDebugString(acBuffer);
|
|
#endif
|
|
|
|
usIndex = (USHORT)pI->uIndex;
|
|
WriteFile(hFile, &usIndex, sizeof(USHORT), &dw, 0);
|
|
WriteFile(hFile, &pI->dwSize, sizeof(DWORD), &dw, 0);
|
|
|
|
WriteFile(hFile, pszPtr, (size_t)pI->dwSize * sizeof(TCHAR),
|
|
&dw, 0);
|
|
|
|
pszPtr += pI->dwSize;
|
|
}
|
|
pI += 1;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
asSessionFiles[uNdx].uChanged = 0;
|
|
|
|
// Finally, notify the shell so it can update the icon.
|
|
//
|
|
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH,
|
|
asSessionFiles[uNdx].hFilename, 0);
|
|
}
|
|
|
|
CSFexit:
|
|
|
|
return nRv;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfReleaseSessionFile
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to release any and all memory associated with the
|
|
* session file handle. This function by itself DOES NOT write any data out
|
|
* to the file. That must be done elsewhere.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
*
|
|
* RETURNS:
|
|
* ZERO if everything is OK, otherwise an error code < 0.
|
|
*/
|
|
int sfReleaseSessionFile(const SF_HANDLE sF)
|
|
{
|
|
unsigned int uNdx = (unsigned int)sF - 1;
|
|
|
|
if (uNdx > SESS_FILE_MAX)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (asSessionFiles[uNdx].uBusy == 0)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
asSessionFiles[uNdx].uBusy = 0;
|
|
|
|
if (asSessionFiles[uNdx].hFilename)
|
|
{
|
|
free(asSessionFiles[uNdx].hFilename);
|
|
asSessionFiles[uNdx].hFilename = NULL;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].hData)
|
|
{
|
|
free(asSessionFiles[uNdx].hData);
|
|
asSessionFiles[uNdx].hData = NULL;
|
|
}
|
|
|
|
if (asSessionFiles[uNdx].hIndex)
|
|
{
|
|
free(asSessionFiles[uNdx].hIndex);
|
|
asSessionFiles[uNdx].hIndex = NULL;
|
|
}
|
|
|
|
memset(&asSessionFiles[uNdx], 0, sizeof(stDSFP));
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfCloseSessionFile
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to release any and all memory associated with the
|
|
* session file handle. This function by itself DOES NOT write any data out
|
|
* to the file. That must be done elsewhere.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
*
|
|
* RETURNS:
|
|
* ZERO if everything is OK, otherwise an error code < 0.
|
|
*/
|
|
int sfCloseSessionFile(const SF_HANDLE sF)
|
|
{
|
|
int rV1, rV2;
|
|
|
|
rV1 = sfFlushSessionFile(sF);
|
|
rV2 = sfReleaseSessionFile(sF);
|
|
|
|
if (rV1 != 0)
|
|
return rV1;
|
|
|
|
return rV2;
|
|
}
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfGetSessionFileName
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to return the file name currently associated with
|
|
* the session file handle.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
* INT nSize -- the size of the following buffer
|
|
* PCHAR pszName -- the address of the buffer to copy the name to
|
|
*
|
|
* RETURNS:
|
|
* ZERO if everything is OK, otherwise an error code < 0;
|
|
*/
|
|
int sfGetSessionFileName(const SF_HANDLE sF, const int nSize, TCHAR *pszName)
|
|
{
|
|
int uNdx = sF - 1;
|
|
#if DEADWOOD
|
|
TCHAR *pszStr = NULL;
|
|
int len;
|
|
#endif
|
|
|
|
if (uNdx > SESS_FILE_MAX)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (asSessionFiles[uNdx].uBusy == 0)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (asSessionFiles[uNdx].hFilename == NULL)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
//
|
|
// Use StrCharCopyN() to copy the filename into the buffer passed.
|
|
// This will localize our revisions to the string manipulation
|
|
// functions if needed at a later date. REV: 03/01/2001
|
|
//
|
|
#if DEADWOOD
|
|
pszStr = asSessionFiles[uNdx].hFilename;
|
|
|
|
//strncpy(pszName, pszStr, nSize);
|
|
|
|
|
|
// JYF 03-Dec-1998 we don't want to read more than strlen
|
|
// of pszStr and nSize so not to read from inaccessible
|
|
// memory when running with debug heap.
|
|
|
|
len = min (nSize, lstrlen (pszStr)+1);
|
|
MemCopy(pszName, pszStr, (size_t)len * sizeof(TCHAR));
|
|
pszName[nSize-1] = TEXT('\0');
|
|
#else
|
|
StrCharCopyN(pszName, asSessionFiles[uNdx].hFilename, nSize);
|
|
#endif
|
|
|
|
return SF_OK;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfSetSessionFileName
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to change the name currently associated with the
|
|
* session file handle. It does not cause the session file handle to reload
|
|
* any data or access the disk at all. Data files are read when the session
|
|
* file is opened and written when the session file is closed.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
* PCHAR pszName -- the address of the new file name
|
|
*
|
|
* RETURNS:
|
|
* ZERO if everything is OK, otherwise and error code < 0;
|
|
*/
|
|
int sfSetSessionFileName(const SF_HANDLE sF, const TCHAR *pszName)
|
|
{
|
|
unsigned int uNdx = (unsigned int)sF - 1;
|
|
TCHAR *pszStr = NULL;
|
|
|
|
if (uNdx > SESS_FILE_MAX)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (asSessionFiles[uNdx].uBusy == 0)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (asSessionFiles[uNdx].fOpen == 0)
|
|
return SF_ERR_FILE_ACCESS;
|
|
|
|
if (asSessionFiles[uNdx].hFilename == NULL)
|
|
{
|
|
asSessionFiles[uNdx].hFilename = (TCHAR *)malloc(FNAME_LEN * sizeof(TCHAR));
|
|
|
|
if (asSessionFiles[uNdx].hFilename == NULL)
|
|
return SF_ERR_MEMORY_ERROR;
|
|
}
|
|
|
|
pszStr = asSessionFiles[uNdx].hFilename;
|
|
|
|
TCHAR_Fill(pszStr, TEXT('\0'), FNAME_LEN);
|
|
StrCharCopyN(pszStr, (LPTSTR)pszName, FNAME_LEN);
|
|
pszStr = NULL;
|
|
|
|
asSessionFiles[uNdx].uChanged = 1;
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfGetSessionItem
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to get data from the session file handle. It can
|
|
* also be used to get the size of a data item.
|
|
*
|
|
* If the last arguement, pvData, is NULL, then the size of the item is
|
|
* returned in *pulSize. If pvData is not NULL, up to *pulSize bytes are
|
|
* returned at pvData. If the number of bytes returned is less than *pulData,
|
|
* the new size is set in *pulSize.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
* uId -- ID if the item
|
|
* pulSize -- where the size is found or returned
|
|
* pvData -- where the data is to be placed
|
|
*
|
|
* RETURNS:
|
|
* ZERO if everything is OK, otherwise and error code < 0;
|
|
*/
|
|
int sfGetSessionItem(const SF_HANDLE sF,
|
|
const unsigned int uId,
|
|
unsigned long *pulSize,
|
|
void *pvData)
|
|
{
|
|
int lReturn = SF_ERR_BAD_PARAMETER;
|
|
int uNdx = sF - 1;
|
|
int dwMinSize;
|
|
int low;
|
|
int mid;
|
|
int high;
|
|
pstDSII pI;
|
|
pstDSII pIx;
|
|
BYTE * pszData;
|
|
|
|
if (uNdx > SESS_FILE_MAX)
|
|
{
|
|
lReturn = SF_ERR_BAD_PARAMETER;
|
|
}
|
|
else if (uNdx < 0)
|
|
{
|
|
lReturn = SF_ERR_BAD_PARAMETER;
|
|
}
|
|
else if (asSessionFiles[uNdx].uBusy == 0)
|
|
{
|
|
lReturn = SF_ERR_BAD_PARAMETER;
|
|
}
|
|
else if (asSessionFiles[uNdx].fOpen == 0)
|
|
{
|
|
lReturn = SF_ERR_FILE_ACCESS;
|
|
}
|
|
else if (asSessionFiles[uNdx].uItemCount == 0)
|
|
{
|
|
lReturn = SF_ERR_BAD_PARAMETER;
|
|
}
|
|
else if ((uId < 1) || (uId > 0x7FFF))
|
|
{
|
|
lReturn = SF_ERR_BAD_PARAMETER;
|
|
}
|
|
/*
|
|
* See if the item is in the index
|
|
*/
|
|
else if (asSessionFiles[uNdx].hIndex == (pstDSII)0)
|
|
{
|
|
lReturn = SF_ERR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
pI = asSessionFiles[uNdx].hIndex;
|
|
|
|
low = 0;
|
|
high = asSessionFiles[uNdx].uItemCount - 1;
|
|
|
|
while (low <= high)
|
|
{
|
|
mid = (low + high) / 2;
|
|
pIx = pI + mid;
|
|
|
|
if ((int)uId < pIx->uIndex)
|
|
{
|
|
high = mid - 1;
|
|
}
|
|
else if ((int)uId > pIx->uIndex)
|
|
{
|
|
low = mid + 1;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Found the item, see what they want to know
|
|
*/
|
|
if (pvData == NULL)
|
|
{
|
|
*pulSize = (unsigned long)pIx->dwSize;
|
|
}
|
|
else
|
|
{
|
|
pszData = asSessionFiles[uNdx].hData;
|
|
dwMinSize = (int)*pulSize;
|
|
|
|
if (dwMinSize > pIx->dwSize)
|
|
{
|
|
dwMinSize = pIx->dwSize;
|
|
}
|
|
|
|
if (dwMinSize)
|
|
{
|
|
MemCopy(pvData, pszData + pIx->dwOffset, (size_t)dwMinSize);
|
|
}
|
|
}
|
|
|
|
lReturn = SF_OK;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfCompareSessionItem
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to check and see if an item exists in the data
|
|
* and if it is the same as the passed in item.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
* uId -- the ID of the item
|
|
* ulSize -- the size of the item
|
|
* pvData -- address of the data
|
|
*
|
|
* RETURNS:
|
|
* TRUE if the two items are the same, otherwise false.
|
|
*/
|
|
int sfCompareSessionItem(const SF_HANDLE sF,
|
|
const unsigned int uId,
|
|
const unsigned long ulSize,
|
|
const void *pvData)
|
|
{
|
|
int uNdx = sF - 1;
|
|
int low, mid, high;
|
|
pstDSII pI;
|
|
pstDSII pIx;
|
|
BYTE *pszData;
|
|
|
|
/*
|
|
* See if the item is in the index
|
|
*/
|
|
if (asSessionFiles[uNdx].hIndex == (pstDSII)0)
|
|
return FALSE;
|
|
|
|
pI = asSessionFiles[uNdx].hIndex;
|
|
|
|
low = 0;
|
|
high = asSessionFiles[uNdx].uItemCount - 1;
|
|
|
|
while (low <= high)
|
|
{
|
|
mid = (low + high) / 2;
|
|
pIx = pI + mid;
|
|
|
|
if ((int)uId < pIx->uIndex)
|
|
high = mid - 1;
|
|
|
|
else if ((int)uId > pIx->uIndex)
|
|
low = mid + 1;
|
|
|
|
else
|
|
{
|
|
/*
|
|
* Check and see if the sizes are the same
|
|
*/
|
|
if (ulSize != (unsigned long)pIx->dwSize)
|
|
return FALSE;
|
|
|
|
/*
|
|
* Check and see if the data is the same
|
|
*/
|
|
pszData = asSessionFiles[uNdx].hData + pIx->dwOffset;
|
|
|
|
if (memcmp((BYTE *)pvData, pszData, ulSize) == 0)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: sfPutSessionItem
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to add or modify an entry in the session file data
|
|
* associated with the current session file handle. It does not cause the
|
|
* actual session file itself to be written. That is done only when the
|
|
* session file handle is closed.
|
|
*
|
|
* ARGUEMENTS:
|
|
* SF_HANDLE sF -- the session file handle
|
|
* uId -- the ID of the item
|
|
* ulSize -- the size of the item
|
|
* pvData -- address of the data
|
|
*
|
|
* RETURNS:
|
|
* ZERO if everything is OK, otherwise and error code < 0;
|
|
*/
|
|
int sfPutSessionItem(const SF_HANDLE sF,
|
|
const unsigned int uId,
|
|
const unsigned long ulSize,
|
|
const void *pvData)
|
|
{
|
|
int uNdx = sF - 1;
|
|
int x, y;
|
|
int32 dwSlide;
|
|
int32 dwOffset;
|
|
int32 dwNewSize;
|
|
pstDSII pI;
|
|
pstDSII pIx, pIy;
|
|
BYTE *pszData;
|
|
|
|
#if defined(DEBUG_OUTPUT)
|
|
unsigned char acBuffer[80];
|
|
#endif
|
|
|
|
if (uNdx > SESS_FILE_MAX)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (asSessionFiles[uNdx].uBusy == 0)
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (asSessionFiles[uNdx].fOpen == 0)
|
|
return SF_ERR_FILE_ACCESS;
|
|
|
|
if ((uId < 1) || (uId > 0x7FFF))
|
|
return SF_ERR_BAD_PARAMETER;
|
|
|
|
if (sfCompareSessionItem(sF, uId, ulSize, pvData))
|
|
return SF_OK;
|
|
|
|
x = sfAddToIndex(uNdx, (unsigned short)uId, 0, 0);
|
|
|
|
pI = asSessionFiles[uNdx].hIndex;
|
|
|
|
if (x != (-1))
|
|
{
|
|
pIx = pI + x;
|
|
if (pIx->dwSize == 0)
|
|
{
|
|
/*
|
|
* Its a new item
|
|
*/
|
|
dwSlide = (int32)ulSize;
|
|
if (x == 0)
|
|
dwOffset = HDR_SIZE;
|
|
else
|
|
dwOffset = (pI+x-1)->dwOffset + (pI+x-1)->dwSize;
|
|
|
|
#if defined(DEBUG_OUTPUT)
|
|
wsprintf(acBuffer,
|
|
"New 0x%x slide %d offset 0x%x",
|
|
uId, dwSlide, dwOffset);
|
|
OutputDebugString(acBuffer);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Its a replacement item
|
|
*/
|
|
dwSlide = (int)ulSize - (int)pIx->dwSize;
|
|
dwOffset = pIx->dwOffset;
|
|
|
|
#if defined(DEBUG_OUTPUT)
|
|
wsprintf(acBuffer,
|
|
"Rep 0x%x slide %d offset 0x%x",
|
|
uId, dwSlide, dwOffset);
|
|
OutputDebugString(acBuffer);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Check the memory requirements
|
|
*/
|
|
dwNewSize = asSessionFiles[uNdx].dwDataUsed + dwSlide;
|
|
|
|
if (dwNewSize > asSessionFiles[uNdx].dwDataSize)
|
|
{
|
|
/*
|
|
* Need to allocate a new chunk of memory
|
|
*/
|
|
BYTE *hG =(BYTE *)
|
|
realloc(asSessionFiles[uNdx].hData, ROUND_UP(dwNewSize));
|
|
|
|
if (hG == NULL)
|
|
{
|
|
return SF_ERR_MEMORY_ERROR;
|
|
}
|
|
else
|
|
{
|
|
asSessionFiles[uNdx].hData = hG;
|
|
asSessionFiles[uNdx].dwDataSize = ROUND_UP(dwNewSize);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Move the old data to the point necessary
|
|
*/
|
|
pszData = asSessionFiles[uNdx].hData;
|
|
asSessionFiles[uNdx].dwDataUsed = dwNewSize;
|
|
|
|
if (dwSlide < 0)
|
|
{
|
|
/* shrink the current space */
|
|
dwNewSize = asSessionFiles[uNdx].dwDataSize;
|
|
dwNewSize -= dwOffset;
|
|
dwNewSize += dwSlide;
|
|
|
|
memmove(pszData + dwOffset, /* destination */
|
|
pszData + dwOffset - dwSlide, /* source */
|
|
(size_t)(dwNewSize - 1)); /* count */
|
|
|
|
#if defined(DEBUG_OUTPUT)
|
|
wsprintf(acBuffer,
|
|
" shrink from 0x%lx to 0x%lx size 0x%x\r\n",
|
|
(long)(pszData + dwOffset - dwSlide),
|
|
(long)(pszData + dwOffset),
|
|
dwNewSize -1);
|
|
OutputDebugString(acBuffer);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* expand the current space */
|
|
dwNewSize = asSessionFiles[uNdx].dwDataSize;
|
|
dwNewSize -= dwOffset;
|
|
dwNewSize -= dwSlide;
|
|
|
|
memmove(pszData + dwOffset + dwSlide, /* destination */
|
|
pszData + dwOffset, /* source */
|
|
(size_t)(dwNewSize - 1)); /* count */
|
|
|
|
#if defined(DEBUG_OUTPUT)
|
|
wsprintf(acBuffer,
|
|
" expand from 0x%lx to 0x%lx size 0x%x\r\n",
|
|
(long)(pszData + dwOffset),
|
|
(long)(pszData + dwOffset + dwSlide),
|
|
dwNewSize - 1);
|
|
OutputDebugString(acBuffer);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Copy in the new data
|
|
*/
|
|
memmove(pszData + dwOffset, /* destination */
|
|
pvData, /* source */
|
|
(unsigned int)ulSize); /* count */
|
|
|
|
|
|
/*
|
|
* Update the item in the index for the current item
|
|
*/
|
|
pIx->dwSize = (int32)ulSize;
|
|
pIx->dwOffset = dwOffset;
|
|
|
|
/*
|
|
* Adjust all the following items in the index
|
|
*/
|
|
for (y = x + 1; y < (int)asSessionFiles[uNdx].uItemCount; y += 1)
|
|
{
|
|
pIy = pI + y;
|
|
pIy->dwOffset += dwSlide;
|
|
}
|
|
|
|
asSessionFiles[uNdx].uChanged = 1;
|
|
return 0;
|
|
}
|
|
|
|
return SF_ERR_BAD_PARAMETER;
|
|
}
|