Hello
I wish I had one source sample C that communicates by pipe of user-mode<–>kernel-mode.
A Sample which work please !
I understand nothing at all!
Thank you.
Party function Vdum_Compipe :
status = IoCallDriver(io_stack->FileObject->DeviceObject, irp);
if (status == STATUS_PENDING)
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); // There is blocking same why ReadFile of this pipe is called of user-mode
else if (!NT_SUCCESS(status))
break;
But the pipe is creating!
Incomplete Sample :
typedef struct {
WCHAR pipe[64];
WCHAR eventrecv[64];
WCHAR eventsend[64];
DWORD sizeko;
CHAR letter;
DISK_GEOMETRY disk_geometry;
UCHAR time_out;
}TCONFIGVD,*PCONFIGVD;
Kernel-Mode
NTSTATUS vdums_deviceiocontrol(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp, PIO_STACK_LOCATION irps)
{
NTSTATUS status=STATUS_NOT_IMPLEMENTED;
…
switch (iocode)
{
…
…
case IOCTL_CMD_PARAMETERVIRTUALDISK:
{
WCHAR eventsend[256];
WCHAR eventrecv[256];
KdPrint((“[VDUM] CMD ParametreVirtualDisk\n”));
if ((irps->Parameters.DeviceIoControl.InputBufferLength < sizeof(TCONFIGVD)))
{
KdPrint((“[VDUM] CMD ParametreVirtualDisk Size mismatch\n”));
status = STATUS_INVALID_PARAMETER;
irp->IoStatus.Information = 0;
break;
}
configvd=(PCONFIGVD)irp->AssociatedIrp.SystemBuffer;
lod=VDUM_GetDevice(configvd->letter);
status=STATUS_INVALID_HANDLE;
if (lod!=0)
{
UNICODE_STRING uszNotifyEventString,pipe_name,uszsend,uszrecv;
KdPrint((“[VDUM] CMD ParametreVirtualDisk lod ok\n”));
paramvd=(PPARAMVD) lod->DeviceExtension;
/*RtlInitUnicodeString(&uszNotifyEventString,
configvd->eventrecv);
paramvd->eventrecv = IoCreateNotificationEvent(&uszNotifyEventString, ¶mvd->NotifyHandleRecv);*/
//if (paramvd->eventrecv!=NULL)
{
KdPrint((“[VDUM] CMD ParametreVirtualDisk eventrecv ok\n”));
wcscpy(eventsend,L"\BaseNamedObjects\“);
wcscpy(eventrecv,L”\BaseNamedObjects\“);
wcscat(eventsend,configvd->eventsend);
wcscat(eventrecv,configvd->eventrecv);
KdPrint((”[VDUM] CMD ParametreVirtualDisk EventSend Name %ws\n",eventsend));
KdPrint((“[VDUM] CMD ParametreVirtualDisk EventRecv Name %ws\n”,eventrecv));
RtlInitUnicodeString(&uszsend,
eventsend);
RtlInitUnicodeString(&uszrecv,
eventrecv);
paramvd->eventsend = IoCreateNotificationEvent(&uszsend, ¶mvd->NotifyHandleSend);
paramvd->eventrecv = IoCreateNotificationEvent(&uszrecv, ¶mvd->NotifyHandleRecv);
KeClearEvent(paramvd->eventsend);
KeClearEvent(paramvd->eventrecv);
if (paramvd->eventsend!=NULL)
{
KdPrint((“[VDUM] CMD ParametreVirtualDisk eventsend ok\n”));
wcscpy(wpipe,L"\??\pipe\");
wcscat(wpipe,configvd->pipe);
paramvd->sizeko=configvd->sizeko;
paramvd->disk_geometry=configvd->disk_geometry;
paramvd->time_out=configvd->time_out;
KdPrint((“[VDUM] CMD ParametreVirtualDisk pipe name %ws\n”,wpipe));
RtlInitUnicodeString(
&pipe_name,
wpipe
);
InitializeObjectAttributes(
&attr,
&pipe_name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
status = ZwCreateFile(
¶mvd->file_handle,
GENERIC_READ | GENERIC_WRITE , // or FILE_READ_DATA
&attr,
&io_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ |
FILE_SHARE_DELETE |
FILE_SHARE_WRITE,
FILE_OPEN,
//IMDISK_TYPE(CreateData->Flags) == IMDISK_TYPE_PROXY ?
FILE_NON_DIRECTORY_FILE |
FILE_SEQUENTIAL_ONLY |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT |
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (status==STATUS_SUCCESS)
{
status =
ObReferenceObjectByHandle(paramvd->file_handle,
FILE_READ_ATTRIBUTES |
FILE_READ_DATA |
FILE_WRITE_DATA,
*IoFileObjectType,
KernelMode,
¶mvd->pipe,
NULL);
if (status==STATUS_SUCCESS)
{
KdPrint((“[VDUM] CMD ParametreVirtualDisk pipe ok\n”));
irp->IoStatus.Information=0;
paramvd->parametrer=TRUE;
status=STATUS_SUCCESS;
}
else
{
KdPrint((“[VDUM] CMD ParametreVirtualDisk pipeerror %x \n”,status));
}
}
else
KdPrint((“[VDUM] ZwCreateFile status returned %x \n”,status));
}
else
{
KdPrint((“[VDUM] CMD ParametreVirtualDisk eventsend fail\n”));
ZwClose(¶mvd->eventrecv);
status=STATUS_INSUFFICIENT_RESOURCES;
}
}
/*else
{
KdPrint((“[VDUM] CMD ParametreVirtualDisk eventrecv fail\n”));
status=STATUS_INSUFFICIENT_RESOURCES;
}*/
}
}
break;
}
…
…
NTSTATUS COM_PIPE(PCP cp)
{
NTSTATUS status=STATUS_SUCCESS;
LARGE_INTEGER dt;
UCHAR len;
PIO_STATUS_BLOCK ios=cp->iostatusblock;
ULONG length=cp->_length;
//LONGLONG offset=(cp->offsethigh<<32)+cp->offsetlow;
ULONG offsethigh=cp->offsethigh;
ULONG offsetlow=cp->offsetlow;
PPARAMVD pvd=cp->pvd;
BOOLEAN writedirect=cp->writedirect;
UCHAR* buffer=cp->buffer;
UCHAR *commande=cp->commande;
//KdPrint((“COM PIPE 1 Commande %s Offset:%x Length:%p\n”,commande,offset,length));
KdPrint((“COM PIPE Offset:%p%p Length:%p\n”,offsethigh,offsetlow,length));
RtlZeroMemory(&dt, sizeof(LARGE_INTEGER));
KeSetEvent(pvd->eventrecv,(KPRIORITY) 0, FALSE);
KeClearEvent(pvd->eventrecv);
len=strlen(commande);
//KdPrint((“COM PIPE 2 Offset:%p%p Length:%p\n”,offsethigh,offsetlow,length));
VDUM_ReadPipe(pvd->pipe,ios,&writedirect,1,&dt,&status);
VDUM_ReadPipe(pvd->pipe,ios,&len,1,&dt,&status);
VDUM_ReadPipe(pvd->pipe,ios,commande,len,&dt,&status);
VDUM_ReadPipe(pvd->pipe,ios,&offsetlow,sizeof (ULONG),&dt,&status);
VDUM_ReadPipe(pvd->pipe,ios,&offsethigh,sizeof (ULONG),&dt,&status);
VDUM_ReadPipe(pvd->pipe,ios,&length,sizeof (ULONG),&dt,&status);
if (status!=STATUS_SUCCESS)
{
KdPrint((“Status VDUM_ReadPipe IN return %x\n”,status));
return status;
}
if (writedirect)
{
VDUM_WritePipe(pvd->pipe,ios,buffer,length,&dt,&status);
}
if (status!=STATUS_SUCCESS)
{
KdPrint((“Status VDUM_WritePipe IN return %x\n”,status));
return status;
}
else
{
status=KeWaitForSingleObject(&pvd->eventsend,
Executive,
KernelMode,
FALSE,
pvd->time_out*1000);
if (status!=STATUS_SUCCESS)
{
KdPrint((“Status KeWaitForSingleObject return %x\n”,status));
}
else
{
CHAR flag=0;
status=VDUM_ReadPipe(pvd->pipe,ios,&flag,1,&dt,&status);
if (status==STATUS_SUCCESS)
{
switch (flag)
{
case 0:
if (!writedirect)
status=VDUM_ReadPipe(pvd->pipe,ios,buffer,length,&dt,&status);
if (status!=STATUS_SUCCESS)
{
KdPrint((“Status VDUM_ReadPipe OUT return %x\n”,status));
return status;
}
break;
case 1:status=STATUS_ACCESS_DENIED;break;
case 2:status=STATUS_NOT_IMPLEMENTED;break;
case 3:status=STATUS_MEDIA_WRITE_PROTECTED;break;
}
KdPrint((“Status COM_PIPE personalize OUT return %x\n”,status));
}
else
{
if (status!=STATUS_SUCCESS)
{
KdPrint((“Status ZwReadFile OUT return %x\n”,status));
}
}
}
}
return status;
}
NTSTATUS
VDUM_ComPipe(IN PFILE_OBJECT FileObject,
IN UCHAR MajorFunction,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length)
{
NTSTATUS status;
//IO_STATUS_BLOCK IoStatusBlock;
ULONG length_done = 0;
KEVENT event;
PIO_STACK_LOCATION io_stack;
LARGE_INTEGER offset = { 0 };
PAGED_CODE();
KdPrint((“[VDUM]: FileObject=%#x, MajorFunction=%#x, IoStatusBlock=%#x, Buffer=%#x, Length=%#x.\n”, FileObject, MajorFunction, IoStatusBlock, Buffer, Length));
ASSERT(FileObject != NULL);
ASSERT(IoStatusBlock != NULL);
ASSERT(Buffer != NULL);
KeInitializeEvent(&event,
NotificationEvent,
FALSE);
while (length_done < Length)
{
ULONG RequestLength = Length - length_done;
do
{
PIRP irp;
KdPrint((“[VDUM]: Building IRP…\n”));
irp = IoBuildSynchronousFsdRequest(MajorFunction,
FileObject->DeviceObject,
(PUCHAR) Buffer + length_done,
RequestLength,
&offset,
&event,
IoStatusBlock);
if (irp == NULL)
{
KdPrint((“[VDUM]: Error building IRP.\n”));
IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
IoStatusBlock->Information = length_done;
return IoStatusBlock->Status;
}
KdPrint((“[VDUM] : Built IRP=%#x.\n”, irp));
io_stack = IoGetNextIrpStackLocation(irp);
io_stack->FileObject = FileObject;
io_stack->DeviceObject = FileObject->DeviceObject;
KdPrint((“[VDUM]: MajorFunction= %#x, Length=%#x\n”,
io_stack->MajorFunction,
io_stack->Parameters.Write.Length));
KeResetEvent(&event);
status = IoCallDriver(io_stack->FileObject->DeviceObject, irp);
if (status == STATUS_PENDING)
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
else if (!NT_SUCCESS(status))
break;
status = IoStatusBlock->Status;
KdPrint((“[VDUM]: IRP %#x completed. Status=%#x.\n”,
irp, IoStatusBlock->Status));
RequestLength >>= 1;
}
while ((status == STATUS_INVALID_BUFFER_SIZE) |
(status == STATUS_INVALID_PARAMETER));
if (!NT_SUCCESS(status))
{
KdPrint((“[VDUM]: I/O failed. Status=%#x.\n”, status));
IoStatusBlock->Status = status;
IoStatusBlock->Information = 0;
return IoStatusBlock->Status;
}
KdPrint((“[VDUM]: I/O done. Status=%#x. Length=%#x\n”,
status, IoStatusBlock->Information));
if (IoStatusBlock->Information == 0)
{
IoStatusBlock->Status = STATUS_CONNECTION_RESET;
IoStatusBlock->Information = 0;
return IoStatusBlock->Status;
}
length_done += (ULONG) IoStatusBlock->Information;
}
KdPrint((“[VDUM]: I/O complete.\n”));
IoStatusBlock->Status = STATUS_SUCCESS;
IoStatusBlock->Information = length_done;
return IoStatusBlock->Status;
}
NTSTATUS
VDUM_ReadPipe(IN PFILE_OBJECT ProxyDevice,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset,
NTSTATUS *status)
{
PAGED_CODE();
/*ASSERT(ProxyDevice != NULL);
ASSERT(IoStatusBlock != NULL);
ASSERT(Buffer != NULL);
ASSERT(ByteOffset != NULL);*/
if (*status==STATUS_SUCCESS)
{
*status = VDUM_ComPipe(ProxyDevice,
IRP_MJ_READ,
IoStatusBlock,
Buffer,
(ULONG) Length);
if (!NT_SUCCESS(*status))
KdPrint(("[VDUM] Proxy Client: Data stream of %u bytes received with I/O "
“status %#x. Status returned by stream reader is %#x.\n”,
IoStatusBlock->Information, IoStatusBlock->Status, status));
KdPrint
((“[VDUM]: Received %u byte data stream.\n”,
IoStatusBlock->Information));
}
return *status;
}
typedef struct {
PPARAMVD pvd;
UCHAR *commande;
//LONGLONG offset;
ULONG offsethigh;
ULONG offsetlow;
ULONG _length;
UCHAR *buffer;
BOOLEAN writedirect;
PIO_STATUS_BLOCK iostatusblock;
}TCP,*PCP;
…
…
case IRP_MJ_READ:
TCP cp;
ULONG len=0;
ULONG lxx=0;
LONGLONG xl=0;
PUCHAR buffer;
PUCHAR system_buffer =
(PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress,
NormalPagePriority);
LARGE_INTEGER offset;
if (system_buffer == NULL)
{
status=irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0;
break;
}
buffer = (PUCHAR)ExAllocatePool(NonPagedPool, io_stack->Parameters.Read.Length);
if (buffer == NULL)
{
status=irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0;
break;
}
if (io_stack->MajorFunction==IRP_MJ_WRITE)
{
KdPrint((“[VDUM] Device %i got write request Offset=%p%p Len=%p.\n”,
pvd->index,
io_stack->Parameters.Read.ByteOffset.HighPart,
io_stack->Parameters.Read.ByteOffset.LowPart,
io_stack->Parameters.Read.Length));
RtlCopyMemory(buffer,system_buffer, irp->IoStatus.Information);
xl=io_stack->Parameters.Read.ByteOffset.LowPart+(io_stack->Parameters.Read.ByteOffset.HighPart<<32);
cp.pvd=pvd;
cp.commande=cWRITE;
//cp.offset=xl;
cp.offsethigh=io_stack->Parameters.Read.ByteOffset.HighPart;
cp.offsetlow=io_stack->Parameters.Read.ByteOffset.LowPart;
cp._length=io_stack->Parameters.Read.Length;
cp.writedirect=TRUE;
cp.iostatusblock=&irp->IoStatus;
status=COM_PIPE(&cp);
irp->IoStatus.Information=0;
}
else
if (io_stack->MajorFunction==IRP_MJ_READ)
{
len=io_stack->Parameters.Read.Length;
xl=io_stack->Parameters.Read.ByteOffset.LowPart+(io_stack->Parameters.Read.ByteOffset.HighPart<<32);
irp->IoStatus.Information = io_stack->Parameters.Read.Length;
cp._length=len;
cp.pvd=pvd;
cp.commande=cREAD;
cp.offsethigh=io_stack->Parameters.Read.ByteOffset.HighPart;
cp.offsetlow=io_stack->Parameters.Read.ByteOffset.LowPart;
cp.writedirect=FALSE;
cp.iostatusblock=&irp->IoStatus;
status=COM_PIPE(&cp);
if (status==STATUS_SUCCESS)
RtlCopyMemory(system_buffer, buffer,irp->IoStatus.Information);
if (status!=STATUS_SUCCESS)
irp->IoStatus.Information=0;
}
ExFreePool(buffer);
}
break;
User - mode :
DWORD WINAPI threadC(PVOID context)
{
PCT ct=(PCT)context;
Sleep(3000);
DWORD dt=0;
DeviceIoControl(ct->hf,IOCTL_CMD_PARAMETERVIRTUALDISK,ct->configvd,sizeof (TCONFIGVD),NULL,0,&dt,NULL);
ct->heventrecv=OpenEvent(SYNCHRONIZE,false,“VDUMeventrecv”);
ct->heventsend=OpenEvent(SYNCHRONIZE,false,“VDUMeventsend”);
return 0;
}
wcscpy(configvd->pipe,L"VDUMtest");
wcscpy(configvd->eventrecv,L"VDUMeventrecv");
wcscpy(configvd->eventsend,L"VDUMeventsend");
HANDLE hConnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
TCHAR s2[128];
HANDLE hPipe = CreateNamedPipe(
“\\.\Pipe\VDUMtest”, // pipe name
PIPE_ACCESS_DUPLEX| // read/write access
FILE_FLAG_WRITE_THROUGH, // message type pipe
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
100, // client time-out
NULL);
// default security attribute
DWORD dt=0;
SetLastError(0);
WORD thid=0;
hthread=CreateThread(NULL,0,threadC,ct,0,&thid);
if (fConnected)
{
while (!sort)
{
char commande[64];
char len=0;
int x=WaitForSingleObject(ct->heventrecv,5000);
if ((x==WAIT_OBJECT_0)&&(!sort))
{
DWORD dt=0;
bool writedirect=false;
LARGE_INTEGER offset;
ZeroMemory(&offset,sizeof (LARGE_INTEGER));
ULONG length=0;
ReadFile(hPipe,&writedirect,1,&dt,NULL);
Can you help please ???
A Access at IRP_MJ_READ , the event ct->heventrecv is setted by kernel but ReadFile Block
Yet although the driver called function COM_PIPE to send data to the pipe.
I understand nothing at all!
Thank you