//++ // // Copyright (C) Microsoft Corporation, 1987 - 1999 // // Module Name: // // ipxtest.c // // Abstract: // // Queries into network drivers // // Author: // // Anilth - 4-20-1998 // // Environment: // // User mode only. // Contains NT-specific code. // // Revision History: // //-- #include "precomp.h" #include "ipxtest.h" static HANDLE s_isnipxfd = INVALID_HANDLE; static wchar_t isnipxname[] = L"\\Device\\NwlnkIpx"; void IPXprint_config(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults ); int do_isnipxioctl( IN HANDLE fd, IN int cmd, OUT char *datap, IN int dlen ); HRESULT LoadIpxInterfaceInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults); void get_emsg(NETDIAG_PARAMS *pParams, int rc); HRESULT InitIpxConfig(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults) { UNICODE_STRING FileString; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; HRESULT hr = hrOK; PrintStatusMessage(pParams,0, IDS_IPX_STATUS_MSG); /** Open the isnipx driver **/ RtlInitUnicodeString (&FileString, isnipxname); InitializeObjectAttributes( &ObjectAttributes, &FileString, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile( &pResults->Ipx.hIsnIpxFd, SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); pResults->Ipx.fInstalled = TRUE; pResults->Ipx.fEnabled = TRUE; if (!NT_SUCCESS(Status)) { pResults->Ipx.hIsnIpxFd = INVALID_HANDLE; // IDS_IPX_15603 "Opening \\Device\\NwlnkIpx failed\n" PrintDebug(pParams, 4, IDS_IPX_15603); pResults->Ipx.fInstalled = FALSE; pResults->Ipx.fEnabled = FALSE; // IPX is not installed, do not return the error code // but return S_FALSE. return S_FALSE; } // Fill in the IPX adapter interface data hr = LoadIpxInterfaceInfo(pParams, pResults); return hr; } IPX_TEST_FRAME* PutIpxFrame( // returns 0-3 ULONG uFrameType, // returns virtual net if NicId = 0 ULONG uNetworkNumber, // adapter's MAC address const UCHAR* pNode, LIST_ENTRY* pListHead // if its NULL, then the new created will be head ) { IPX_TEST_FRAME* pFrame = NULL; if(pListHead == NULL) return NULL; pFrame = (IPX_TEST_FRAME*)malloc(sizeof(IPX_TEST_FRAME)); if(pFrame == NULL) return NULL; if( pListHead->Flink == NULL && pListHead->Blink == NULL) // the head is not initilized InitializeListHead(pListHead); pFrame->uFrameType = uFrameType; pFrame->uNetworkNumber = uNetworkNumber; memcpy(&pFrame->Node[0], pNode, sizeof(pFrame->Node)); InsertTailList(pListHead, &(pFrame->list_entry)); return pFrame; } HRESULT LoadIpxInterfaceInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults) { int rc; USHORT nicid, nicidcount; ISN_ACTION_GET_DETAILS getdetails; HANDLE hMpr = NULL; DWORD dwErr; PVOID pv; HRESULT hr = hrOK; int i, iIpx; INTERFACE_RESULT * pIfResults; LPTSTR pszAdapterName = NULL; unsigned char node[6] = {0, 0,0,0,0,1}; // Initialize the map from guid to interface name CheckErr( MprConfigServerConnect(NULL, &hMpr) ); assert(hMpr != INVALID_HANDLE); /** First query nicid 0 **/ getdetails.NicId = 0; rc = do_isnipxioctl(pResults->Ipx.hIsnIpxFd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails)); if (rc) { // IDS_IPX_15604 "Error querying config nwlnkipx :" PrintDebug(pParams, 0, IDS_IPX_15604); if (pParams->fDebugVerbose) { get_emsg(pParams, rc); } goto Error; } // // The NicId 0 query returns the total number. // nicidcount = getdetails.NicId; // We should have an open spot for the IPX internal interface // ---------------------------------------------------------------- assert(pResults->cNumInterfacesAllocated > pResults->cNumInterfaces); // Set the first IPX interface as the IPX internal iIpx = pResults->cNumInterfaces; // Add the internal interface pIfResults = pResults->pArrayInterface + iIpx; pIfResults->fActive = TRUE; pIfResults->Ipx.fActive = TRUE; pIfResults->pszName = StrDup(_T("Internal")); pIfResults->pszFriendlyName = LoadAndAllocString(IDS_IPX_INTERNAL); pIfResults->Ipx.uNicId = 0; pIfResults->Ipx.fBindingSet = 0; pIfResults->Ipx.uType = 0; // multiple frame types PutIpxFrame(0, REORDER_ULONG(getdetails.NetworkNumber), node, &(pIfResults->Ipx.list_entry_Frames)); iIpx++; // move on to the next new interface structure pResults->cNumInterfaces++; InitializeListHead(&pResults->Dns.lmsgOutput); for (nicid = 1; nicid <= nicidcount; nicid++) { // get the next structure getdetails.NicId = nicid; rc = do_isnipxioctl(pResults->Ipx.hIsnIpxFd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails) ); if (rc) { continue; } // convert the adapter name into ASCII pszAdapterName = StrDupTFromW(getdetails.AdapterName); // see if this interface is already in the list pIfResults = NULL; for ( i=0; icNumInterfaces; i++) { if (lstrcmpi(pResults->pArrayInterface[i].pszName, pszAdapterName) == 0) { pIfResults = pResults->pArrayInterface + i; break; } } // if we didn't find a match, use one of the newly allocated // interfaces if (pIfResults == NULL) { // We need a new interface result structure, grab one // (if it is free), else allocate more. if (pResults->cNumInterfaces >= pResults->cNumInterfacesAllocated) { // Need to do a realloc to get more memory pv = Realloc(pResults->pArrayInterface, sizeof(INTERFACE_RESULT)*(pResults->cNumInterfacesAllocated+8)); if (pv == NULL) CheckHr( E_OUTOFMEMORY ); pResults->pArrayInterface = pv; // Zero out the new section of memory ZeroMemory(pResults->pArrayInterface + pResults->cNumInterfacesAllocated, sizeof(INTERFACE_RESULT)*8); pResults->cNumInterfacesAllocated += 8; } pIfResults = pResults->pArrayInterface + iIpx; iIpx++; pResults->cNumInterfaces++; pIfResults->pszName = _tcsdup(pszAdapterName); } free(pszAdapterName); pszAdapterName = NULL; // Enable IPX on this interface pIfResults->fActive = TRUE; pIfResults->Ipx.fActive = TRUE; pIfResults->Ipx.uNicId = nicid; // support multiple frame types PutIpxFrame(getdetails.FrameType, REORDER_ULONG(getdetails.NetworkNumber), &(getdetails.Node[0]), &(pIfResults->Ipx.list_entry_Frames)); // Translate the adapter name (if needed) if (!pIfResults->pszFriendlyName) { if (getdetails.Type == IPX_TYPE_LAN) { WCHAR swzName[512]; PWCHAR pszGuid = &(getdetails.AdapterName[0]); dwErr = MprConfigGetFriendlyName(hMpr, pszGuid, swzName, sizeof(swzName)); if (dwErr == NO_ERROR) pIfResults->pszFriendlyName = StrDupTFromW(swzName); else pIfResults->pszFriendlyName = StrDupTFromW(getdetails.AdapterName); } else pIfResults->pszFriendlyName = StrDupTFromW(getdetails.AdapterName); } pIfResults->Ipx.fBindingSet = getdetails.BindingSet; } Error: /** Close up and exit **/ // Cleanup interface map if (hMpr) MprConfigServerDisconnect(hMpr); return hr; } HRESULT IpxTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults) { return hrOK; } int do_isnipxioctl( IN HANDLE fd, IN int cmd, OUT char *datap, IN int dlen) { NTSTATUS Status; UCHAR buffer[sizeof(NWLINK_ACTION) + sizeof(ISN_ACTION_GET_DETAILS) - 1]; PNWLINK_ACTION action; IO_STATUS_BLOCK IoStatusBlock; int rc; /** Fill out the structure **/ action = (PNWLINK_ACTION)buffer; action->Header.TransportId = ISN_ACTION_TRANSPORT_ID; action->OptionType = NWLINK_OPTION_CONTROL; action->BufferLength = sizeof(ULONG) + dlen; action->Option = cmd; RtlMoveMemory(action->Data, datap, dlen); /** Issue the ioctl **/ Status = NtDeviceIoControlFile( fd, NULL, NULL, NULL, &IoStatusBlock, IOCTL_TDI_ACTION, NULL, 0, action, FIELD_OFFSET(NWLINK_ACTION,Data) + dlen); if (Status != STATUS_SUCCESS) { if (Status == STATUS_INVALID_PARAMETER) { rc = ERANGE; } else { rc = EINVAL; } } else { if (dlen > 0) { RtlMoveMemory (datap, action->Data, dlen); } rc = 0; } return rc; } void get_emsg(NETDIAG_PARAMS *pParams, int rc) { /** We have 3 defined error codes that can come back. 1 - EINVAL means that we sent down parameters wrong (SHOULD NEVER HAPPEN) 2 - ERANGE means that the board number is invalid (CAN HAPPEN IF USER ENTERS BAD BOARD) 3 - ENOENT means that on remove - the address given is not in the source routing table. **/ switch (rc) { case EINVAL: // IDS_IPX_15605 "we sent down parameters wrong\n" PrintMessage(pParams, IDS_IPX_15605); break; case ERANGE: // IDS_IPX_15606 "board number is invalid\n" PrintMessage(pParams, IDS_IPX_15606); break; case ENOENT: // IDS_IPX_15607 "remove - the address given is not in the source routing table\n" PrintMessage(pParams, IDS_IPX_15607); break; default: // IDS_IPX_15608 "Unknown Error\n" PrintMessage(pParams, IDS_IPX_15608); break; } return; } /*!-------------------------------------------------------------------------- IpxGlobalPrint - Author: KennT ---------------------------------------------------------------------------*/ void IpxGlobalPrint( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults) { if (!pResults->Ipx.fInstalled) return; #if 0 if (pParams->fVerbose) { PrintNewLine(pParams, 2); PrintTestTitleResult(pParams, IDS_IPX_LONG, IDS_IPX_SHORT, TRUE, pResults->Ipx.hr, 0); } #endif } /*!-------------------------------------------------------------------------- IpxPerInterfacePrint - Author: KennT ---------------------------------------------------------------------------*/ void IpxPerInterfacePrint( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults, INTERFACE_RESULT *pInterfaceResults) { int ids; LPTSTR pszFrameType = NULL; LIST_ENTRY* pEntry = NULL; IPX_TEST_FRAME* pFrameEntry = NULL; // no per-interface results if (!pResults->Ipx.fInstalled) { if (pParams->fReallyVerbose) // IDS_IPX_15609 " IPX test : IPX is not installed on this machine.\n" PrintMessage(pParams, IDS_IPX_15609); return; } if (!pInterfaceResults->Ipx.fActive) return; // IDS_IPX_15610 "\n Ipx configration\n" PrintMessage(pParams, IDS_IPX_15610); // support multiple frame types // loop all the frame in the list_entry pEntry = pInterfaceResults->Ipx.list_entry_Frames.Flink; for ( pEntry = pInterfaceResults->Ipx.list_entry_Frames.Flink ; pEntry != &pInterfaceResults->Ipx.list_entry_Frames ; pEntry = pEntry->Flink ) { pFrameEntry = CONTAINING_RECORD(pEntry, IPX_TEST_FRAME, list_entry); ASSERT(pFrameEntry); // network number // IDS_IPX_15611 " Network Number : %.8x\n" PrintMessage(pParams, IDS_IPX_15611, pFrameEntry->uNetworkNumber); // node // IDS_IPX_15612 " Node : %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n" PrintMessage(pParams, IDS_IPX_15612, pFrameEntry->Node[0], pFrameEntry->Node[1], pFrameEntry->Node[2], pFrameEntry->Node[3], pFrameEntry->Node[4], pFrameEntry->Node[5]); // frame type switch (pFrameEntry->uFrameType) { case 0 : ids = IDS_IPX_ETHERNET_II; break; case 1 : ids = IDS_IPX_802_3; break; case 2 : ids = IDS_IPX_802_2; break; case 3 : ids = IDS_IPX_SNAP; break; case 4 : ids = IDS_IPX_ARCNET; break; default: ids = IDS_IPX_UNKNOWN; break; } pszFrameType = LoadAndAllocString(ids); // IDS_IPX_15613 " Frame type : %s\n" PrintMessage(pParams, IDS_IPX_15613, pszFrameType); Free(pszFrameType); PrintNewLine(pParams, 1); } // type PrintNewLine(pParams, 1); } /*!-------------------------------------------------------------------------- IpxCleanup - Author: KennT ---------------------------------------------------------------------------*/ void IpxCleanup( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults) { int i; LIST_ENTRY* pEntry = NULL; IPX_TEST_FRAME* pFrameEntry = NULL; INTERFACE_RESULT* pIfResults = NULL; if (pResults->Ipx.hIsnIpxFd != INVALID_HANDLE) NtClose(pResults->Ipx.hIsnIpxFd); pResults->Ipx.hIsnIpxFd = INVALID_HANDLE; // per interface stuff -- loop through for ( i = 0; i < pResults->cNumInterfacesAllocated; i++) { pIfResults = pResults->pArrayInterface + i; if(pIfResults->Ipx.list_entry_Frames.Flink) // there is data need to be cleaned up { while (!IsListEmpty(&(pIfResults->Ipx.list_entry_Frames))) { pEntry = RemoveHeadList(&(pIfResults->Ipx.list_entry_Frames)); // find data pointer pFrameEntry = CONTAINING_RECORD(pEntry, IPX_TEST_FRAME, list_entry); free(pFrameEntry); } } } }