Hi All,
Im using APC mechanism to notify a user application from the kernel and using KeIntilizeAPC() and KeInsertQueueAPC().
I register a callback function and user level memory buffer using IOCTL.
Kernel notifies the user application of some event via this registered callback function and passes some data along with it. The event data it copies to the user level memory buffer using RtlCopyMemory().
But actually kernel fails to copy the data to the user memory buffer. Please suggest some mechanism so that the desired functionality is achieved.
Code to register APC callback function:
case IOCTL_VPE_REG_USER_APC:
{
UINT32 cap_status;
UINT32 *ret_val;
AR_PRegUserApc puser_apc;
puser_apc = ( AR_PRegUserApc ) user_buffer;
cap_status = cap_see_register_apc(puser_apc);
ret_val = (UINT16 * ) user_buffer;
*ret_val= cap_status;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(UINT32);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
AR_SEE_STATUS
cap_see_register_apc(AR_PRegUserApc puser_apc)
{
/* Should be global and in nonPaged Pool */
PKTHREAD pTargetThread = KeGetCurrentThread();
/**/
//PKNORMAL_ROUTINE gblNormalRtn;
pPoolTargetThread = (PKTHREAD)ExAllocatePool(NonPagedPool,sizeof(PKTHREAD));
pPoolTargetThread = pTargetThread;
gblAPCRtn = (PKNORMAL_ROUTINE)ExAllocatePool(NonPagedPool,sizeof(PKNORMAL_ROUTINE));
gblAPCRtn = (PKNORMAL_ROUTINE)puser_apc->target_proc;
gblEvtMemory = ExAllocatePool(NonPagedPool,sizeof(void *));
gblEvtMemory = puser_apc->evtMemory;
return AR_SEE_SUCCESS;
}
Code to queue apc and to copy data:
void QueueUserAPC(HANDLE pID,
unsigned long evtDev,
unsigned long evtType,
unsigned long evtLen,
void * data
)
{
PKAPC pKAPC;
PKKERNEL_ROUTINE lclKernelRtn = // Point to driver routine that will be used as kernel routine.
(PKKERNEL_ROUTINE)KrnlRoutine;
KAPC_ENVIRONMENT lclEnvironment;
UCHAR lclApcMode = UserMode;
// eventT ApcData;
struct APCData ApcData;
ApcData.data1 = 1;
ApcData.data2 = 2;
ApcData.devHandle = evtDev;
ApcData.digits[0] = ‘3’;
ApcData.evtDev = evtDev;
ApcData.evtLen = evtLen;
ApcData.evtType = evtType;
ApcData.opernResult = 4;
ApcData.pID = pID;
RtlCopyMemory(gblEvtMemory,(void *)&ApcData,sizeof(ApcData));
pKAPC = (PKAPC)ExAllocatePoolWithTag( // Allocate space for KAPC object.
NonPagedPool,
sizeof(KAPC),
‘jaja’
);
if (NULL==pKAPC)
{
return;
}
// Inasmuch as errors (BSODs) arose in KeInsertQueueApc with certain combinations of parameters in KeInitializeApc,
// clear the KAPC first.
memset(pKAPC, 0, sizeof(KAPC));
lclEnvironment = CurrentApcEnvironment;
/*
* this apc informs the user mode api that there is a pending evvent in the event queue of the kernel
* and that an ioctl must be issued to retreive it. Also the event dispatcher in the user mode
* is intelligent enough to decide , to whom this event is to be dispatched
*/
KeInitializeApc(
pKAPC,
pPoolTargetThread,
lclEnvironment,
lclKernelRtn,
NULL,
gblAPCRtn,
lclApcMode,
((PVOID)NULL)
);
KeInsertQueueApc(
pKAPC,
NULL,
NULL,
0);
*((unsigned char *)pPoolTargetThread+0x4a) = 1; // Set KAPC_STATE.UserApcPending on.
}
Regards,
Rajeev