/*++ Copyright (c) 1995 Microsoft Corporation Module Name: autodial.c Abstract: NT specific routines for interfacing with the RAS AutoDial driver (rasacd.sys). Author: Anthony Discolo (adiscolo) Aug 30, 1995 Revision History: Who When What -------- -------- ---------------------------------------------- adiscolo 08-30-95 created Notes: --*/ #include "precomp.h" #pragma hdrstop #ifdef RASAUTODIAL #include #include // // Global variables // BOOLEAN fAcdLoadedG; ACD_DRIVER AcdDriverG; ULONG ulDriverIdG = 'Nbi '; VOID NbiRetryTdiConnect( IN BOOLEAN fSuccess, IN PVOID *pArgs ) /*++ Routine Description: This routine is called indirectly by the automatic connection driver to continue the connection process after an automatic connection has been made. Arguments: fSuccess - TRUE if the connection attempt was successful. pArgs - a pointer to the argument vector Return Value: None. --*/ { NTSTATUS status; PDEVICE pDevice = pArgs[0]; PCONNECTION pConnection = pArgs[1]; PREQUEST pRequest = pArgs[2]; CTELockHandle ConnectionLH, DeviceLH; CTELockHandle CancelLH; BOOLEAN bLockFreed = FALSE; // // Check that the connection is valid. This references // the connection. // #if notdef // DBG DbgPrint("NbiRetryTdiConnect: fSuccess=%d, pConnection=0x%x\n", fSuccess, pConnection); #endif status = NbiVerifyConnection(pConnection); if (!NT_SUCCESS(status)) { DbgPrint( "NbiRetryTdiConnect: NbiVerifyConnection failed on connection 0x%x (status=0x%x)\n", pConnection, status); return; } NB_GET_CANCEL_LOCK( &CancelLH ); NB_GET_LOCK (&pConnection->Lock, &ConnectionLH); NB_GET_LOCK (&pDevice->Lock, &DeviceLH); #if notdef // DBG DbgPrint( "NbiRetryTdiConnect: AddressFile=0x%x, DisassociatePending=0x%x, ClosePending=0x%x\n", pConnection->AddressFile, pConnection->DisassociatePending, pConnection->ClosePending); #endif if ((pConnection->AddressFile != NULL) && (pConnection->AddressFile != (PVOID)-1) && (pConnection->DisassociatePending == NULL) && (pConnection->ClosePending == NULL)) { NbiReferenceConnectionLock(pConnection, CREF_CONNECT); // // Clear the AUTOCONNECTING flag since we // done with the automatic connection attempt. // Set the AUTOCONNECTED flag to prevent us // from attempting an automatic connection // for this connection again. // pConnection->Flags &= ~CONNECTION_FLAGS_AUTOCONNECTING; pConnection->Flags |= CONNECTION_FLAGS_AUTOCONNECTED; pConnection->State = CONNECTION_STATE_CONNECTING; pConnection->Retries = pDevice->ConnectionCount; status = NbiTdiConnectFindName( pDevice, pRequest, pConnection, CancelLH, ConnectionLH, DeviceLH, &bLockFreed); } else { DbgPrint("NbiRetryTdiConnect: Connect on invalid connection 0x%x\n", pConnection); pConnection->SubState = CONNECTION_SUBSTATE_C_DISCONN; NB_FREE_LOCK (&pDevice->Lock, DeviceLH); status = STATUS_INVALID_CONNECTION; } if (!bLockFreed) { NB_FREE_LOCK (&pConnection->Lock, ConnectionLH); NB_FREE_CANCEL_LOCK(CancelLH); } // // Complete the irp if necessary. // if (status != STATUS_PENDING) { REQUEST_INFORMATION(pRequest) = 0; REQUEST_STATUS(pRequest) = status; NbiCompleteRequest(pRequest); NbiFreeRequest(pDevice, pRequest); } NbiDereferenceConnection(pConnection, CREF_VERIFY); } /* NbiRetryTdiConnect */ BOOLEAN NbiCancelAutoDialRequest( IN PVOID pArg, IN ULONG ulFlags, IN ACD_CONNECT_CALLBACK pProc, IN USHORT nArgs, IN PVOID *pArgs ) { #if notdef // DBG DbgPrint("NbiCancelAutodialRequest: pArg=0x%x\n", pArg); #endif if (nArgs != 2) return FALSE; return (pArgs[1] == pArg); } // NbiCancelAutoDialRequest BOOLEAN NbiCancelTdiConnect( IN PDEVICE pDevice, IN PREQUEST pRequest, IN PCONNECTION pConnection ) /*++ DESCRIPTION This routine is called by the I/O system to cancel a connection when we are attempting to restore an automatic connection. ARGUMENTS pDevice: a pointer to the device object for this driver pRequest: a pointer to the irp to be cancelled pConnection: a pointer to the connnection to be cancelled RETURN VALUE TRUE if the request was canceled; FALSE otherwise. --*/ { ACD_ADDR addr; // // Get the address of the connection. // addr.fType = ACD_ADDR_NB; RtlCopyMemory(&addr.cNetbios, pConnection->RemoteName, 16); #ifdef notdef // DBG DbgPrint( "NbiCancelTdiConnect: pIrp=0x%x, RemoteName=%-15.15s, pConnection=0x%x\n", pRequest, addr.cNetbios, pConnection); #endif // // Cancel the autodial request. // return (*AcdDriverG.lpfnCancelConnection)( ulDriverIdG, &addr, NbiCancelAutoDialRequest, pConnection); } // NbiCancelTdiConnect BOOLEAN NbiAttemptAutoDial( IN PDEVICE pDevice, IN PCONNECTION pConnection, IN ULONG ulFlags, IN ACD_CONNECT_CALLBACK pProc, IN PREQUEST pRequest ) /*++ Routine Description: Call the automatic connection driver to attempt an automatic connection. Arguments: pDevice - a pointer to the DEVICE structure for this connection pConnection - a pointer to the CONNECTION block for this connection ulFlags - connection flags to pass to the automatic connection driver pProc - a callback procedure when the automatic connection completes pRequest - a pointer to the request irp Return Value: TRUE if the automatic connection was started successfully, FALSE otherwise. --*/ { ACD_ADDR addr; PVOID pArgs[3]; BOOLEAN bSuccess; // // If we've already attempted an automatic connection // on this connection, don't try it again. // if (pConnection->Flags & CONNECTION_FLAGS_AUTOCONNECTED) return FALSE; // // Get the address of the connection. // addr.fType = ACD_ADDR_NB; RtlCopyMemory(&addr.cNetbios, pConnection->RemoteName, 16); #ifdef notdef // DBG DbgPrint("NbiAttemptAutoDial: szAddr=%15.15s\n", addr.cNetbios); #endif // // Attempt to start the connection. // NbiRetryTdiConnect() will be called // when the connection process has completed. // pArgs[0] = pDevice; pArgs[1] = pConnection; pArgs[2] = pRequest; bSuccess = (*AcdDriverG.lpfnStartConnection)( ulDriverIdG, &addr, ulFlags, pProc, 3, pArgs); if (bSuccess) { // // Set the AUTOCONNECTING flag so we know // to also cancel the connection in the // automatic connection driver if this // request gets canceled. // pConnection->Flags |= CONNECTION_FLAGS_AUTOCONNECTING; } } // NbiAttemptAutoDial VOID NbiNoteNewConnection( IN PCONNECTION pConnection ) { NTSTATUS status; ACD_ADDR addr; ACD_ADAPTER adapter; ULONG i; TDI_ADDRESS_IPX tdiIpxAddress; addr.fType = ACD_ADDR_NB; RtlCopyMemory(&addr.cNetbios, pConnection->RemoteName, 16); // // Determine the mac address of the adapter // over which the connection has been made. // status = (pConnection->Device->Bind.QueryHandler)( IPX_QUERY_IPX_ADDRESS, #if defined(_PNP_POWER) &pConnection->LocalTarget.NicHandle, #else pConnection->LocalTarget.NicId, #endif _PNP_POWER &tdiIpxAddress, sizeof(TDI_ADDRESS_IPX), NULL); if (status != STATUS_SUCCESS) { #if notdef // DBG DbgPrint("NbiNoteNewConnection: QueryHandler(IPX_QUERY_IPX_ADDRESS) failed (status=0x%x)\n", status); return; #endif } // // Copy the source mac address to identify // the adapter. // adapter.fType = ACD_ADAPTER_MAC; for (i = 0; i < 6; i++) adapter.cMac[i] = tdiIpxAddress.NodeAddress[i]; #if notdef // DBG DbgPrint( "NbiNoteNewConnection: address=%-15.15s, remote mac=%02x:%02x:%02x:%02x:%02x:%02x\n", addr.cNetbios, adapter.cMac[0], adapter.cMac[1], adapter.cMac[2], adapter.cMac[3], adapter.cMac[4], adapter.cMac[5]); #endif // // Simply notify the automatic connection driver // that a successful connection has been made. // (*AcdDriverG.lpfnNewConnection)( &addr, &adapter); } // NbiNoteNewConnection VOID NbiAcdBind() { NTSTATUS status; UNICODE_STRING nameString; IO_STATUS_BLOCK ioStatusBlock; PIRP pIrp; PFILE_OBJECT pAcdFileObject; PDEVICE_OBJECT pAcdDeviceObject; PACD_DRIVER pDriver = &AcdDriverG; // // Initialize the name of the automatic // connection device. // RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME); // // Get the file and device objects for the // device. // status = IoGetDeviceObjectPointer( &nameString, SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, &pAcdFileObject, &pAcdDeviceObject); if (status != STATUS_SUCCESS) return; // // Reference the device object. // ObReferenceObject(pAcdDeviceObject); // // Remove the reference IoGetDeviceObjectPointer() // put on the file object. // ObDereferenceObject(pAcdFileObject); // // Initialize our part of the ACD_DRIVER // structure. // KeInitializeSpinLock(&AcdDriverG.SpinLock); AcdDriverG.ulDriverId = ulDriverIdG; AcdDriverG.fEnabled = FALSE; // // Build a request to get the automatic // connection driver entry points. // pIrp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_ACD_BIND, pAcdDeviceObject, (PVOID)&pDriver, sizeof (pDriver), NULL, 0, TRUE, NULL, &ioStatusBlock); if (pIrp == NULL) { ObDereferenceObject(pAcdDeviceObject); return; } // // Submit the request to the // automatic connection driver. // status = IoCallDriver(pAcdDeviceObject, pIrp); fAcdLoadedG = (status == STATUS_SUCCESS); // // Close the device. // ObDereferenceObject(pAcdDeviceObject); } // NbiAcdBind VOID NbiAcdUnbind() { NTSTATUS status; UNICODE_STRING nameString; IO_STATUS_BLOCK ioStatusBlock; PIRP pIrp; PFILE_OBJECT pAcdFileObject; PDEVICE_OBJECT pAcdDeviceObject; PACD_DRIVER pDriver = &AcdDriverG; // // Don't bother to unbind if we // didn't successfully bind in the // first place. // if (!fAcdLoadedG) return; // // Initialize the name of the automatic // connection device. // RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME); // // Get the file and device objects for the // device. // status = IoGetDeviceObjectPointer( &nameString, SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, &pAcdFileObject, &pAcdDeviceObject); if (status != STATUS_SUCCESS) return; // // Reference the device object. // ObReferenceObject(pAcdDeviceObject); // // Remove the reference IoGetDeviceObjectPointer() // put on the file object. // ObDereferenceObject(pAcdFileObject); // // Build a request to unbind from // the automatic connection driver. // pIrp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_ACD_UNBIND, pAcdDeviceObject, (PVOID)&pDriver, sizeof (pDriver), NULL, 0, TRUE, NULL, &ioStatusBlock); if (pIrp == NULL) { ObDereferenceObject(pAcdDeviceObject); return; } // // Submit the request to the // automatic connection driver. // status = IoCallDriver(pAcdDeviceObject, pIrp); // // Close the device. // ObDereferenceObject(pAcdDeviceObject); } // NbiAcdUnbind #endif // RASAUTODIAL