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.
465 lines
12 KiB
465 lines
12 KiB
#define UNICODE 1
|
|
|
|
#include <ntosp.h>
|
|
#include <zwapi.h>
|
|
#include <tdikrnl.h>
|
|
|
|
|
|
#define UINT ULONG //tmp
|
|
#include <irioctl.h>
|
|
|
|
#include <ircommtdi.h>
|
|
#include <ircommdbg.h>
|
|
|
|
NTSTATUS
|
|
IrdaOpenControlChannel(
|
|
HANDLE *ControlHandle
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK Iosb;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING DeviceName;
|
|
|
|
RtlInitUnicodeString(&DeviceName, IRDA_DEVICE_NAME);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &DeviceName,
|
|
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
|
|
|
|
Status = ZwCreateFile(
|
|
ControlHandle,
|
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
|
&ObjectAttributes,
|
|
&Iosb, // returned status information.
|
|
0, // block size (unused).
|
|
0, // file attributes.
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_CREATE, // create disposition.
|
|
0, // create options.
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
IrdaDiscoverDevices(
|
|
PDEVICELIST pDevList,
|
|
PULONG pDevListLen
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK Iosb;
|
|
HANDLE ControlHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING DeviceName;
|
|
|
|
RtlInitUnicodeString(&DeviceName, IRDA_DEVICE_NAME);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &DeviceName,
|
|
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
|
|
|
|
Status = ZwCreateFile(
|
|
&ControlHandle,
|
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
|
&ObjectAttributes,
|
|
&Iosb, // returned status information.
|
|
0, // block size (unused).
|
|
0, // file attributes.
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_CREATE, // create disposition.
|
|
0, // create options.
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
Status = ZwDeviceIoControlFile(
|
|
ControlHandle,
|
|
NULL, // EventHandle
|
|
NULL, // APC Routine
|
|
NULL, // APC Context
|
|
&Iosb,
|
|
IOCTL_IRDA_GET_INFO_ENUM_DEV,
|
|
pDevList,
|
|
*pDevListLen,
|
|
pDevList, // OutputBuffer
|
|
*pDevListLen // OutputBufferLength
|
|
);
|
|
|
|
if (Status == STATUS_PENDING )
|
|
{
|
|
Status = ZwWaitForSingleObject(ControlHandle, TRUE, NULL);
|
|
ASSERT(NT_SUCCESS(Status) );
|
|
Status = Iosb.Status;
|
|
}
|
|
|
|
ZwClose(ControlHandle);
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
IrdaIASStringQuery(
|
|
ULONG DeviceID,
|
|
PSTR ClassName,
|
|
PSTR AttributeName,
|
|
PWSTR *ReturnString
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK Iosb;
|
|
HANDLE AddressHandle;
|
|
IAS_QUERY IasQuery;
|
|
|
|
*ReturnString=NULL;
|
|
|
|
Status=IrdaOpenControlChannel(&AddressHandle);
|
|
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
D_ERROR(DbgPrint("IRCOMM: IrdaCreateAddress() failed %08lx\n",Status);)
|
|
|
|
return Status;
|
|
}
|
|
|
|
RtlCopyMemory(&IasQuery.irdaDeviceID[0],&DeviceID,sizeof(IasQuery.irdaDeviceID));
|
|
strcpy(IasQuery.irdaClassName,ClassName);
|
|
strcpy(IasQuery.irdaAttribName,AttributeName);
|
|
|
|
Status = ZwDeviceIoControlFile(
|
|
AddressHandle,
|
|
NULL, // EventHandle
|
|
NULL, // APC Routine
|
|
NULL, // APC Context
|
|
&Iosb,
|
|
IOCTL_IRDA_QUERY_IAS,
|
|
&IasQuery,
|
|
sizeof(IasQuery),
|
|
&IasQuery, // OutputBuffer
|
|
sizeof(IasQuery) // OutputBufferLength
|
|
);
|
|
|
|
if (Status == STATUS_PENDING ) {
|
|
|
|
ZwWaitForSingleObject(AddressHandle, TRUE, NULL);
|
|
Status = Iosb.Status;
|
|
}
|
|
|
|
ZwClose(AddressHandle);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return Status;
|
|
}
|
|
|
|
{
|
|
WCHAR TempBuffer[IAS_MAX_USER_STRING+1];
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
UnicodeString.Length=0;
|
|
|
|
if (IasQuery.irdaAttribute.irdaAttribUsrStr.CharSet == LmCharSetUNICODE) {
|
|
|
|
UnicodeString.MaximumLength=(USHORT)(IasQuery.irdaAttribute.irdaAttribUsrStr.Len+1);
|
|
|
|
} else {
|
|
|
|
UnicodeString.MaximumLength=(USHORT)(IasQuery.irdaAttribute.irdaAttribUsrStr.Len+1)*sizeof(WCHAR);
|
|
}
|
|
|
|
UnicodeString.Buffer=ALLOCATE_PAGED_POOL(UnicodeString.MaximumLength);
|
|
|
|
if (UnicodeString.Buffer == NULL) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(UnicodeString.Buffer,UnicodeString.MaximumLength);
|
|
|
|
//
|
|
// zero out the temp buffer, so we can copy the remote device name,
|
|
// so we can be sure it is null terminated
|
|
//
|
|
RtlZeroMemory(TempBuffer,sizeof(TempBuffer));
|
|
|
|
RtlCopyMemory(TempBuffer,IasQuery.irdaAttribute.irdaAttribUsrStr.UsrStr,IasQuery.irdaAttribute.irdaAttribUsrStr.Len);
|
|
|
|
if (IasQuery.irdaAttribute.irdaAttribUsrStr.CharSet == LmCharSetUNICODE) {
|
|
//
|
|
// the name is unicode
|
|
//
|
|
Status=RtlAppendUnicodeToString(&UnicodeString,TempBuffer);
|
|
|
|
} else {
|
|
//
|
|
// the name is ansi, need to convert unicode
|
|
//
|
|
ANSI_STRING AnsiString;
|
|
|
|
RtlInitAnsiString(
|
|
&AnsiString,
|
|
(PCSZ)TempBuffer
|
|
);
|
|
|
|
Status=RtlAnsiStringToUnicodeString(
|
|
&UnicodeString,
|
|
&AnsiString,
|
|
FALSE
|
|
);
|
|
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
*ReturnString=UnicodeString.Buffer;
|
|
|
|
} else {
|
|
|
|
FREE_POOL(UnicodeString.Buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrdaIASIntegerQuery(
|
|
ULONG DeviceID,
|
|
PSTR ClassName,
|
|
PSTR AttributeName,
|
|
LONG *ReturnValue
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK Iosb;
|
|
HANDLE AddressHandle;
|
|
IAS_QUERY IasQuery;
|
|
|
|
*ReturnValue=0;
|
|
|
|
Status=IrdaOpenControlChannel(&AddressHandle);
|
|
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
D_ERROR(DbgPrint("IRCOMM: IrdaCreateAddress() failed %08lx\n",Status);)
|
|
|
|
return Status;
|
|
}
|
|
|
|
RtlCopyMemory(&IasQuery.irdaDeviceID[0],&DeviceID,sizeof(IasQuery.irdaDeviceID));
|
|
strcpy(IasQuery.irdaClassName,ClassName);
|
|
strcpy(IasQuery.irdaAttribName,AttributeName);
|
|
|
|
Status = ZwDeviceIoControlFile(
|
|
AddressHandle,
|
|
NULL, // EventHandle
|
|
NULL, // APC Routine
|
|
NULL, // APC Context
|
|
&Iosb,
|
|
IOCTL_IRDA_QUERY_IAS,
|
|
&IasQuery,
|
|
sizeof(IasQuery),
|
|
&IasQuery, // OutputBuffer
|
|
sizeof(IasQuery) // OutputBufferLength
|
|
);
|
|
|
|
if (Status == STATUS_PENDING ) {
|
|
|
|
ZwWaitForSingleObject(AddressHandle, TRUE, NULL);
|
|
Status = Iosb.Status;
|
|
}
|
|
|
|
ZwClose(AddressHandle);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
return Status;
|
|
}
|
|
|
|
if (IasQuery.irdaAttribType != IAS_ATTRIB_INT) {
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
*ReturnValue=IasQuery.irdaAttribute.irdaAttribInt;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
IrdaIASStringSet(
|
|
HANDLE AddressHandle,
|
|
PSTR ClassName,
|
|
PSTR AttributeName,
|
|
PSTR StringToSet
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK Iosb;
|
|
IAS_SET IasSet;
|
|
|
|
|
|
strcpy(IasSet.irdaClassName,ClassName);
|
|
strcpy(IasSet.irdaAttribName,AttributeName);
|
|
IasSet.irdaAttribType=IAS_ATTRIB_STR;
|
|
IasSet.irdaAttribute.irdaAttribUsrStr.CharSet=LmCharSetASCII;
|
|
IasSet.irdaAttribute.irdaAttribUsrStr.Len=(UCHAR)strlen(StringToSet);
|
|
strcpy(IasSet.irdaAttribute.irdaAttribUsrStr.UsrStr,StringToSet);
|
|
|
|
|
|
Status = ZwDeviceIoControlFile(
|
|
AddressHandle,
|
|
NULL, // EventHandle
|
|
NULL, // APC Routine
|
|
NULL, // APC Context
|
|
&Iosb,
|
|
IOCTL_IRDA_SET_IAS,
|
|
&IasSet,
|
|
sizeof(IasSet),
|
|
&IasSet, // OutputBuffer
|
|
sizeof(IasSet) // OutputBufferLength
|
|
);
|
|
|
|
if (Status == STATUS_PENDING ) {
|
|
|
|
ZwWaitForSingleObject(AddressHandle, TRUE, NULL);
|
|
Status = Iosb.Status;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
D_ERROR(DbgPrint("IRENUM:IrdaIASStringSet() failed %08lx\n",Status);)
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrdaIASOctetSet(
|
|
PFILE_OBJECT FileObject,
|
|
PSTR ClassName,
|
|
PSTR AttributeName,
|
|
PUCHAR Value,
|
|
ULONG ValueLength
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK Iosb;
|
|
IAS_SET IasSet;
|
|
KEVENT Event;
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
KeInitializeEvent(&Event,NotificationEvent,FALSE);
|
|
|
|
strcpy(IasSet.irdaClassName,ClassName);
|
|
strcpy(IasSet.irdaAttribName,AttributeName);
|
|
IasSet.irdaAttribType=IAS_ATTRIB_OCTETSEQ;
|
|
|
|
IasSet.irdaAttribute.irdaAttribOctetSeq.Len=(USHORT)ValueLength;
|
|
RtlCopyMemory(&IasSet.irdaAttribute.irdaAttribOctetSeq.OctetSeq,Value,ValueLength);
|
|
|
|
|
|
Irp=IoBuildDeviceIoControlRequest(
|
|
IOCTL_IRDA_SET_IAS,
|
|
IoGetRelatedDeviceObject(FileObject),
|
|
&IasSet,
|
|
sizeof(IasSet),
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
&Event,
|
|
&Iosb
|
|
);
|
|
|
|
if (Irp == NULL) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
IrpSp=IoGetNextIrpStackLocation(Irp);
|
|
|
|
IrpSp->FileObject=FileObject;
|
|
|
|
IoCallDriver(
|
|
IoGetRelatedDeviceObject(FileObject),
|
|
Irp
|
|
);
|
|
|
|
|
|
KeWaitForSingleObject(
|
|
&Event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// get the final status from the io request
|
|
//
|
|
Status = Iosb.Status;
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
D_ERROR(DbgPrint("IRCOMM:IrdaIASOctetSet() failed %08lx\n",Status);)
|
|
|
|
}
|
|
//
|
|
// the irp is completed and freed by the os
|
|
//
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
IrdaLazyDiscoverDevices(
|
|
HANDLE ControlHandle,
|
|
HANDLE Event,
|
|
PIO_STATUS_BLOCK Iosb,
|
|
PDEVICELIST pDevList,
|
|
ULONG DevListLen
|
|
)
|
|
{
|
|
|
|
ZwDeviceIoControlFile(
|
|
ControlHandle,
|
|
Event, // EventHandle
|
|
NULL, // APC Routine
|
|
NULL, // APC Context
|
|
Iosb,
|
|
IOCTL_IRDA_LAZY_DISCOVERY,
|
|
NULL,
|
|
0,
|
|
pDevList, // OutputBuffer
|
|
DevListLen // OutputBufferLength
|
|
);
|
|
|
|
|
|
return;
|
|
}
|