///////////////////////////////////////////////////////// // // Copyright (c) 2001 Microsoft Corporation // // Module Name: // open.cpp // // Abstract: // This module contains code which deals with opening and closing // of the various types of tdi objects // ////////////////////////////////////////////////////////// #include "sysvars.h" extern "C" { #pragma warning(disable: NAMELESS_STRUCT_UNION) #include "tdiinfo.h" #pragma warning(default: NAMELESS_STRUCT_UNION) } // // defines stolen from include files not in ddk // #define AO_OPTION_IP_UCASTIF 17 #define FSCTL_TCP_BASE FILE_DEVICE_NETWORK #define _TCP_CTL_CODE(function, method, access) \ CTL_CODE(FSCTL_TCP_BASE, function, method, access) #define IOCTL_TCP_WSH_SET_INFORMATION_EX \ _TCP_CTL_CODE(10, METHOD_BUFFERED, FILE_ANY_ACCESS) // // end of stolen defines // ////////////////////////////////////////////////////////////// // private constants and prototypes ////////////////////////////////////////////////////////////// const PCHAR strFunc1 = "TSOpenControl"; const PCHAR strFunc2 = "TSCloseControl"; const PCHAR strFunc3 = "TSOpenAddress"; const PCHAR strFunc4 = "TSCloseAddress"; const PCHAR strFunc5 = "TSOpenEndpoint"; const PCHAR strFunc6 = "TSCloseEndpoint"; //const PCHAR strFuncP1 = "TSCompleteCommand"; const PCHAR strFuncP2 = "TSPerformOpenControl"; const PCHAR strFuncP3 = "TSPerformOpenAddress"; const PCHAR strFuncP4 = "TSPerformOpenEndpoint"; const PCHAR strFuncP5 = "TSPerformAssociate"; const PCHAR strFuncP6 = "TSPerformDisassociate"; TDI_STATUS TSCompleteCommand( PDEVICE_OBJECT pDeviceObject, PIRP pLowerIrp, PVOID pvContext ); NTSTATUS TSPerformOpenControl( PCONTROL_CHANNEL pControlChannel, PUCNTSTRING pucString ); NTSTATUS TSPerformOpenAddress( PADDRESS_OBJECT pAddressObject, PUCNTSTRING pucString, PTRANSPORT_ADDRESS pTransportAddress, BOOLEAN fIsConnect ); NTSTATUS TSPerformOpenEndpoint( PENDPOINT_OBJECT pEndpointObject, PUCNTSTRING pucString ); NTSTATUS TSPerformAssociate( PENDPOINT_OBJECT pEndpoint ); VOID TSPerformDisassociate( PENDPOINT_OBJECT pEndpoint ); ////////////////////////////////////////////////////////////// // public functions ////////////////////////////////////////////////////////////// // ---------------------------------------------------------------------------- // // Function: TSOpenControl // // Arguments: pSendBuffer -- arguments from user dll for open command // pIrp -- completion information // // Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode) // // Descript: This function sets up the structure for a new control channel, // and attempts to open the specified control channel // // ---------------------------------------------------------------------------- NTSTATUS TSOpenControl(PSEND_BUFFER pSendBuffer, PRECEIVE_BUFFER pReceiveBuffer) { PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName; // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint1("\nCommand = ulOPENCONTROL\n" "DeviceName = %ws\n", pucString->wcBuffer); } // // allocate our structure and put it in the linked list... // PCONTROL_CHANNEL pControlChannel; NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pControlChannel, sizeof(CONTROL_CHANNEL), strFunc1, "ControlChannel"); if (lStatus == STATUS_SUCCESS) { pControlChannel->GenHead.ulSignature = ulControlChannelObject; ULONG ulTdiHandle = TSInsertNode(&pControlChannel->GenHead); if (ulTdiHandle) { lStatus = TSPerformOpenControl(pControlChannel, pucString); if (lStatus == STATUS_SUCCESS) { pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle; return STATUS_SUCCESS; } // // handle errors in PerformOpenControl // TSRemoveNode(ulTdiHandle); } else { lStatus = STATUS_INSUFFICIENT_RESOURCES; } TSFreeMemory(pControlChannel); } return lStatus; } // ----------------------------------------------------------------- // // Function: TSCloseControl // // Arguments: pControlChannel -- our control channel object to close // // Returns: none // // Descript: This function frees the resources for a control channel, // and calls the tdi provider to close it // // ---------------------------------------------------------------------------- VOID TSCloseControl(PCONTROL_CHANNEL pControlChannel) { // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint1("\nCommand = ulCLOSECONTROL\n" "ControlChannel = %p\n", pControlChannel); } ObDereferenceObject(pControlChannel->GenHead.pFileObject); NTSTATUS lStatus = ZwClose(pControlChannel->GenHead.FileHandle); if (lStatus != STATUS_SUCCESS) { DebugPrint2("%s: ZwClose failed with status 0x%08x\n", strFunc2, lStatus); } TSFreeMemory(pControlChannel); } // ----------------------------------------------------------------- // // Function: TSOpenAddress // // Arguments: pSendBuffer -- arguments from user dll for open command // pIrp -- completion information // // Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode) // // Descript: This function sets up the structure for a new address object, // and attempts to open the specified address object // // ---------------------------------------------------------------------------- NTSTATUS TSOpenAddress(PSEND_BUFFER pSendBuffer, PRECEIVE_BUFFER pReceiveBuffer) { PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName; PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.OpenArgs.TransAddr; // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint1("\nCommand = ulOPENADDRESS\n" "DeviceName = %ws\n", pucString->wcBuffer); TSPrintTaAddress(pTransportAddress->Address); } // // allocate our structure and put it in the linked list... // PADDRESS_OBJECT pAddressObject; NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pAddressObject, sizeof(ADDRESS_OBJECT), strFunc3, "AddressObject"); if (lStatus == STATUS_SUCCESS) { pAddressObject->GenHead.ulSignature = ulAddressObject; ULONG ulTdiHandle = TSInsertNode(&pAddressObject->GenHead); if (ulTdiHandle) { lStatus = TSPerformOpenAddress(pAddressObject, pucString, pTransportAddress, FALSE); if (lStatus == STATUS_SUCCESS) { pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle; return STATUS_SUCCESS; } // // handle error in PerformOpenAddress // TSRemoveNode(ulTdiHandle); } else { lStatus = STATUS_INSUFFICIENT_RESOURCES; } TSFreeMemory(pAddressObject); } return lStatus; } // ----------------------------------------------------------------- // // Function: TSCloseAddress // // Arguments: pAddressObject -- address object to close // // Returns: none // // Descript: This function frees the resources for an address object, // and calls the tdi provider to close it // // ---------------------------------------------------------------------------- VOID TSCloseAddress(PADDRESS_OBJECT pAddressObject) { // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint1("\nCommand = ulCLOSEADDRESS\n" "AddressObject = %p\n", pAddressObject); } TSFreeSpinLock(&pAddressObject->TdiSpinLock); TSFreePacketData(pAddressObject); ObDereferenceObject(pAddressObject->GenHead.pFileObject); if (pAddressObject->pIrpPool) { TSFreeIrpPool(pAddressObject->pIrpPool); } NTSTATUS lStatus = ZwClose(pAddressObject->GenHead.FileHandle); if (lStatus != STATUS_SUCCESS) { DebugPrint2("%s: ZwClose failed with status 0x%08x\n", strFunc4, lStatus); } TSFreeMemory(pAddressObject); } // ----------------------------------------------------------------- // // Function: TSOpenEndpoint // // Arguments: pSendBuffer -- arguments from user dll for open command // pIrp -- completion information // // Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode) // // Descript: This function sets up the structure for an endpoint. This // involves opening an endpoint, opening an address object, and // associating them... // // ---------------------------------------------------------------------------- NTSTATUS TSOpenEndpoint(PSEND_BUFFER pSendBuffer, PRECEIVE_BUFFER pReceiveBuffer) { PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName; PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.OpenArgs.TransAddr; // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint1("\nCommand = ulOPENENDPOINT\n" "DeviceName = %ws\n", pucString->wcBuffer); TSPrintTaAddress(pTransportAddress->Address); } // // set up for the file open // need to do our "context" structure first, since the // eabuffer requires it... // PENDPOINT_OBJECT pEndpoint; NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pEndpoint, sizeof(ENDPOINT_OBJECT), strFunc5, "EndpointObject"); if (lStatus == STATUS_SUCCESS) { pEndpoint->GenHead.ulSignature = ulEndpointObject; ULONG ulTdiHandle = TSInsertNode(&pEndpoint->GenHead); if (ulTdiHandle) { lStatus = TSPerformOpenEndpoint(pEndpoint, pucString); if (lStatus == STATUS_SUCCESS) { PADDRESS_OBJECT pAddressObject; lStatus = TSAllocateMemory((PVOID *)&pAddressObject, sizeof(ADDRESS_OBJECT), strFunc5, "AddressObject"); if (lStatus == STATUS_SUCCESS) { pAddressObject->GenHead.ulSignature = ulAddressObject; lStatus = TSPerformOpenAddress(pAddressObject, pucString, pTransportAddress, TRUE); if (lStatus == STATUS_SUCCESS) { pEndpoint->pAddressObject = pAddressObject; pAddressObject->pEndpoint = pEndpoint; lStatus = TSPerformAssociate(pEndpoint); if (lStatus == STATUS_SUCCESS) { pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle; return STATUS_SUCCESS; } } } // // fall thru to here on open/associate failures // } else { TSRemoveNode(ulTdiHandle); } } else { lStatus = STATUS_INSUFFICIENT_RESOURCES; } TSCloseEndpoint(pEndpoint); // also frees it! } return lStatus; } // ----------------------------------------------------------------- // // Function: TSCloseEndpoint // // Arguments: pEndpoint -- endpoint object to close // // Returns: none // // Descript: This function frees the resources for a connection object, // and calls the tdi provider to close it // // ---------------------------------------------------------------------------- VOID TSCloseEndpoint(PENDPOINT_OBJECT pEndpoint) { // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint1("\nCommand = ulCLOSEENDPOINT\n" "Endpoint = %p\n", pEndpoint); } if (pEndpoint->pAddressObject) { if (pEndpoint->fIsAssociated) { TSPerformDisassociate(pEndpoint); } TSCloseAddress(pEndpoint->pAddressObject); pEndpoint->pAddressObject = NULL; } if (pEndpoint->GenHead.pFileObject) { ObDereferenceObject(pEndpoint->GenHead.pFileObject); NTSTATUS lStatus = ZwClose(pEndpoint->GenHead.FileHandle); if (lStatus != STATUS_SUCCESS) { DebugPrint2("%s: ZwClose failed with status 0x%08x\n", strFunc6, lStatus); } } TSFreeMemory(pEndpoint); } //////////////////////////////////////////////////////////////// // Private Functions /////////////////////////////////////////////////////////////// // ------------------------------------------------------ // // Function: TSCompleteCommand // // Arguments: ptr to address object or endpoint to close for command // lstatus = status of close attempt (as TDI_STATUS) // param = 0 // // Returns: none // // Descript: This function is called to complete a CloseAddress or // a CloseEndpoint on Win98 // // ------------------------------------------------------- #pragma warning(disable: UNREFERENCED_PARAM) TDI_STATUS TSCompleteCommand(PDEVICE_OBJECT pDeviceObject, PIRP pLowerIrp, PVOID pvContext) { TDI_STATUS TdiStatus = pLowerIrp->IoStatus.Status; PGENERIC_HEADER pGenHead = (PGENERIC_HEADER)pvContext; TSSetEvent(&pGenHead->TdiEvent); pGenHead->lStatus = TdiStatus; TSFreeIrp(pLowerIrp, NULL); return TDI_MORE_PROCESSING; } #pragma warning(default: UNREFERENCED_PARAM) // ----------------------------------------------- // // Function: TSPerformOpenControl // // Arguments: pControlChannel -- used to store file information // pucString -- name of device to open // // Returns: status of operation // // Descript: Actually opens the control channel, and then sets the // appropriate fields in our structure // // ----------------------------------------------- NTSTATUS TSPerformOpenControl(PCONTROL_CHANNEL pControlChannel, PUCNTSTRING pucString) { UNICODE_STRING ustrDeviceName; // // we need a unicode string to actually do the open // NTSTATUS lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer, pucString->usLength + 2, strFuncP2, "StringBuffer"); if (lStatus == STATUS_SUCCESS) { HANDLE FileHandle; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; // // create the unicode string // ustrDeviceName.Length = pucString->usLength; ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2); RtlCopyMemory(ustrDeviceName.Buffer, pucString->wcBuffer, ustrDeviceName.Length); // // set up the object attributes needed to open this... // InitializeObjectAttributes(&ObjectAttributes, &ustrDeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); lStatus = ZwCreateFile(&FileHandle, GENERIC_READ | GENERIC_WRITE, // desired access. &ObjectAttributes, // object attributes. &IoStatusBlock, // returned status information. NULL, // Allocation size (unused). FILE_ATTRIBUTE_NORMAL, // file attributes. FILE_SHARE_WRITE, FILE_CREATE, 0, // create options. NULL, 0); // // make sure it really succeeded // if (NT_SUCCESS(lStatus)) { lStatus = IoStatusBlock.Status; } // // clean up this now (don't need it anymore) // TSFreeMemory(ustrDeviceName.Buffer); // // if it succeeded, then set up our node structure // if (NT_SUCCESS(lStatus)) { PFILE_OBJECT pFileObject; lStatus = ObReferenceObjectByHandle(FileHandle, 0, NULL, KernelMode, (PVOID *)&pFileObject, NULL); if (NT_SUCCESS(lStatus)) { pControlChannel->GenHead.FileHandle = FileHandle; pControlChannel->GenHead.pFileObject = pFileObject; pControlChannel->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject); return STATUS_SUCCESS; // only successful exit point } else { DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n", lStatus); } } // // get here if ZwCreateFile failed // else { DebugPrint3("OpenControlChannel failed for %ws with code %x iostatus %x\n", pucString->wcBuffer, lStatus, IoStatusBlock.Status); } } return lStatus; } // ----------------------------------------------- // // Function: TSPerformOpenAddress // // Arguments: pAddressObject -- used to store file information // pucString -- name of device to open // pTransportAddr -- address to open on the device // fIsConnect -- TRUE for connection, false for datagram // // Returns: status of operation // // Descript: Actually opens the address object, and then sets the // appropriate fields in our structure // // ----------------------------------------------- NTSTATUS TSPerformOpenAddress(PADDRESS_OBJECT pAddressObject, PUCNTSTRING pucString, PTRANSPORT_ADDRESS pTransportAddress, BOOLEAN fIsConnect) { // // address open uses an ea buffer that contains the transport address // ULONG ulAddressLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) + FIELD_OFFSET(TA_ADDRESS, Address) + pTransportAddress->Address[0].AddressLength; ULONG ulEaLengthNeeded = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + (TDI_TRANSPORT_ADDRESS_LENGTH + 1) + ulAddressLength; // // allocate the ea buffer first... // PFILE_FULL_EA_INFORMATION EaBuffer; NTSTATUS lStatus = TSAllocateMemory((PVOID *)&EaBuffer, ulEaLengthNeeded, strFuncP3, "EaBuffer"); if (lStatus == STATUS_SUCCESS) { UNICODE_STRING ustrDeviceName; // // setup the ea buffer // EaBuffer->NextEntryOffset = 0; EaBuffer->Flags = 0; EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; EaBuffer->EaValueLength = (USHORT)ulAddressLength; RtlCopyMemory(&EaBuffer->EaName[0], TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH + 1); RtlCopyMemory(&EaBuffer->EaName[TDI_TRANSPORT_ADDRESS_LENGTH+1], pTransportAddress, ulAddressLength); // // we need a unicode string to actually do the open // lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer, pucString->usLength + 2, strFuncP3, "StringBuffer"); if (lStatus == STATUS_SUCCESS) { IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandle; // // create the unicode string // ustrDeviceName.Length = pucString->usLength; ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2); RtlCopyMemory(ustrDeviceName.Buffer, pucString->wcBuffer, ustrDeviceName.Length); // // set up the object attributes needed to open this... // InitializeObjectAttributes(&ObjectAttributes, &ustrDeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); lStatus = ZwCreateFile(&FileHandle, GENERIC_READ | GENERIC_WRITE, // desired access. &ObjectAttributes, // object attributes. &IoStatusBlock, // returned status information. NULL, // Allocation size (unused). FILE_ATTRIBUTE_NORMAL, // file attributes. FILE_SHARE_WRITE, FILE_CREATE, 0, // create options. EaBuffer, ulEaLengthNeeded); // // make sure it really succeeded // if (NT_SUCCESS(lStatus)) { lStatus = IoStatusBlock.Status; } // // clean up what we can here... // TSFreeMemory(ustrDeviceName.Buffer); TSFreeMemory(EaBuffer); // // if it succeeded, then set up our node structure // if (NT_SUCCESS(lStatus)) { PFILE_OBJECT pFileObject; lStatus = ObReferenceObjectByHandle(FileHandle, 0, NULL, KernelMode, (PVOID *)&pFileObject, NULL); if (NT_SUCCESS(lStatus)) { pAddressObject->GenHead.FileHandle = FileHandle; pAddressObject->GenHead.pFileObject = pFileObject; pAddressObject->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject); TSAllocateSpinLock(&pAddressObject->TdiSpinLock); // // if ipv4, set up socket for strong host // if (fIsConnect && (pTransportAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP)) { TCP_REQUEST_SET_INFORMATION_EX* pInfo; CHAR achBuf[ sizeof(*pInfo) + sizeof(ULONG) ]; ULONG ulValue = 1; IO_STATUS_BLOCK iosb; pInfo = (TCP_REQUEST_SET_INFORMATION_EX* )achBuf; pInfo->ID.toi_entity.tei_entity = CL_TL_ENTITY; pInfo->ID.toi_entity.tei_instance = 0; pInfo->ID.toi_class = INFO_CLASS_PROTOCOL; pInfo->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT; pInfo->ID.toi_id = AO_OPTION_IP_UCASTIF; RtlCopyMemory(pInfo->Buffer, &ulValue, sizeof(ULONG)); pInfo->BufferSize = sizeof(ULONG); PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_TCP_WSH_SET_INFORMATION_EX, pAddressObject->GenHead.pDeviceObject, (PVOID )pInfo, sizeof(*pInfo) + sizeof(ULONG), NULL, 0, FALSE, NULL, &iosb); if (pIrp) { PIO_STACK_LOCATION pIrpSp = IoGetNextIrpStackLocation(pIrp); pIrpSp->FileObject = pFileObject; IoCallDriver(pAddressObject->GenHead.pDeviceObject, pIrp); } } return STATUS_SUCCESS; // only successful exit } else { DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n", lStatus); } ZwClose(FileHandle); } // // get here if ZwCreateFile failed // else { DebugPrint3("OpenAddressObject failed for %ws with code %x iostatus %x\n", pucString->wcBuffer, lStatus, IoStatusBlock.Status); } } // // get here if cannot allocate unicode string buffer // else { TSFreeMemory(EaBuffer); } } return lStatus; } // ----------------------------------------------- // // Function: TSPerformOpenEndpoint // // Arguments: pEndpoint -- used to store file information // pucString -- name of device to open // // Returns: status of operation // // Descript: Actually opens the endpoint object, and then sets the // appropriate fields in our structure // // ----------------------------------------------- NTSTATUS TSPerformOpenEndpoint(PENDPOINT_OBJECT pEndpoint, PUCNTSTRING pucString) { // // NOTE: CONNECTION_CONTEXT == PVOID // ULONG ulEaLengthNeeded = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + (TDI_CONNECTION_CONTEXT_LENGTH + 1) + sizeof(CONNECTION_CONTEXT); // // allocate the ea buffer... // PFILE_FULL_EA_INFORMATION EaBuffer; NTSTATUS lStatus = TSAllocateMemory((PVOID *)&EaBuffer, ulEaLengthNeeded, strFunc5, "EaBuffer"); if (lStatus == STATUS_SUCCESS) { UNICODE_STRING ustrDeviceName; // // setup the ea buffer // EaBuffer->NextEntryOffset = 0; EaBuffer->Flags = 0; EaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH; EaBuffer->EaValueLength = sizeof(CONNECTION_CONTEXT); RtlCopyMemory(&EaBuffer->EaName[0], TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH + 1); RtlCopyMemory(&EaBuffer->EaName[TDI_CONNECTION_CONTEXT_LENGTH+1], &pEndpoint, sizeof(CONNECTION_CONTEXT)); // // we need a unicode string to actually do the open // lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer, pucString->usLength + 2, strFunc5, "StringBuffer"); if (lStatus == STATUS_SUCCESS) { IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandle; // // create the unicode string // ustrDeviceName.Length = pucString->usLength; ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2); RtlCopyMemory(ustrDeviceName.Buffer, pucString->wcBuffer, ustrDeviceName.Length); // // set up the object attributes needed to open this... // InitializeObjectAttributes(&ObjectAttributes, &ustrDeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); lStatus = ZwCreateFile(&FileHandle, GENERIC_READ | GENERIC_WRITE, // desired access. &ObjectAttributes, // object attributes. &IoStatusBlock, // returned status information. NULL, // Allocation size (unused). FILE_ATTRIBUTE_NORMAL, // file attributes. FILE_SHARE_WRITE, FILE_CREATE, 0, // create options. EaBuffer, ulEaLengthNeeded); // // make sure it really succeeded // if (NT_SUCCESS(lStatus)) { lStatus = IoStatusBlock.Status; } // // free up what we can here... // TSFreeMemory(ustrDeviceName.Buffer); TSFreeMemory(EaBuffer); // // if it succeeded, then set up our node structure // if (NT_SUCCESS(lStatus)) { PFILE_OBJECT pFileObject; lStatus = ObReferenceObjectByHandle(FileHandle, 0, NULL, KernelMode, (PVOID *)&pFileObject, NULL); if (NT_SUCCESS(lStatus)) { pEndpoint->GenHead.FileHandle = FileHandle; pEndpoint->GenHead.pFileObject = pFileObject; pEndpoint->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject); return STATUS_SUCCESS; // only successful exit } else { DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n", lStatus); } ZwClose(FileHandle); } // // get here if ZwCreateFile failed // else { DebugPrint3("OpenEndpointObject failed for %ws with code %x iostatus %x\n", pucString->wcBuffer, lStatus, IoStatusBlock.Status); } } // // get here if cannot allocate unicode string buffer // else { TSFreeMemory(EaBuffer); } } return lStatus; } // ----------------------------------------------------------------- // // Function: TSPerformAssociate // // Arguments: pEndpoint -- connection endpoint structure // // Returns: NTSTATUS (normally success) // // Descript: This function attempts to associate a transport address // object with an endpoint object // // ----------------------------------------------------------------------------- NTSTATUS TSPerformAssociate(PENDPOINT_OBJECT pEndpoint) { TSInitializeEvent(&pEndpoint->GenHead.TdiEvent); PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject, NULL); if (!pLowerIrp) { return STATUS_INSUFFICIENT_RESOURCES; } // // set up everything and call the tdi provider // #pragma warning(disable: CONSTANT_CONDITIONAL) TdiBuildAssociateAddress(pLowerIrp, pEndpoint->GenHead.pDeviceObject, pEndpoint->GenHead.pFileObject, TSCompleteCommand, pEndpoint, pEndpoint->pAddressObject->GenHead.FileHandle); #pragma warning(default: CONSTANT_CONDITIONAL) // // (should ALWAYS be pending) // NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject, pLowerIrp); if (lStatus == STATUS_PENDING) { TSWaitEvent(&pEndpoint->GenHead.TdiEvent); lStatus = pEndpoint->GenHead.lStatus; } if (lStatus == STATUS_SUCCESS) { pEndpoint->fIsAssociated = TRUE; } return lStatus; } // ----------------------------------------------------------------- // // Function: TSPerformDisassociateAddress // // Arguments: pEndpoint -- connection endpoint structure // // Returns: NTSTATUS (normally pending) // // Descript: This function attempts to disassociate a transport address // object from its associated endpoint object // // ---------------------------------------------------------------------------- VOID TSPerformDisassociate(PENDPOINT_OBJECT pEndpoint) { TSInitializeEvent(&pEndpoint->GenHead.TdiEvent); PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject, NULL); if (!pLowerIrp) { return; } // // set up everything and call the tdi provider // #pragma warning(disable: CONSTANT_CONDITIONAL) TdiBuildDisassociateAddress(pLowerIrp, pEndpoint->GenHead.pDeviceObject, pEndpoint->GenHead.pFileObject, TSCompleteCommand, pEndpoint); #pragma warning(default: CONSTANT_CONDITIONAL) NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject, pLowerIrp); if (lStatus == STATUS_PENDING) { TSWaitEvent(&pEndpoint->GenHead.TdiEvent); } } //////////////////////////////////////////////////////////////////////////////// // end of file open.cpp ////////////////////////////////////////////////////////////////////////////////