home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cset21v6.zip
/
MMPM2TK
/
TK
/
FSSHT
/
SHINIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-25
|
18KB
|
414 lines
/****************************************************************************/
/* */
/* Copyright (c) IBM Corporation 1992, 1993 */
/* All Rights Reserved */
/* */
/* SOURCE FILE NAME: SHINIT.C */
/* */
/* DESCRIPTIVE NAME: Stream Handler Dll Initialization routine */
/* */
/* FUNCTION: This function is called each time a new process loads this */
/* DLL. If this is the first call, we must register with the */
/* SSM as a handler. For each call, we need to allocate any */
/* resources needed on a process basis (GetSeg's, etc), and */
/* set up an exit list routine to deallocate these resources. */
/* */
/* ENTRY POINTS: */
/* _DLL_InitTerm */
/* ShExitList */
/*************************** END OF SPECIFICATIONS **************************/
#ifdef MMRAS
#define MMRAS_PTRACE
#endif
#ifdef PTRACE
#define MMRAS_PTRACE
#endif
#define INCL_NOPMAPI /* no PM include files required */
#define INCL_DOSSEMAPHORES
#define INCL_DOSPROCESS /* For exit list defines */
#define INCL_DOSERRORS
#define INCL_DOSMISC
#define INCL_DOSDEVICES
#include <os2.h>
#include <os2me.h>
#include <hhpheap.h>
#include <shi.h>
#ifdef MMRAS_PTRACE
#include <ptrace.h>
#endif
/************************** START OF SPECIFICATIONS *************************/
/* */
/* SUBROUTINE NAME: ShInit */
/* */
/* DESCRIPTIVE NAME: Stream Handler Initialization routine */
/* */
/* FUNCTION: DLL initialization routine, to set up control blocks, allocate */
/* storage etc. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: _DLL_InitTerm */
/* LINKAGE: CALL NEAR (0:32) */
/* */
/* INPUT: */
/* HMODULE hmod Module handle */
/* ULONG fTerm DLL termination flag */
/* */
/* EXIT-NORMAL: NO_ERROR (0) */
/* */
/* EXIT-ERROR: */
/* ERROR_ALLOC_RESOURCES */
/* */
/* SIDE EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: None */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* _CRT_init */
/* DosCreateMutexSem */
/* DosOpenMutexSem */
/* DosRequestMutexSem */
/* DosCloseMutexSem */
/* SMHEntryPoint */
/* HhpCreateHeap */
/* HhpAccessHeap */
/* DosExitList */
/* HhpReleaseHeap */
/* DosReleaseMutexSem */
/* */
/* DATA STRUCTURES: */
/* hmtxGlobalData */
/* hHeap */
/* */
/*************************** END OF SPECIFICATIONS **************************/
ULONG _DLL_InitTerm( HMODULE hmod, ULONG fTerm)
{ /* Start of ShInit */
RC rc = NO_ERROR; /* local return code */
PARM_REG smhRegParm; /* Parameters for SMH_REGISTER */
int Registered = FALSE;
int HeapAllocated_Attached = FALSE;
int GlobDataMtxCreated = FALSE;
hmod;
/*
* Checking this parameter will insure that this routine will only
* be run on an actual initialization. Return success from the
* termination.
*/
if (fTerm)
{
return (1L);
}
if (_CRT_init())
{
return (0L);
}
/*
* Get the semaphore controlling the process count & update the process
* count if successful. Then after we have the sem, if the count is
* one, we are guaranteed that we must do the global initializations.
*
* There is a problem that to determine if we need to create or open the
* semaphore we need to check the ProcessCount to see if this is the
* first process, but since we don't have the semaphore we don't have
* a guarentee the count won't change. If we get caught in this window
* then we will fail to get the semaphore and the rc will indicate error.
*/
if (ulProcessCount == 0)
{ /* First process */
if (!(rc = DosCreateMutexSem(pszProcCntMutexName,
&hmtxProcCnt,
0L,
TRUE)))
{
ulProcessCount++;
}
} /* First process */
else
{ /* not first process */
/* if a process exits and decrements ProcessCount before we get */
/* the semaphore here, we will fail. */
if (!(rc = DosOpenMutexSem(pszProcCntMutexName,
&hmtxProcCnt)))
{
if (!(rc = DosRequestMutexSem(hmtxProcCnt,
SEM_INDEFINITE_WAIT)))
{
ulProcessCount++;
}
else
{
DosCloseMutexSem(hmtxProcCnt);
}
}
} /* not first process */
if (!rc)
{ /* Semaphore ok, In critical section */
/*
* If this is the first time this init routine is called then we are
* being brought in by the loader the first time, so we need to register
* with the SSM.
*/
if (ulProcessCount == 1)
{ /* First process */
smhRegParm.ulFunction = SMH_REGISTER;
smhRegParm.pszSHName = pszHandlerName;
smhRegParm.phidSrc = &SrcHandlerID;
smhRegParm.phidTgt = &TgtHandlerID;
smhRegParm.pshcfnEntry = ( PSHCFN ) ShcRouter;
smhRegParm.ulFlags = 0L;
if (ulHandlerFlags & HANDLER_CAN_BE_SOURCE)
{
smhRegParm.ulFlags = REGISTER_SRC_HNDLR;
}
if (ulHandlerFlags & HANDLER_CAN_BE_TARGET)
{
smhRegParm.ulFlags |= REGISTER_TGT_HNDLR;
}
if (ulHandlerFlags & HANDLER_IS_NONSTREAMING)
{
smhRegParm.ulFlags |= REGISTER_NONSTREAMING;
}
rc = SMHEntryPoint((PVOID)&smhRegParm);
/*
* If ok then allocate our memory pool (heap), since it is under
* semaphore control create and get the semaphore first.
*/
if (!rc)
{ /* Register ok */
Registered = TRUE;
hHeap = HhpCreateHeap(HEAPSIZE,
HH_SHARED);
if (hHeap)
{ /* Heap Allocated */
HeapAllocated_Attached = TRUE;
if (!(rc = DosCreateMutexSem(NULL,
&hmtxGlobalData,
DC_SEM_SHARED,
FALSE)))
{
GlobDataMtxCreated = TRUE;
}
} /* Heap Allocated */
else
{ /* Heap not allocated */
rc = ERROR_ALLOC_RESOURCES;
} /* Heap not allocated */
} /* Register ok */
} /* First Process */
else
{ /* Not first process */
if (!(rc = DosOpenMutexSem(NULL,
&hmtxGlobalData)))
{ /* Global data semaphore opened */
GlobDataMtxCreated = TRUE;
if (!ENTERCRIT(rc))
{ /* Global Data Sem obtained */
if (HhpAccessHeap(hHeap, HhpGetPID()))
{ /* Error accessing heap */
rc = ERROR_ALLOC_RESOURCES;
} /* Error accessing heap */
else
{ /* Heap attached */
HeapAllocated_Attached = TRUE;
} /* Heap attached */
EXITCRIT;
} /* Global Data Sem obtained */
} /* Global data semaphore opened */
} /* Not first process */
/*
* If things are ok, Register an exit list handler and if that works
* increment the process count.
*/
if (!rc)
{
rc = DosExitList(EXTLSTADD_ORDER,
(PFNEXITLIST)ShExitList);
}
if (rc)
{ /* Error occurred - Clean Up */
if (HeapAllocated_Attached)
{
HhpReleaseHeap(hHeap,
HhpGetPID());
}
if (GlobDataMtxCreated)
{
DosCloseMutexSem(hmtxGlobalData);
}
if (Registered)
{ /* Deregister */
PARM_DEREG smhDeregParm;
smhDeregParm.ulFunction = SMH_DEREGISTER;
smhDeregParm.pszSHName = pszHandlerName;
SMHEntryPoint(&smhDeregParm);
} /* Deregister */
ulProcessCount--;
DosReleaseMutexSem(hmtxProcCnt);
DosCloseMutexSem(hmtxProcCnt);
} /* Error occurred - Clean Up */
else
{
#ifdef MMRAS_PTRACE
InitPTrace()
#endif
DosReleaseMutexSem(hmtxProcCnt);
}
} /* Semaphore ok, In critical section */
/*
* The return codes expected are:
* TRUE (any non-zero) - init routine worked
* FALSE (zero) - init routine failed
*
* So we have to reverse the local rc before we pass it back.
*/
return(!rc);
} /* End of SHInit */
/************************** START OF SPECIFICATIONS *************************/
/* */
/* SUBROUTINE NAME: ShExitList */
/* */
/* DESCRIPTIVE NAME: Stream Hanlder Exit List routine */
/* */
/* FUNCTION: Clean up resources allocated for each process, and if this is */
/* the last process, then deregister with the SSM. */
/* In all cases we need to destroy all streams owned by this */
/* process. */
/* */
/* ENTRY POINT: */
/* LINKAGE: CALL NEAR (0:32) */
/* */
/* INPUT: */
/* */
/* EXIT-NORMAL: NO_ERROR (0) */
/* */
/* EXIT-ERROR: */
/* None */
/* */
/* SIDE EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: None */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* HhpGetPID */
/* DosRequestMutexSem */
/* DosCloseMutexSem */
/* SMHEntryPoint */
/* HhpShcDestroy */
/* DosExitList */
/* HhpReleaseHeap */
/* DosReleaseMutexSem */
/* */
/* DATA STRUCTURES: */
/* hmtxGlobalData */
/* hHeap */
/* */
/*************************** END OF SPECIFICATIONS **************************/
VOID APIENTRY ShExitList()
{ /* Start of ShExitList */
PSIB psib; /* Stream instance block */
PSIB psibToDestroy = NULL; /* Stream instance block to destroy */
PARM_DESTROY dyparm; /* parameter block to destroy routine */
PID pid; /* Process ID */
RC rc; /* Return code */
/*
* There is nothing we can do if calls fail, so don't bother checking.
*/
DosRequestMutexSem(hmtxProcCnt, SEM_INDEFINITE_WAIT);
/*
* If this is the last process we will be removed from memory, so
* call SSM to deregister.
*/
if (ulProcessCount == 1)
{
PARM_DEREG smhDeregParm;
smhDeregParm.ulFunction = SMH_DEREGISTER;
smhDeregParm.pszSHName = pszHandlerName;
SMHEntryPoint(&smhDeregParm);
}
/* We need to call destroy for each stream created by this process. */
/* Get the PID, and the global data semaphore. */
/* Search the SIB chain for this process's stream instances. */
/* Call destroy to destroy the stream instances */
/* Release the global data semaphore */
pid = HhpGetPID();
ENTERCRIT(rc);
psib = pSIB_list_head;
while (psib)
{
if (psib->ProcessID == pid)
{
psibToDestroy = psib;
psib = psib->pnxtSIB;
if (psibToDestroy->ThreadID)
{
psibToDestroy->ulActionFlags |= SIBACTFLG_THREAD_DEAD;
}
dyparm.hstream = psibToDestroy->hStream;
dyparm.hid = psibToDestroy->HandlerID;
ShcDestroy(&dyparm);
}
else
{
psib = psib->pnxtSIB;
}
}
/*
* Unattach from the memory pool, and from the Global data semaphore
*/
HhpReleaseHeap(hHeap, pid);
EXITCRIT;
DosCloseMutexSem(hmtxGlobalData);
/* Clean up the process count variable and it's semaphore. */
ulProcessCount--;
DosReleaseMutexSem(hmtxProcCnt);
DosCloseMutexSem(hmtxProcCnt);
DosExitList(EXLST_EXIT, (PFNEXITLIST)ShExitList);
} /* End of ShExitList */