www.pudn.com > IpFilter.rar > cpprun.cpp


/////////////////////////////////////////////////////////////////////////////// 
// 
// Copyright (C) 1999 - 2000 Mark Roddy 
// 
//	Hollis Technology Solutions 
//	94 Dow Road 
//	Hollis, NH 03049 
//	info@hollistech.com 
//	www.hollistech.com 
// 
// This library is free software; you can redistribute it and/or 
// modify it under the terms of the GNU Lesser General Public 
// License as published by the Free Software Foundation; either 
// version 2 of the License, or (at your option) any later version. 
// 
// This library is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
// Lesser General Public License for more details. 
// 
// You should have received a copy of the GNU Lesser General Public 
// License along with this library; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
// 
// www.fsf.org 
// 
// 
// 
//	Synopsis:  
//  
// 
//	Version Information: 
// 
//	$Header: /cpprun/sys/cpplib/cpprun.cpp 4     1/01/00 11:00p Markr $  
// 
/////////////////////////////////////////////////////////////////////////////// 
#define HTS_UNIQUE_FILE_ID 0x1204002 
 
#include "htscpp_internal.h" 
 
// 
// we appropriate DriverEntry so the driver must use another name for this routine. 
// 
 
 
#ifdef __cplusplus 
extern "C" { 
#endif 
 
    NTSTATUS 
    Cp_DriverEntry(PDRIVER_OBJECT DriverObject, 
                   PUNICODE_STRING RegistryPath);  
    NTSTATUS 
    DriverEntry(PDRIVER_OBJECT DriverObject, 
                   PUNICODE_STRING RegistryPath); 
 
#ifdef __cplusplus 
} 
#endif  /* __cplusplus */ 
 
 
static 
void __cdecl onexitinit ( 
        void 
        ); 
static  
PVFV __cdecl onexit ( 
        PVFV func 
        ); 
static 
void __cdecl callPVFVArray ( 
        PVFV * pfbegin, 
        PVFV * pfend 
        ); 
static 
void __cdecl doexit ( 
        int code, 
        int quick, 
        int retcaller 
        ); 
 
 
static VOID 
    _CppDriverUnload(PDRIVER_OBJECT DriverObject); 
 
static PDRIVER_UNLOAD clientUnload = NULL; 
 
NTSTATUS 
DriverEntry(PDRIVER_OBJECT DriverObject, 
               PUNICODE_STRING RegistryPath) 
 
{ 
 
    onexitinit(); 
     
 
    callPVFVArray(__crtXca, __crtXcz); 
 
 
    // 
    // call the clients driver entry routine. 
    // 
 
    NTSTATUS Status = Cp_DriverEntry(DriverObject, RegistryPath); 
 
    if (NT_SUCCESS(Status)) { 
 
        // 
        // we have to steal the unload vector if it exists 
        // 
        if (DriverObject->DriverUnload) { 
 
            clientUnload = DriverObject->DriverUnload; 
            DriverObject->DriverUnload = _CppDriverUnload; 
        } 
 
    } else { 
        // 
        // call the d'tors for global and static objects? 
        // 
        doexit (0, 0, 1); 
    } 
    return Status; 
} 
 
static 
VOID 
    _CppDriverUnload(PDRIVER_OBJECT DriverObject) 
{ 
     
    // 
    // call the clients unload routine 
    // 
    if (clientUnload) { 
 
        clientUnload(DriverObject); 
 
    } 
 
    // 
    // do what is appropriate for destorying global objects 
    // 
    doexit (0, 0, 1); 
 
    return; 
 
} 
 
// 
// this must be externally visible! 
// 
int __cdecl atexit ( 
        PVFV func 
        ) 
{ 
        return (onexit(func) == NULL) ? -1 : 0; 
} 
 
// 
// this was "initterm" but we ain't initting any 'terms' I can think 
// of. What we are doing is calling an array of functions. 
// 
void __cdecl callPVFVArray ( 
        PVFV * pfbegin, 
        PVFV * pfend 
        ) 
{ 
     
    while ( pfbegin < pfend ) 
    { 
        /* 
         * if current table entry is non-NULL, call thru it. 
         */ 
        if ( *pfbegin != NULL ) 
            (**pfbegin)(); 
        ++pfbegin; 
    } 
} 
 
// 
// the CRT code had some ugly stuff that created a variable length array of 
// function pointers. This was scrapped in favor of a linked list. 
// 
 
typedef struct { 
    LIST_ENTRY  link; // double linked list of exit functions 
    PVFV         exitFunc; 
} EXIT_FUNC_LIST, *PEXIT_FUNC_LIST; 
 
LIST_ENTRY exitList; 
 
 
void __cdecl onexitinit ( 
        void 
        ) 
{ 
    // 
    // this is a bit easier 
    // 
    InitializeListHead(&exitList); 
 
} 
 
PVFV __cdecl onexit ( 
        PVFV func 
        ) 
 
{ 
    PEXIT_FUNC_LIST pFuncListEntry =  
        (PEXIT_FUNC_LIST)malloc(sizeof(EXIT_FUNC_LIST), 'EPcO'); 
 
    if (!pFuncListEntry) { 
 
        return NULL; 
    } 
    pFuncListEntry->exitFunc = func; 
 
    // 
    // gee, creating a lifo list is rather trivial 
    // 
    InsertHeadList(&exitList, &pFuncListEntry->link); 
         
    return func; 
} 
 
void drainExit() 
{ 
    PEXIT_FUNC_LIST pFuncListEntry; 
 
    while(!IsListEmpty(&exitList)) { 
 
        // 
        // this cast relies on link being the first field of 
        // EXIT_FUNC_LIST. 
        //         
        pFuncListEntry = (PEXIT_FUNC_LIST) RemoveHeadList(&exitList); 
        AssertAlways((PVOID) pFuncListEntry == (PVOID)&pFuncListEntry->link); 
 
        // 
        // wrap this in a try/except handler? 
        // 
        if (pFuncListEntry->exitFunc) { 
 
            pFuncListEntry->exitFunc(); 
 
        } 
 
        free(pFuncListEntry); 
    } 
 
} 
 
void __cdecl doexit ( 
        int code, 
        int quick, 
        int retcaller 
        ) 
{ 
 
    if (!quick) { 
       
        drainExit(); 
 
         
    } 
 
     
    return; 
 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//  
// Change History Log 
// 
// $Log: /cpprun/sys/cpplib/cpprun.cpp $ 
//  
// 4     1/01/00 11:00p Markr 
//  
// 3     12/31/99 4:29p Markr 
//  
// 2     12/17/99 8:30a Markr 
// 
///////////////////////////////////////////////////////////////////////////////