Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1685 lines
49 KiB

/*** amliapi.c - AMLI APIs
*
* Copyright (c) 1996,1997 Microsoft Corporation
* Author: Michael Tsang (MikeTs)
* Created 08/13/96
*
* MODIFICATION HISTORY
*/
#include "pch.h"
//#include "amlihook.h"
//#include "amlitest.h"
#ifdef LOCKABLE_PRAGMA
#pragma ACPI_LOCKABLE_DATA
#pragma ACPI_LOCKABLE_CODE
#endif
/*++
OSIAML contains the AML for the _OSI Method. This AML is generated from the following ASL:
Method(_OSI, 0x1, NotSerialized)
{
Return(OSI(Arg0))
}
--*/
UCHAR OSIAML[] = {
0xa4, 0xca, 0x68
};
/***EP AMLIInitialize - Initialize AML interpreter
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIInitialize | AML Interpreter initialization.
*
* This function must be called before any AML interpreter functions
* can be called. This function will typically allocate and
* initialize global resources, create the ACPI name space etc.
* It is typically called in the initialization of the ACPI core
* driver.
*
* @PARM ULONG | dwCtxtBlkSize | Specifies the size of Context blocks. If
* zero, use default context block size.
*
* @PARM ULONG | dwGlobalHeapBlkSize | Specifies the size of Global heap.
* If zero, use default global heap size.
*
* @PARM ULONG | dwfAMLIInit | AMLI initialization flags.
*
* @FLAG AMLIIF_INIT_BREAK | Break into the debugger at initialization
* completion.
*
* @FLAG AMLIIF_LOADDDB_BREAK | Break into the debugger at load definition
* block completion.
*
* @PARM ULONG | dwmsTimeSliceLength | Time slice length in msec.
*
* @PARM ULONG | dwmsTimeSliceInterval | Time slice interval in msec.
*
* @PARM ULONG | dwmsMaxCTObjs | Number of context to allocate
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*/
NTSTATUS AMLIAPI AMLIInitialize(ULONG dwCtxtBlkSize, ULONG dwGlobalHeapBlkSize,
ULONG dwfAMLIInit, ULONG dwmsTimeSliceLength,
ULONG dwmsTimeSliceInterval, ULONG dwmsMaxCTObjs)
{
TRACENAME("AMLIINITIALIZE")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(1, ("AMLIInitialize(InitFlags=%x,CtxtBlkSize=%d,GlobalHeapBlkSize=%d,TimeSliceLen=%d,TimeSliceInterval=%d)\n",
dwfAMLIInit, dwCtxtBlkSize, dwGlobalHeapBlkSize,
dwmsTimeSliceLength, dwmsTimeSliceInterval));
#ifndef DEBUGGER
DEREF(dwfAMLIInit);
#endif
RESETERR();
if (gpnsNameSpaceRoot != NULL)
{
rc = AMLI_LOGERR(AMLIERR_ALREADY_INITIALIZED,
("AMLIInitialize: interpreter already initialized"));
}
else
{
gdwCtxtBlkSize = dwCtxtBlkSize ? dwCtxtBlkSize: DEF_CTXTBLK_SIZE;
gdwGlobalHeapBlkSize = dwGlobalHeapBlkSize? dwGlobalHeapBlkSize:
DEF_GLOBALHEAPBLK_SIZE;
gdwfAMLIInit = dwfAMLIInit;
gdwfHacks = GetHackFlags(NULL);
//
// Sanity Check
//
if (dwmsMaxCTObjs > 1024) {
dwmsMaxCTObjs = 1024;
}
gdwcCTObjsMax = (dwmsMaxCTObjs > DEF_CTXTMAX_SIZE) ? dwmsMaxCTObjs :
DEF_CTXTMAX_SIZE;
#ifdef DEBUGGER
// gDebugger.dwfDebugger |= (DBGF_LOGEVENT_ON | DBGF_ERRBREAK_ON);
gDebugger.dwfDebugger |= DBGF_LOGEVENT_ON;
SetLogSize(DEF_MAXLOG_ENTRIES);
KeInitializeSpinLock( &gdwGHeapSpinLock );
#endif
KeInitializeSpinLock( &gdwGContextSpinLock );
//
// Initialize the LookAside lists.
//
ExInitializeNPagedLookasideList(
&AMLIContextLookAsideList,
NULL,
NULL,
0,
gdwCtxtBlkSize,
CTOBJ_TAG,
(USHORT) gdwcCTObjsMax
);
if ((rc = NewHeap(gdwGlobalHeapBlkSize, &gpheapGlobal)) ==
STATUS_SUCCESS)
{
int i;
PNSOBJ pns;
static PSZ apszDefinedRootObjs[] =
{
"_GPE", "_PR", "_SB", "_SI", "_TZ"
};
#define NUM_DEFINED_ROOT_OBJS (sizeof(apszDefinedRootObjs)/sizeof(PSZ))
gpheapGlobal->pheapHead = gpheapGlobal;
if ((rc = CreateNameSpaceObject(gpheapGlobal, NAMESTR_ROOT, NULL,
NULL, NULL, 0)) == STATUS_SUCCESS)
{
for (i = 0; i < NUM_DEFINED_ROOT_OBJS; ++i)
{
if ((rc = CreateNameSpaceObject(gpheapGlobal,
apszDefinedRootObjs[i],
NULL, NULL, NULL, 0)) !=
STATUS_SUCCESS)
{
break;
}
}
}
if ((rc == STATUS_SUCCESS) &&
((rc = CreateNameSpaceObject(gpheapGlobal, "_REV", NULL, NULL,
&pns, 0)) == STATUS_SUCCESS))
{
pns->ObjData.dwDataType = OBJTYPE_INTDATA;
pns->ObjData.uipDataValue = AMLI_REVISION;
}
if ((rc == STATUS_SUCCESS) &&
((rc = CreateNameSpaceObject(gpheapGlobal, "_OS", NULL, NULL,
&pns, 0)) == STATUS_SUCCESS))
{
pns->ObjData.dwDataType = OBJTYPE_STRDATA;
pns->ObjData.dwDataLen = STRLEN(gpszOSName) + 1;
if ((pns->ObjData.pbDataBuff = NEWSDOBJ(gpheapGlobal,
pns->ObjData.dwDataLen))
== NULL)
{
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
("AMLIInitialize: failed to allocate \\_OS name object"));
}
else
{
MEMCPY(pns->ObjData.pbDataBuff, gpszOSName,
pns->ObjData.dwDataLen);
}
}
if ((rc == STATUS_SUCCESS) &&
((rc = CreateNameSpaceObject(gpheapGlobal,"_OSI", NULL, NULL,
&pns, 0)) == STATUS_SUCCESS))
{
pns->ObjData.dwDataType = OBJTYPE_METHOD;
pns->ObjData.dwDataLen = sizeof(METHODOBJ) + sizeof(OSIAML) - sizeof(UCHAR);
if ((pns->ObjData.pbDataBuff = NEWSDOBJ(gpheapGlobal,
pns->ObjData.dwDataLen))
== NULL)
{
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
("AMLIInitiaize: failed to allocate \\_OSI name object"));
}
else
{
MEMZERO(pns->ObjData.pbDataBuff, pns->ObjData.dwDataLen);
//This method has one argument
((PMETHODOBJ)(pns->ObjData.pbDataBuff))->bMethodFlags |= 0x1;
MEMCPY(((PMETHODOBJ)(pns->ObjData.pbDataBuff))->abCodeBuff, (PUCHAR)OSIAML,
sizeof(OSIAML));
}
}
if ((rc == STATUS_SUCCESS) &&
((rc = CreateNameSpaceObject(gpheapGlobal, "_GL", NULL, NULL,
&pns, 0)) == STATUS_SUCCESS))
{
pns->ObjData.dwfData = DATAF_GLOBAL_LOCK;
rc = InitMutex(gpheapGlobal, pns, 0);
}
if (rc == STATUS_SUCCESS)
{
gReadyQueue.dwmsTimeSliceLength = dwmsTimeSliceLength?
dwmsTimeSliceLength:
DEF_TIMESLICE_LENGTH;
gReadyQueue.dwmsTimeSliceInterval = dwmsTimeSliceInterval?
dwmsTimeSliceInterval:
DEF_TIMESLICE_INTERVAL;
KeInitializeTimer(&gReadyQueue.Timer);
InitializeMutex(&gReadyQueue.mutCtxtQ);
ExInitializeWorkItem(&gReadyQueue.WorkItem,
StartTimeSlicePassive, &gReadyQueue);
InitializeMutex(&gmutCtxtList);
InitializeMutex(&gmutOwnerList);
InitializeMutex(&gmutHeap);
InitializeMutex(&gmutSleep);
KeInitializeDpc(&gReadyQueue.DpcStartTimeSlice,
StartTimeSlice,
&gReadyQueue);
KeInitializeDpc(&gReadyQueue.DpcExpireTimeSlice,
ExpireTimeSlice,
&gReadyQueue);
KeInitializeDpc(&SleepDpc, SleepQueueDpc, NULL);
KeInitializeTimer(&SleepTimer);
InitializeListHead(&SleepQueue);
InitializeRegOverrideFlags();
InitIllegalIOAddressListFromHAL();
}
}
}
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
#ifdef DEBUGGER
if (gdwfAMLIInit & AMLIIF_INIT_BREAK)
{
PRINTF("\n" MODNAME ": Break at AMLI Initialization Completion.\n");
AMLIDebugger(FALSE);
}
#endif
EXIT(1, ("AMLIInitialize=%x\n", rc));
return rc;
} //AMLIInitialize
/***EP AMLITerminate - Terminate AML interpreter
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLITerminate | AML Interpreter termination.
*
* This function is called to clean up all the global resources used
* by the AML interpreter.
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*/
NTSTATUS AMLIAPI AMLITerminate(VOID)
{
TRACENAME("AMLITERMINATE")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(1, ("AMLITerminate()\n"));
RESETERR();
if (gpnsNameSpaceRoot == NULL)
{
rc = AMLI_LOGERR(AMLIERR_NOT_INITIALIZED,
("AMLITerminate: interpreter not initialized"));
}
else
{
PLIST plist;
PHEAP pheap;
#ifdef DEBUGGER
FreeSymList();
if (gDebugger.pEventLog != NULL)
{
MFREE(gDebugger.pEventLog);
}
MEMZERO(&gDebugger, sizeof(DBGR));
#endif
ASSERT(gReadyQueue.pkthCurrent == NULL);
ASSERT(gReadyQueue.pctxtCurrent == NULL);
FreeNameSpaceObjects(gpnsNameSpaceRoot);
gpnsNameSpaceRoot = NULL;
MEMZERO(&gReadyQueue, sizeof(CTXTQ));
while ((plist = ListRemoveTail(&gplistCtxtHead)) != NULL)
{
FreeContext(CONTAINING_RECORD(plist, CTXT, listCtxt));
}
while ((plist = ListRemoveTail(&gplistObjOwners)) != NULL)
{
FreeObjOwner((POBJOWNER)plist, FALSE);
}
while ((plist = ListRemoveTail(&gplistDefuncNSObjs)) != NULL)
{
FREENSOBJ(CONTAINING_RECORD(plist, NSOBJ, list));
}
FreeRSAccessList(gpRSAccessHead);
gpRSAccessHead = NULL;
MEMZERO(&ghNotify, sizeof(EVHANDLE));
MEMZERO(&ghValidateTable, sizeof(EVHANDLE));
MEMZERO(&ghFatal, sizeof(EVHANDLE));
MEMZERO(&ghGlobalLock, sizeof(EVHANDLE));
MEMZERO(&ghCreate, sizeof(EVHANDLE));
MEMZERO(&ghDestroyObj,sizeof(EVHANDLE));
for (pheap = gpheapGlobal; pheap != NULL; pheap = gpheapGlobal)
{
gpheapGlobal = pheap->pheapNext;
FreeHeap(pheap);
}
FreellegalIOAddressList();
gdwfAMLI = 0;
#ifdef DEBUG
if (gdwcMemObjs != 0)
{
DumpMemObjCounts();
ASSERT(gdwcMemObjs == 0);
}
#endif
}
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
EXIT(1, ("AMLITerminate=%x\n", rc));
return rc;
} //AMLITerminate
/***EP AMLILoadDDB - Load and parse Differentiated Definition Block
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLILoadDDB | Load Differentiated Definition Block.
*
* This function loads and parses the given Differentiated System
* Description Table as well as any dynamic Differentiated Definition
* Block. It will parse the DDB and populate the ACPI name space
* accordingly.
*
* @PARM PDSDT | pDSDT | Pointer to a DSDT block.
*
* @PARM HANDLE * | phDDB | Pointer to the variable that will receive
* the DDB handle (can be NULL).
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code if encountering parse error.
*
* @DEVNOTE If an error occurs in the middle of loading a DDB, the loading
* will be aborted but the objects created prior to the error remain
* in the name space. Therefore, it is the responsibility of the
* caller to call AMLIUnLoadDDB to destroy the created objects if
* desired and the return handle is not NULL.
*/
NTSTATUS AMLIAPI AMLILoadDDB(PDSDT pDSDT, HANDLE *phDDB)
{
TRACENAME("AMLILOADDDB")
NTSTATUS rc = STATUS_SUCCESS;
PCTXT pctxt = NULL;
POBJOWNER powner = NULL;
ENTER(1, ("AMLILoadDDB(pDSDT=%x,phDDB=%x)\n", pDSDT, phDDB));
ASSERT(pDSDT != NULL);
RESETERR();
CHKDEBUGGERREQ();
gInitTime = TRUE;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON)
{
PRINTF(MODNAME ": %08x: Loading Definition Block %s at 0x%08x.\n",
KeGetCurrentThread(), NameSegString(pDSDT->Header.Signature),
pDSDT);
}
#endif
gdwfHacks |= GetHackFlags(pDSDT);
if ((rc = NewContext(&pctxt)) == STATUS_SUCCESS)
{
ASSERT(gpheapGlobal != NULL);
pctxt->pheapCurrent = gpheapGlobal;
#ifdef DEBUG
gdwfAMLI |= AMLIF_LOADING_DDB;
#endif
if (atLoad.pfnCallBack != NULL && atLoad.dwfOpcode & OF_CALLBACK_EX) {
((PFNOPEX)atLoad.pfnCallBack)(
EVTYPE_OPCODE_EX,
OPEXF_NOTIFY_PRE,
atLoad.dwOpcode,
NULL,
atLoad.dwCBData
);
}
rc = LoadDDB(pctxt,pDSDT, gpnsNameSpaceRoot, &powner);
if (rc == STATUS_SUCCESS)
{
rc = SyncLoadDDB(pctxt);
}
#ifdef DEBUG
{
KIRQL oldIrql;
gdwfAMLI &= ~AMLIF_LOADING_DDB;
KeAcquireSpinLock( &gdwGHeapSpinLock, &oldIrql );
gdwGHeapSnapshot = gdwGlobalHeapSize;
KeReleaseSpinLock( &gdwGHeapSpinLock, oldIrql );
}
#endif
}
if (phDDB != NULL)
{
*phDDB = (HANDLE)powner;
}
if ((powner != NULL) && (atLoad.pfnCallBack != NULL))
{
if (atLoad.dwfOpcode & OF_CALLBACK_EX) {
((PFNOPEX)atLoad.pfnCallBack)(
EVTYPE_OPCODE_EX,
OPEXF_NOTIFY_POST,
atLoad.dwOpcode,
NULL,
atLoad.dwCBData
);
} else {
atLoad.pfnCallBack(
EVTYPE_OPCODE,
atLoad.dwOpcode,
NULL,
atLoad.dwCBData
);
}
}
#ifdef DEBUGGER
if (gdwfAMLIInit & AMLIIF_LOADDDB_BREAK)
{
PRINTF("\n" MODNAME ": Break at Load Definition Block Completion.\n");
AMLIDebugger(FALSE);
}
#endif
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
gInitTime = FALSE;
EXIT(1, ("AMLILoadDDB=%x (powner=%x)\n", rc, powner));
return rc;
} //AMLILoadDDB
/***EP AMLIUnloadDDB - Unload Differentiated Definition Block
*
* @DOC EXTERNAL
*
* @FUNC VOID | AMLIUnloadDDB | Unload the Differentiated Definition Block.
*
* This function is called to unload the given dynamic DDB object and
* clean it out of the name space. Note that this function does not
* differentiate between a DSDT from a dynamic DDB, so it is the
* caller's responsibility to not freeing the DSDT accidentally.
*
* @PARM HANDLE | hDDB | handle to the definition block context to be
* unloaded.
*
* @RDESC None.
*/
VOID AMLIAPI AMLIUnloadDDB(HANDLE hDDB)
{
TRACENAME("AMLIUNLOADDDB")
ENTER(1, ("AMLIUnloadDDB(hDDB=%x)\n", hDDB));
RESETERR();
if (hDDB != NULL)
{
ASSERT(((POBJOWNER)hDDB)->dwSig == SIG_OBJOWNER);
UnloadDDB((POBJOWNER)hDDB);
}
EXIT(1, ("AMLIUnloadDDB!\n"));
} //AMLIUnloadDDB
/***EP AMLIGetNameSpaceObject - Find a name space object
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIGetNameSpaceObject | Find an object in the ACPI
* name space.
*
* This function accepts an absolute object path as well as a
* relative object path in the form of an ASCIIZ string.
* It will search through the name space in the appropriate
* scope for the given object path and returns the object
* pointer when it is found.
*
* @PARM PSZ | pszObjPath | Pointer to an ASCIIZ string specifying the
* object path.
*
* @PARM PNSOBJ | pnsScope | If not NULL, this points to the object scope
* where the search starts. If pszObjPath is specifying an absolute
* path, this parameter is ignored.
*
* @PARM PPNSOBJ | ppns | Pointer to a variable to hold the object
* point.
*
* @PARM ULONG | dwfFlags | Option flags.
*
* @FLAG NSF_LOCAL_SCOPE | Search local scope only.
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*/
NTSTATUS AMLIAPI AMLIGetNameSpaceObject(PSZ pszObjPath, PNSOBJ pnsScope,
PPNSOBJ ppns, ULONG dwfFlags)
{
TRACENAME("AMLIGETNAMESPACEOBJECT")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIGetNameSpaceObject(ObjPath=%s,Scope=%s,ppns=%p,Flags=%x)\n",
pszObjPath, GetObjectPath(pnsScope), ppns, dwfFlags));
ASSERT(pszObjPath != NULL);
ASSERT(*pszObjPath != '\0');
ASSERT(ppns != NULL);
RESETERR();
CHKDEBUGGERREQ();
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_GetNameSpaceObject(
pszObjPath,pnsScope,ppns,dwfFlags,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
if ((pnsScope != NULL) && (pnsScope->ObjData.dwfData & DATAF_NSOBJ_DEFUNC))
{
AMLI_WARN(("AMLIGetNameSpaceObject: pnsScope is no longer valid"));
rc = STATUS_NO_SUCH_DEVICE;
}
else
{
ASSERT((pnsScope == NULL) || !(pnsScope->ObjData.dwfData & DATAF_NSOBJ_DEFUNC));
rc = GetNameSpaceObject(pszObjPath, pnsScope, ppns, dwfFlags);
}
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_GetNameSpaceObject(
&pHData,rc);
}
EXIT(1, ("AMLIGetNameSpaceObject=%x (pns=%p)\n", rc, *ppns));
return rc;
} //AMLIGetNameSpaceObject
/***EP AMLIGetFieldUnitRegionObj - Get OpRegion associated with FieldUnit
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIGetFieldUnitRegionObj | Get the OperationRegion
* object associated with the FieldUnit object.
*
* @PARM PFIELDUNITOBJ | pfu | Pointer to a FieldUnit object.
*
* @PARM PPNSOBJ | ppns | Pointer to a variable to hold the OperationRegion
* object.
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*/
NTSTATUS AMLIAPI AMLIGetFieldUnitRegionObj(PFIELDUNITOBJ pfu, PPNSOBJ ppns)
{
TRACENAME("AMLIGETFIELDUNITREGIONOBJ")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIGetFieldUnitRegionObj(pfu=%x,ppns=%x)\n", pfu, ppns));
ASSERT(pfu != NULL);
ASSERT(ppns != NULL);
RESETERR();
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_GetFieldUnitRegionObj(
pfu,ppns,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
rc = GetFieldUnitRegionObj(pfu, ppns);
if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_GetFieldUnitRegionObj(
&pHData,rc);
}
EXIT(1, ("AMLIGetFieldUnitRegionObj=%x (pns=%x)\n", rc, *ppns));
return rc;
} //AMLIGetFieldUnitRegionObj
/***EP AMLIEvalNameSpaceObject - Evaluate a name space object
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIEvalNameSpaceObject | Evaluate a name space object.
*
* This function evaluate a given object. If the given object is a
* control method, it will execute it. If the given object is a data
* object, the data value is returned in a given buffer.
*
* @PARM PNSOBJ | pns | Pointer to the object to be evaluated.
*
* @PARM POBJDATA | pdataResult | Pointer to the OBJDATA structure which will
* hold the result of the evaluation (can be NULL if don't care about
* result).
*
* @PARM int | icArgs | Specify the number of arguments pass to the method
* object for evaluation (only valid if pns points to a method object).
*
* @PARM POBJDATA | pdataArgs | Pointer to an array of argument data object
* (only valid if pns points to a method object).
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*
* @DEVNOTE The returned object may contain buffer pointer to the actual
* data in the ACPI name space. Therefore, the caller must be very
* careful not to overwrite any data in the buffer. Also, the caller
* is responsible for calling AMLIFreeDataBuffs on the result object
* after the result object data is no longer needed.
*/
NTSTATUS AMLIAPI AMLIEvalNameSpaceObject(PNSOBJ pns, POBJDATA pdataResult,
int icArgs, POBJDATA pdataArgs)
{
TRACENAME("AMLIEVALNAMESPACEOBJECT")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIEvalNameSpaceObject(Obj=%s,pdataResult=%x,icArgs=%d,pdataArgs=%x)\n",
GetObjectPath(pns), pdataResult, icArgs, pdataArgs));
ASSERT(pns != NULL);
ASSERT((icArgs == 0) || (pdataArgs != NULL));
RESETERR();
CHKGLOBALHEAP();
CHKDEBUGGERREQ();
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_EvalNameSpaceObject(
pns,pdataResult,icArgs,pdataArgs,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
if (pns->ObjData.dwfData & DATAF_NSOBJ_DEFUNC)
{
AMLI_WARN(("AMLIEvalNameSpaceObject: pnsObj is no longer valid"));
rc = STATUS_NO_SUCH_DEVICE;
}
else
{
if (pdataResult != NULL)
MEMZERO(pdataResult, sizeof(OBJDATA));
pns = GetBaseObject(pns);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON)
{
PRINTF(MODNAME ": %08x: EvalNameSpaceObject(%s)\n",
KeGetCurrentThread(), GetObjectPath(pns));
}
#endif
rc = SyncEvalObject(pns, pdataResult, icArgs, pdataArgs);
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
}
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_EvalNameSpaceObject(
&pHData,rc);
}
EXIT(1, ("AMLIEvalNameSpaceObject=%x\n", rc));
return rc;
} //AMLIEvalNameSpaceObject
/***EP AMLIAsyncEvalObject - Evaluate an object asynchronously
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIAsyncEvalObject | Evaluate an object asynchronously.
*
* @PARM PNSOBJ | pns | Pointer to the object to be evaluated.
*
* @PARM POBJDATA | pdataResult | Pointer to the OBJDATA structure which will
* hold the result of the evaluation (can be NULL if don't care about
* result).
*
* @PARM int | icArgs | Specify the number of arguments pass to the method
* object for evaluation (only valid if pns points to a method object).
*
* @PARM POBJDATA | pdataArgs | Pointer to an array of argument data object
* (only valid if pns points to a method object).
*
* @PARM PFNACB | pfnAsyncCallBack | Pointer to the asynchronous callback
* function in case the control method is blocked and has to be
* completed asynchronously (can be NULL if no Callback required).
*
* @PARM PVOID | pvContext | Pointer to some context data that the
* interpreter will pass to the Async callback handler.
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*
* @DEVNOTE The returned object may contain buffer pointer to the actual
* data in the ACPI name space. Therefore, the caller must be very
* careful not to overwrite any data in the buffer. Also, the caller
* is responsible for calling AMLIFreeDataBuffs on the result object
* after the result object data is no longer needed.
*/
NTSTATUS AMLIAPI AMLIAsyncEvalObject(PNSOBJ pns, POBJDATA pdataResult,
int icArgs, POBJDATA pdataArgs,
PFNACB pfnAsyncCallBack, PVOID pvContext)
{
TRACENAME("AMLIASYNCEVALOBJECT")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIAsyncEvalObject(Obj=%s,pdataResult=%x,icArgs=%d,pdataArgs=%x,pfnAysnc=%x)\n",
GetObjectPath(pns), pdataResult, icArgs, pdataArgs,
pfnAsyncCallBack));
ASSERT(pns != NULL);
ASSERT((icArgs == 0) || (pdataArgs != NULL));
RESETERR();
CHKGLOBALHEAP();
CHKDEBUGGERREQ();
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_AsyncEvalObject(
pns,pdataResult,icArgs,pdataArgs,
&pfnAsyncCallBack,&pvContext,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
if (pns->ObjData.dwfData & DATAF_NSOBJ_DEFUNC)
{
AMLI_WARN(("AMLIAsyncEvalObject: pnsObj is no longer valid"));
rc = STATUS_NO_SUCH_DEVICE;
}
else
{
if (pdataResult != NULL)
MEMZERO(pdataResult, sizeof(OBJDATA));
pns = GetBaseObject(pns);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON)
{
PRINTF(MODNAME ": %08x: AsyncEvalObject(%s)\n",
KeGetCurrentThread(), GetObjectPath(pns));
}
#endif
rc = AsyncEvalObject(pns, pdataResult, icArgs, pdataArgs,
pfnAsyncCallBack, pvContext, TRUE);
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
}
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_AsyncEvalObject(
&pHData,rc);
}
EXIT(1, ("AMLIAsyncEvalObject=%x\n", rc));
return rc;
} //AMLIAsyncEvalObject
/***EP AMLINestAsyncEvalObject - Evaluate an object asynchronously from within
* the current context
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLINestAsyncEvalObject | Evaluate an object
* asynchronously from within the current context.
*
* @PARM PNSOBJ | pns | Pointer to the object to be evaluated.
*
* @PARM POBJDATA | pdataResult | Pointer to the OBJDATA structure which will
* hold the result of the evaluation (can be NULL if don't care about
* result).
*
* @PARM int | icArgs | Specify the number of arguments pass to the method
* object for evaluation (only valid if pns points to a method object).
*
* @PARM POBJDATA | pdataArgs | Pointer to an array of argument data object
* (only valid if pns points to a method object).
*
* @PARM PFNACB | pfnAsyncCallBack | Pointer to the asynchronous callback
* function in case the control method is blocked and has to be
* completed asynchronously (can be NULL if no Callback required).
*
* @PARM PVOID | pvContext | Pointer to some context data that the
* interpreter will pass to the Async callback handler.
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*
* @DEVNOTE The returned object may contain buffer pointer to the actual
* data in the ACPI name space. Therefore, the caller must be very
* careful not to overwrite any data in the buffer. Also, the caller
* is responsible for calling AMLIFreeDataBuffs on the result object
* after the result object data is no longer needed.
*/
NTSTATUS AMLIAPI AMLINestAsyncEvalObject(PNSOBJ pns, POBJDATA pdataResult,
int icArgs, POBJDATA pdataArgs,
PFNACB pfnAsyncCallBack,
PVOID pvContext)
{
TRACENAME("AMLINESTASYNCEVALOBJECT")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLINestAsyncEvalObject(Obj=%s,pdataResult=%x,icArgs=%d,pdataArgs=%x,pfnAysnc=%x)\n",
GetObjectPath(pns), pdataResult, icArgs, pdataArgs,
pfnAsyncCallBack));
ASSERT(pns != NULL);
ASSERT((icArgs == 0) || (pdataArgs != NULL));
RESETERR();
CHKGLOBALHEAP();
CHKDEBUGGERREQ();
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_NestAsyncEvalObject(
pns,pdataResult,icArgs,pdataArgs,
&pfnAsyncCallBack,&pvContext,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
if (pns->ObjData.dwfData & DATAF_NSOBJ_DEFUNC)
{
AMLI_WARN(("AMLINestAsyncEvalObject: pnsObj is no longer valid"));
rc = STATUS_NO_SUCH_DEVICE;
}
else
{
if (pdataResult != NULL)
MEMZERO(pdataResult, sizeof(OBJDATA));
pns = GetBaseObject(pns);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON)
{
PRINTF(MODNAME ": %08x: AsyncNestEvalObject(%s)\n",
KeGetCurrentThread(), GetObjectPath(pns));
}
#endif
rc = NestAsyncEvalObject(pns, pdataResult, icArgs, pdataArgs,
pfnAsyncCallBack, pvContext, TRUE);
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
}
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_NestAsyncEvalObject(
&pHData,rc);
}
EXIT(1, ("AMLINestAsyncEvalObject=%x\n", rc));
return rc;
} //AMLINestAsyncEvalObject
/***EP AMLIEvalPackageElement - Evaluate a package element
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIEvalPackageElement | Evaluate a package element.
*
* This function evaluate an element of a given package object.
* A package is essentially an array of objects. This API provides
* a way to evaluate individual element object inside a package.
*
* @PARM PNSOBJ | pns | Pointer to the package object to be evaluated. If
* the object is a method, then the method is evaluated first before
* the resulting package object is evaluated. It is an error if the
* resulting object is not of package type.
*
* @PARM int | iPkgIndex | Package index (0-based).
*
* @PARM POBJDATA | pdataResult | Pointer to the OBJDATA structure which will
* hold the result of the evaluation (can be NULL if don't care about
* result).
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*
* @DEVNOTE The returned object may contain buffer pointer to the actual
* data in the ACPI name space. Therefore, the caller must be very
* careful not to overwrite any data in the buffer. Also, the caller
* is responsible for calling AMLIFreeDataBuffs on the result object
* after the result object data is no longer needed.
*/
NTSTATUS AMLIAPI AMLIEvalPackageElement(PNSOBJ pns, int iPkgIndex,
POBJDATA pdataResult)
{
TRACENAME("AMLIEVALPACKAGEELEMENT")
NTSTATUS rc = STATUS_SUCCESS;
OBJDATA data;
POBJDATA pdata = NULL;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIEvalPackageElement(Obj=%s,Index=%d,pdataResult=%x)\n",
GetObjectPath(pns), iPkgIndex, pdataResult));
ASSERT(pns != NULL);
ASSERT(pdataResult != NULL);
RESETERR();
CHKGLOBALHEAP();
CHKDEBUGGERREQ();
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_EvalPackageElement(
pns,iPkgIndex,pdataResult,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
if (pns->ObjData.dwfData & DATAF_NSOBJ_DEFUNC)
{
AMLI_WARN(("AMLIEvalPackageElement: pnsObj is no longer valid"));
rc = STATUS_NO_SUCH_DEVICE;
}
else
{
MEMZERO(pdataResult, sizeof(OBJDATA));
MEMZERO(&data, sizeof(data));
pns = GetBaseObject(pns);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON)
{
PRINTF(MODNAME ": %08x: EvalPackageElement(%s,%d)\n",
KeGetCurrentThread(), GetObjectPath(pns), iPkgIndex);
}
#endif
if (pns->ObjData.dwDataType == OBJTYPE_METHOD)
{
if ((rc = SyncEvalObject(pns, &data, 0, NULL)) == STATUS_SUCCESS)
{
if (data.dwDataType == OBJTYPE_PKGDATA)
pdata = &data;
else
{
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
("AMLIEvalPackageElement: result object of the method is not package (ObjType=%s)",
GetObjectTypeName(data.dwDataType)));
}
}
}
else if (pns->ObjData.dwDataType == OBJTYPE_PKGDATA)
{
pdata = &pns->ObjData;
}
else
{
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
("AMLIEvalPackageElement: object is not a method or package (ObjType=%s)",
GetObjectTypeName(pns->ObjData.dwDataType)));
}
if (rc == STATUS_SUCCESS)
{
rc = EvalPackageElement((PPACKAGEOBJ)pdata->pbDataBuff, iPkgIndex,
pdataResult);
}
FreeDataBuffs(&data, 1);
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
else
{
ASSERT((pdataResult->pbDataBuff == NULL) ||
!(pdataResult->dwfData & DATAF_BUFF_ALIAS));
}
}
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_EvalPackageElement(
&pHData,rc);
}
EXIT(1, ("AMLIEvalPackageElement=%x\n", rc));
return rc;
} //AMLIEvalPackageElement
/***EP AMLIEvalPkgDataElement - Evaluate an element of a package data
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIEvalPkgDataElement | Evaluate a package data element.
*
* This function evaluate an element of a given package data object.
* A package is essentially an array of objects. This API provides
* a way to evaluate individual element object inside a package.
*
* @PARM POBJDATA | pdataPkg | Pointer to the package data object to be
* evaluated. It is an error if the data object is not of package
* type.
*
* @PARM int | iPkgIndex | Package index (0-based).
*
* @PARM POBJDATA | pdataResult | Pointer to the OBJDATA structure which will
* hold the result of the evaluation (can be NULL if don't care about
* result).
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*
* @DEVNOTE The returned object may contain buffer pointer to the actual
* data in the ACPI name space. Therefore, the caller must be very
* careful not to overwrite any data in the buffer. Also, the caller
* is responsible for calling AMLIFreeDataBuffs on the result object
* after the result object data is no longer needed.
*/
NTSTATUS AMLIAPI AMLIEvalPkgDataElement(POBJDATA pdataPkg, int iPkgIndex,
POBJDATA pdataResult)
{
TRACENAME("AMLIEVALPKGDATAELEMENT")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIEvalPkgDataElement(pdataPkg=%x,Index=%d,pdataResult=%x)\n",
pdataPkg, iPkgIndex, pdataResult));
ASSERT(pdataResult != NULL);
RESETERR();
CHKGLOBALHEAP();
CHKDEBUGGERREQ();
MEMZERO(pdataResult, sizeof(OBJDATA));
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_EvalPkgDataElement(
pdataPkg,iPkgIndex,pdataResult,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON)
{
PRINTF(MODNAME ": %08x: EvalPkgDataElement(%x,%d)\n",
KeGetCurrentThread(), pdataPkg, iPkgIndex);
}
#endif
if (pdataPkg->dwDataType != OBJTYPE_PKGDATA)
{
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
("AMLIEvalPkgDataElement: object is not a package (ObjType=%s)",
GetObjectTypeName(pdataPkg->dwDataType)));
}
else
{
rc = EvalPackageElement((PPACKAGEOBJ)pdataPkg->pbDataBuff, iPkgIndex,
pdataResult);
}
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
else
{
ASSERT((pdataResult->pbDataBuff == NULL) ||
!(pdataResult->dwfData & DATAF_BUFF_ALIAS));
}
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_EvalPkgDataElement(
&pHData,rc);
}
EXIT(1, ("AMLIEvalPkgDataElement=%x\n", rc));
return rc;
} //AMLIEvalPkgDataElement
/***EP AMLIFreeDataBuffs - Free data buffers of an object array
*
* @DOC EXTERNAL
*
* @FUNC VOID | AMLIFreeDataBuffs | Free data buffers of a data object
* array.
*
* This function is typically called after evaluating an object to
* free the result object buffers.
*
* @PARM POBJDATA | pdata | Pointer to the object array.
*
* @PARM int | icData | Specifies the number of objects in the array.
*
* @RDESC None.
*/
VOID AMLIAPI AMLIFreeDataBuffs(POBJDATA pdata, int icData)
{
TRACENAME("AMLIFREEDATABUFFS")
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIFreeDataBuffs(pdata=%x,icData=%d)\n", pdata, icData));
ASSERT(pdata != NULL);
ASSERT(icData > 0);
RESETERR();
if(IsAmliHookEnabled())
{
AMLITest_Pre_FreeDataBuffs(
pdata,icData,&pHData);
}
FreeDataBuffs(pdata, icData);
if(IsAmliHookEnabled())
{
AMLITest_Post_FreeDataBuffs(
&pHData,STATUS_SUCCESS);
}
EXIT(1, ("AMLIFreeDataBuffs!\n"));
} //AMLIFreeDataBuffs
/***EP AMLIRegEventHandler - Register an event handler
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIRegEventHandler | Register an event handler.
* handler.
*
* This function allows the caller to hook a callback handler for some
* AMLI events.
*
* @PARM ULONG | dwEventType | Event type the handler will handle.
*
* @PARM ULONG_PTR | uipEventData | Event specific data the handler will
* handle.
*
* @PARM PFNHND | pfnHandler | Callback handler entry point (can be NULL
* if deregistering previous handler).
*
* @PARM ULONG_PTR | uipParam | Parameter Data (will be passed to the
* callback handler).
*
* @RDESC None.
*/
NTSTATUS AMLIAPI AMLIRegEventHandler(ULONG dwEventType, ULONG_PTR uipEventData,
PFNHND pfnHandler, ULONG_PTR uipParam)
{
TRACENAME("AMLIREGEVENTHANDLER")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIRegEventHandler(EventType=%x,EventData=%x,pfnHandler=%x,Param=%x)\n",
dwEventType, uipEventData, pfnHandler, uipParam));
RESETERR();
if(IsAmliHookEnabled())
{
rc = AMLIHook_Pre_RegEventHandler(
dwEventType,uipEventData,&pfnHandler,&uipParam,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
switch (dwEventType)
{
case EVTYPE_OPCODE:
rc = RegOpcodeHandler((ULONG)uipEventData, (PFNOH)pfnHandler,
uipParam, 0);
break;
case EVTYPE_OPCODE_EX:
rc = RegOpcodeHandler((ULONG)uipEventData, (PFNOH)pfnHandler,
uipParam, OF_CALLBACK_EX);
break;
case EVTYPE_NOTIFY:
rc = RegEventHandler(&ghNotify, pfnHandler, uipParam);
break;
case EVTYPE_FATAL:
rc = RegEventHandler(&ghFatal, pfnHandler, uipParam);
break;
case EVTYPE_VALIDATE_TABLE:
rc = RegEventHandler(&ghValidateTable, pfnHandler, uipParam);
break;
case EVTYPE_ACQREL_GLOBALLOCK:
rc = RegEventHandler(&ghGlobalLock, pfnHandler, uipParam);
break;
case EVTYPE_RS_COOKACCESS:
rc = RegRSAccess((ULONG)uipEventData, pfnHandler, uipParam, FALSE);
break;
case EVTYPE_RS_RAWACCESS:
rc = RegRSAccess((ULONG)uipEventData, pfnHandler, uipParam, TRUE);
break;
case EVTYPE_CREATE:
rc = RegEventHandler(&ghCreate, pfnHandler, uipParam);
break;
case EVTYPE_DESTROYOBJ:
rc =RegEventHandler(&ghDestroyObj, pfnHandler, uipParam);
break;
#ifdef DEBUGGER
case EVTYPE_CON_MESSAGE:
rc = RegEventHandler(&gDebugger.hConMessage, pfnHandler, uipParam);
break;
case EVTYPE_CON_PROMPT:
rc = RegEventHandler(&gDebugger.hConPrompt, pfnHandler, uipParam);
break;
#endif
default:
rc = AMLI_LOGERR(AMLIERR_INVALID_EVENTTYPE,
("AMLIRegEventHandler: invalid event type %x",
dwEventType));
}
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
if(IsAmliHookEnabled())
{
rc = AMLIHook_Post_RegEventHandler(
&pHData,rc);
}
EXIT(1, ("AMLIRegEventHandler=%x\n", rc));
return rc;
} //AMLIRegEventHandler
/***EP AMLIPauseInterpreter
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIPauseInterpreter | Flush the interpreter queue
* and pause the interpreter so that all subsequent new method
* execution requests will be queued.
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*/
NTSTATUS AMLIAPI AMLIPauseInterpreter(PFNAA pfnCallback, PVOID Context)
{
TRACENAME("AMLIPAUSEINTERPRETER")
NTSTATUS rc = STATUS_SUCCESS;
PAMLIHOOK_DATA pHData = NULL;
ENTER(1, ("AMLIPauseInterpreter(Callback=%p,Context=%p)\n",
pfnCallback, Context));
RESETERR();
if(IsAmliHookEnabled())
{
rc = AMLITest_Pre_PauseInterpreter(
&pfnCallback,&Context,&pHData);
if(rc != STATUS_SUCCESS)
return(rc);
}
AcquireMutex(&gReadyQueue.mutCtxtQ);
if (!(gReadyQueue.dwfCtxtQ & (CQF_PAUSED | CQF_FLUSHING)))
{
if (gplistCtxtHead == NULL)
{
//
// There is no pending ctxt.
//
gReadyQueue.dwfCtxtQ |= CQF_PAUSED;
}
else
{
//
// There are pending ctxts, so we go into flushing mode.
//
gReadyQueue.dwfCtxtQ |= CQF_FLUSHING;
gReadyQueue.pfnPauseCallback = pfnCallback;
gReadyQueue.PauseCBContext = Context;
rc = AMLISTA_PENDING;
}
}
else
{
rc = AMLI_LOGERR(AMLIERR_FATAL,
("AMLIPauseInterpreter: interpreter already entered paused state"));
}
ReleaseMutex(&gReadyQueue.mutCtxtQ);
LOGSCHEDEVENT('PAUS', (ULONG_PTR)rc, 0, 0);
if (rc == AMLISTA_PENDING)
rc = STATUS_PENDING;
else if (rc != STATUS_SUCCESS)
rc = NTERR(rc);
if(IsAmliHookEnabled())
{
rc = AMLITest_Post_PauseInterpreter(
&pHData,rc);
}
EXIT(1, ("AMLIPauseInterpreter=%x\n", rc));
return rc;
} //AMLIPauseInterpreter
/***EP AMLIResumeInterpreter
*
* @DOC EXTERNAL
*
* @FUNC VOID | AMLIResumeInterpreter | Resume the interpreter from
* paused state.
*
* @RDESC None.
*/
VOID AMLIAPI AMLIResumeInterpreter(VOID)
{
PAMLIHOOK_DATA pHData = NULL;
TRACENAME("AMLIRESUMEINTERPRETER")
ENTER(1, ("AMLIResumeInterpreter()\n"));
RESETERR();
if(IsAmliHookEnabled())
{
AMLITest_Pre_ResumeInterpreter(
&pHData);
}
AcquireMutex(&gReadyQueue.mutCtxtQ);
if (gReadyQueue.dwfCtxtQ & (CQF_PAUSED | CQF_FLUSHING))
{
gReadyQueue.dwfCtxtQ &= ~(CQF_PAUSED | CQF_FLUSHING);
gReadyQueue.pfnPauseCallback = NULL;
gReadyQueue.PauseCBContext = NULL;
LOGSCHEDEVENT('RSUM', 0, 0, 0);
if ((gReadyQueue.plistCtxtQ != NULL) &&
!(gReadyQueue.dwfCtxtQ & CQF_WORKITEM_SCHEDULED))
{
OSQueueWorkItem(&gReadyQueue.WorkItem);
gReadyQueue.dwfCtxtQ |= CQF_WORKITEM_SCHEDULED;
LOGSCHEDEVENT('RSTQ', 0, 0, 0);
}
}
else
{
AMLI_WARN(("AMLIResumeInterpreter: not in paused state"));
}
ReleaseMutex(&gReadyQueue.mutCtxtQ);
if(IsAmliHookEnabled())
{
AMLITest_Post_ResumeInterpreter(
&pHData,STATUS_SUCCESS);
}
EXIT(1, ("AMLIResumeInterpreter!\n"));
} //AMLIResumeInterpreter
/***EP AMLIReferenceObject - Bump up the reference count of the object
*
* @DOC EXTERNAL
*
* @FUNC VOID | AMLIReferenceObject | Bump up the reference count of the
* name space object.
*
* @PARM PNSOBJ | pnsObj | Points to the name space object.
*
* @RDESC None.
*/
VOID AMLIAPI AMLIReferenceObject(PNSOBJ pnsObj)
{
TRACENAME("AMLIREFERENCEOBJECT")
ENTER(1, ("AMLIReferenceObject(pnsObj=%x)\n", pnsObj));
RESETERR();
ASSERT(pnsObj != NULL);
pnsObj->dwRefCount++;
EXIT(1, ("AMLIReferenceObj!\n"));
} //AMLIReferenceObject
/***EP AMLIDereferenceObject - Bump down the reference count of the object
*
* @DOC EXTERNAL
*
* @FUNC VOID | AMLIDereferenceObject | Bump down the reference count of the
* name space object. If it reaches zero and it is in defunc state,
* deallocate the object.
*
* @PARM PNSOBJ | pnsObj | Points to the name space object.
*
* @RDESC None.
*/
VOID AMLIAPI AMLIDereferenceObject(PNSOBJ pnsObj)
{
TRACENAME("AMLIDEREFERENCEOBJECT")
ENTER(1, ("AMLIDereferenceObject(pnsObj=%x)\n", pnsObj));
RESETERR();
ASSERT(pnsObj != NULL);
ASSERT(pnsObj->dwRefCount > 0);
if (pnsObj->dwRefCount > 0)
{
pnsObj->dwRefCount--;
if ((pnsObj->dwRefCount == 0) && (pnsObj->ObjData.dwfData & DATAF_NSOBJ_DEFUNC))
{
ListRemoveEntry(&pnsObj->list, &gplistDefuncNSObjs);
FREENSOBJ(pnsObj);
}
}
EXIT(1, ("AMLIDereferenceObj!\n"));
} //AMLIDereferenceObject
/***EP AMLIDestroyFreedObjs - Destroy freed objects during an unload
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIDestroyFreedObjs | Destroy freed objects from a
* previous unload.
*
* @PARM PNSOBJ | pnsObj | The object in the freed list to be destroyed.
*
* @RDESC SUCCESS - Returns STATUS_SUCCESS.
*
* @RDESC FAILURE - Returns NT status code.
*/
NTSTATUS AMLIAPI AMLIDestroyFreedObjs(PNSOBJ pnsObj)
{
TRACENAME("AMLIDESTROYFREEDOBJS")
ENTER(1, ("AMLIDestroyFreedObjs(pnsObj=%x)\n",pnsObj));
RESETERR();
ASSERT(pnsObj != NULL);
//
// Destroy the namespace object
//
FreeNameSpaceObjects(pnsObj);
EXIT(1, ("AMLIDestroyFreedObjs=%x \n",STATUS_SUCCESS));
return STATUS_SUCCESS;
} //AMLIDestroyFreedObjs
#ifdef DEBUGGER
/***EP AMLIGetLastError - Get last error code and message
*
* @DOC EXTERNAL
*
* @FUNC NTSTATUS | AMLIGetLastError | Get last error code and associated
* error message.
*
* @PARM PSZ * | ppszErrMsg | Point to a variable to hold the error message
* buffer pointer. If there is no error, the variable is set to NULL.
*
* @RDESC Returns the last error code.
*/
NTSTATUS AMLIAPI AMLIGetLastError(PSZ *ppszErrMsg)
{
TRACENAME("AMLIGETLASTERROR")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(1, ("AMLIGetLastError(ppszErrMsg=%x)\n", ppszErrMsg));
ASSERT(ppszErrMsg != NULL);
if ((rc = gDebugger.rcLastError) != STATUS_SUCCESS)
*ppszErrMsg = gDebugger.szLastError;
else
*ppszErrMsg = NULL;
EXIT(1, ("AMLIGetLastError=%x (Msg=%s)\n",
rc, *ppszErrMsg? *ppszErrMsg: "<null>"));
return rc;
} //AMLIGetLastError
#endif //ifdef DEBUGGER