![]() |
|
![]() |
|
|
|
|
||
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
|
Frequently Asked QuestionsCopyright (C) www.ntkernel.com 2000-2005 (prepared using NT Kernel Resources web BBS materials) Q: How to install Windows NDIS intermediate driver based on Windows 2000 PASSTHRU sample on Windows 98? A: You can use use the INF file below: ;---------------------------------------------------------------------------;
Q: Where can I get the definition of NDIS_PROTOCOL_BLOCK structure? Does it depend of Windows version or NDIS version? A: _NDIS_PROTOCOL_BLOCK structure definition depends of Windows and NDIS versions and it's just partially documented by Microsoft. Some it's definitions can be found in ndis.h. An example, for Windows XP NDIS_PROTOCOL_BLOCK defined as the following: struct _NDIS_PROTOCOL_BLOCK
{
_NDIS_OPEN_BLOCK* OpenQueue;
_REFERENCE Ref;
_KEVENT* DeregEvent;
_NDIS_PROTOCOL_BLOCK* NextProtocol;
_NDIS50_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics;
_WORK_QUEUE_ITEM WorkItem;
_KMUTANT Mutex;
DWORD MutexOwner;
_UNICODE_STRING* BindDeviceName;
_UNICODE_STRING* RootDeviceName;
_NDIS_M_DRIVER_BLOCK* AssociatedMiniDriver;
_NDIS_MINIPORT_BLOCK* BindingAdapter;
};
But in ndis.h for Windows ME you can find the following definition: struct _NDIS_PROTOCOL_BLOCK
{
PNDIS_OPEN_BLOCK OpenQueue; // queue of opens for this protocol
REFERENCE Ref; // contains spinlock for OpenQueue
UINT Length; // of this NDIS_PROTOCOL_BLOCK struct
NDIS50_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics;// handler addresses struct
_NDIS_PROTOCOL_BLOCK * NextProtocol; // Link to next
ULONG MaxPatternSize;
#if defined(NDIS_WRAPPER)
//
// Protocol filters
//
struct _NDIS_PROTOCOL_FILTER * ProtocolFilter[NdisMediumMax+1];
WORK_QUEUE_ITEM WorkItem; // Used during NdisRegisterProtocol to
// notify protocols of existing drivers.
KMUTEX Mutex; // For serialization of Bind/Unbind requests
PKEVENT DeregEvent; // Used by NdisDeregisterProtocol
#endif
};
As you can see this structure definition depends of NDIS_PROTOCOL_CHARACTERISTICS definition, which is NDIS version dependent. The Windows version dependence does not need any comments. Q: netbt.sys calls tcpip!TCPSendData directly. How can this be explained? A: Yes, that's true, tcpip.sys can be requested for the pointer to the internal routine tcpip!TCPSendData. You can see the processing of the particular request (IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER) in reversed engineered code of tcpip!TCPDispatch. This interface improves performance of kernel-mode tcpip.sys clients.
TDI_STATUS TCPDispatch(PDEVICE_OBJECT pDeviceObject,PIRP Irp)
{
TDI_STATUS Status;
PIO_STACK_LOCATION irpStack;
// try-except exists only in the W2K/XP version of TCPIP.SYS
__try
{
// IpMcastDeviceObject exists only in the W2K/XP version of TCPIP.SYS
if (pDeviceObject == IpMcastDeviceObject)
return IpMcastDispatch(pDeviceObject,Irp);
if (pDeviceObject == IPDeviceObject)
return IPDispatch(pDeviceObject,Irp);
irpStack = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0;
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
Status = TCPCreate(pDeviceObject,Irp,irpStack);
break;
case IRP_MJ_CLOSE:
Status = TCPClose(Irp,irpStack);
break;
case IRP_MJ_WRITE:
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
case IRP_MJ_DEVICE_CONTROL:
if (NT_SUCCESS(TdiMapUserRequest(pDeviceObject,Irp,irpStack)))
return TCPDispatchInternalDeviceControl(pDeviceObject,Irp);
else
{
if (irpStack->Parameters.DeviceIoControl.IoControlCode
== IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER)
{
// exists only in W2K/XP
if (Irp->RequestorMode == UserMode)
ProbeForWrite (
irpStack->Parameters.DeviceIoControl.Type3InputBuffer,
sizeof(PULONG),
4
);
irpStack->Parameters.DeviceIoControl.Type3InputBuffer
= TCPSendData;
Status = STATUS_SUCCESS;
}
else
return TCPDispatchDeviceControl(Irp,irpStack);
}
break;
case IRP_MJ_CLEANUP:
Status = TCPCleanup(pDeviceObject,Irp,irpStack);
break;
case IRP_MJ_QUERY_SECURITY:
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
case IRP_MJ_SYSTEM_CONTROL: // exists only in W2K/XP
return TCPEventTraceControl(pDeviceObject,Irp);
case IRP_MJ_PNP_POWER: // exists only in W2K/XP
Status = TCPDispatchPnPPower(Irp,irpStack);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// does something (I don't know what exactly) in the case of an exception
// ProbeForWrite can rise an exception
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp,IO_NETWORK_INCREMENT);
return Status;
}
Q: How can I create named pipe in the kernel-mode (NtCreateNamedPipeFile/ZwCreateNamedPipeFile is not exported by ntoskrnl.exe)? A: There are several ways to do this:
.text:77F883D6 public ZwCreateNamedPipeFile .text:77F883D6 ZwCreateNamedPipeFile proc near .text:77F883D6 .text:77F883D6 arg_0 = byte ptr 4 .text:77F883D6 .text:77F883D6 mov eax, 26h ; NtCreateNamedPipeFile .text:77F883DB lea edx, [esp+arg_0] .text:77F883DF int 2Eh ; DOS 2+ internal - EXECUTE COMMAND .text:77F883DF ; DS:SI -> counted CR-terminated command string .text:77F883E1 retn 38h .text:77F883E1 ZwCreateNamedPipeFile endp
NTSTATUS NtCreateNamedPipeFile (
OUT PHANDLE FileHandle,
IN ULONG DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN ULONG NamedPipeType,
IN ULONG ReadMode,
IN ULONG CompletionMode,
IN ULONG MaximumInstances,
IN ULONG InboundQuota,
IN ULONG OutboundQuota,
IN PLARGE_INTEGER DefaultTimeout OPTIONAL
)
{
NAMED_PIPE_CREATE_PARAMETERS NamedPipeParms;
NTSTATUS Status;
__try
{
if ( DefaultTimeout )
{
NamedPipeParms.TimeoutSpecified = TRUE;
NamedPipeParms.DefaultTimeout.QuadPart = DefaultTimeout->QuadPart;
}
else
{
NamedPipeParms.TimeoutSpecified = FALSE;
}
NamedPipeParms.NamedPipeType = NamedPipeType;
NamedPipeParms.ReadMode = ReadMode;
NamedPipeParms.CompletionMode = CompletionMode;
NamedPipeParms.MaximumInstances = MaximumInstances;
NamedPipeParms.InboundQuota = InboundQuota;
NamedPipeParms.OutboundQuota = OutboundQuota;
Status = IoCreateFile (
FileHandle,
DesiredAccess,
ObjectAttributes,
IoStatusBlock,
NULL,
0,
ShareAccess,
CreateDisposition,
CreateOptions,
NULL,
0,
CreateFileTypeNamedPipe,
&NamedPipeParms,
0
);
return Status;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KdPrint (("NtCreateNamedPipeFile: Exception occured.\n"));
return STATUS_UNSUCCESSFUL;
}
}
The routine can be called as the following: #define NAMED_PIPE_NAME L"\\??\\pipe\\PipeClient"
...
// Some code skipped
...
RtlInitUnicodeString ( &namedPipe, NAMED_PIPE_NAME );
InitializeObjectAttributes (
&attr,
&namedPipe,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
nTimeOut.QuadPart = -1000;
// Create Named Pipe
ntStatus = NtCreateNamedPipeFile (
&g_hNamedPipeHandle,
FILE_ANY_ACCESS,
&attr,
&ioStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_CREATE,
0,
FILE_PIPE_BYTE_STREAM_TYPE,
FILE_PIPE_BYTE_STREAM_MODE,
FILE_PIPE_QUEUE_OPERATION,
1,
0,
0,
&nTimeOut
);
if (NT_SUCCESS (ntStatus))
{
KdPrint (("Pipe created succesfully\n"));
}
Please pay attention to two important notes:
| ||
|
Copyright © NT Kernel Resources, 2000-2009. Design & Programming by Multi Service |
|||