/********************************************************************
*	DrvIPC.c
*
*	Macintosh driver interprocess communication implementation.
*
*	Copyright (c) 1995-1997, Willows Software Inc.  All rights reserved.
********************************************************************/

/* System includes */
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include "windows.h"
#include "KrnAtoms.h"
#include "DrvHook.h"
#include "DrvIPC.h"
#include "Log.h"
#include "DrvSystem.h"

/* Local prototypes */
static BOOL DrvInitIPC(void);
static DWORD DrvInitAtomTable(LPATOMTABLE,LPSTR,LPSTR);
static DWORD DrvAtomData(WORD, LPATOMTABLE);


/********************************************************************
*   Interprocess Communications hook.
********************************************************************/
DWORD PrivateIPCHook(WORD wFunc, LPARAM dwParm1,LPARAM dwParm2, LPVOID lpStruct)
{

    switch (wFunc) {
	case DSUBSYSTEM_INIT:
		DrvInitIPC();
	    return 1L;

	case DSUBSYSTEM_GETCAPS:
	    return 0L;

	case DSUBSYSTEM_EVENTS:
	    return 0L;

	/* dwParm1 - pointer to table name */
	/* dwParm2 - pointer to data name */
	/* lpStruct - pointer to ATOMTABLE */
	case IPCH_INITATOMTABLE:
	    return DrvInitAtomTable((LPATOMTABLE)lpStruct, (LPSTR)dwParm1, (LPSTR)dwParm2);

	/* LOWORD(dwParm1) - subfunction */
	/* lpStruct - pointer to ATOMTABLE */
	case IPCH_GLOBALATOMDATA:
	    return DrvAtomData(LOWORD(dwParm1), (LPATOMTABLE)lpStruct);

	default:
	    return 0L;
    }
}


/********************************************************************
*   Interprocess Communications hook.
********************************************************************/
static BOOL DrvInitIPC(void)
{
	return FALSE;
}

/********************************************************************
*   Initialize a global atom table.
********************************************************************/
static DWORD DrvInitAtomTable(LPATOMTABLE lpAtomTable, LPSTR lpTableName, LPSTR lpDataName)
{
LPDRVATOMSTRUCT lpDrvAtomStruct;

    if ((lpAtomTable == 0) || (lpTableName == 0) || (lpDataName == 0))
		return 0L;

	/* Allocate the driver atom structure that keeps track of the "server" atoms. */	
    lpDrvAtomStruct = (LPDRVATOMSTRUCT)DrvMalloc(sizeof(DRVATOMSTRUCT));
    memset((LPSTR)lpDrvAtomStruct,'\0',sizeof(DRVATOMSTRUCT));

	/* LATER: Do a real atom mechanism, for now we just leave it alone */

	/*  Do not allocate any atoms yet, there are none. 	*/

    lpAtomTable->lpDrvData = (LPVOID)lpDrvAtomStruct;

    return 1L;
}

/********************************************************************
*   Initialize a global atom table.
********************************************************************/
static DWORD DrvAtomData(WORD wFunc, LPATOMTABLE lpAtomTable)
{
size_t	nSize;
LPDRVATOMSTRUCT lpDrvAtomStruct;

    if (lpAtomTable == 0)
		return 0L;

    if (lpAtomTable->lpDrvData == NULL)
		if (!DrvInitAtomTable(lpAtomTable,"_GlobalTable","_GlobalData"))
	    	return 0L;

    lpDrvAtomStruct = (LPDRVATOMSTRUCT)lpAtomTable->lpDrvData;

    if (wFunc == GAD_READONLY || wFunc == GAD_READWRITE) {
		/* lpDrvAtomStruct->XTable and XData are already valid for now */
		lpAtomTable->TableSize = lpDrvAtomStruct->DrvTableSize;
		lpAtomTable->DataSize = lpDrvAtomStruct->DrvDataSize;

		if (wFunc == GAD_READONLY) {
		    lpAtomTable->AtomTable = lpDrvAtomStruct->DrvTable;
	    	lpAtomTable->AtomData  = lpDrvAtomStruct->DrvData;
		    if (lpAtomTable->DataSize == 0) {
				lpAtomTable->AtomTable = 0;
				lpAtomTable->TableSize = 0;
	    	}
		}
		else {
	    	if ((lpAtomTable->TableSize == 0) || (lpAtomTable->DataSize == 0)) {
				lpAtomTable->AtomTable = 0;
				lpAtomTable->TableSize = 0;
				lpAtomTable->AtomData  = 0;
			}
	   		else {
				/* Make a copy of the "server" atom table to give to the library */
				/* Since the library will possibly re-allocate memory, it needs to */
				/*  be from the same memory pool, hence the callback. */
				nSize = lpAtomTable->TableSize*sizeof(ATOMENTRY);

				/* Free the previous atom table, which was originated from here */
				if (lpAtomTable->AtomTable)
					LibFree(lpAtomTable->AtomTable);
				if (lpAtomTable->AtomData)
					LibFree(lpAtomTable->AtomData);

				/* Create copies of the "server" atoms */
				lpAtomTable->AtomTable = (LPATOMENTRY) LibMalloc(nSize);
				memcpy((LPVOID)lpAtomTable->AtomTable, (LPVOID)lpDrvAtomStruct->DrvTable, nSize);

				lpAtomTable->AtomData =	(LPSTR)LibMalloc(lpAtomTable->DataSize);
				memcpy(lpAtomTable->AtomData, lpDrvAtomStruct->DrvData, lpAtomTable->DataSize);

		    }
		}
    }

    if (wFunc == GAD_UPDATE) {
		if (lpAtomTable->TableSize == 0 || lpAtomTable->DataSize == 0) {
			/* X would do a delete property here*/
		} else {
			/* The library will have and/or resized the table, so update our copy */
			nSize = lpAtomTable->TableSize*sizeof(ATOMENTRY);
			if (lpAtomTable->TableSize != lpDrvAtomStruct->DrvTableSize) {
				if (lpDrvAtomStruct->DrvTable)			/* Make sure there IS a server table */
					lpDrvAtomStruct->DrvTable = DrvRealloc(lpDrvAtomStruct->DrvTable, nSize);
				else
					lpDrvAtomStruct->DrvTable = DrvMalloc(nSize);
				lpDrvAtomStruct->DrvTableSize = lpAtomTable->TableSize;
			}
			memcpy(lpDrvAtomStruct->DrvTable, lpAtomTable->AtomTable, nSize);

			nSize = lpAtomTable->DataSize;
			if (lpAtomTable->DataSize != lpDrvAtomStruct->DrvDataSize) {
				if (lpDrvAtomStruct->DrvData)				/* Make sure there IS a server table */
					lpDrvAtomStruct->DrvData = DrvRealloc(lpDrvAtomStruct->DrvData, nSize);
				else
					lpDrvAtomStruct->DrvData = DrvMalloc(nSize);
				lpDrvAtomStruct->DrvDataSize = lpAtomTable->DataSize;
			}
			memcpy(lpDrvAtomStruct->DrvData, lpAtomTable->AtomData, nSize);

		}
    }

    return 1L;
}


