/*********************************************************************** * NtQuerySystemTime (NTDLL.@) * ZwQuerySystemTime (NTDLL.@) */ NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER time ) { LONGLONG secs; struct timeval now; gettimeofday( &now, 0 ); secs = now.tv_sec + SECS_1601_TO_1970; time->QuadPart = RtlExtendedIntegerMultiply( secs, 10000000 ) + now.tv_usec * 10; return STATUS_SUCCESS; }
//* TdiQueryInformation - Query Information handler. // // The TDI QueryInformation routine. Called when the client wants to // query information on a connection, the provider as a whole, or to // get statistics. // // Input: Request - The request structure for this command. // QueryType - The type of query to be performed. // Buffer - Buffer to place data into. // BufferSize - Pointer to size in bytes of buffer. On return, // filled in with bytes copied. // IsConn - Valid only for TDI_QUERY_ADDRESS_INFO. TRUE // if we are querying the address info on // a connection. // // Returns: Status of attempt to query information. // TDI_STATUS TdiQueryInformation(PTDI_REQUEST Request, uint QueryType, PNDIS_BUFFER Buffer, uint *BufferSize, uint IsConn) { union { TDI_CONNECTION_INFO ConnInfo; TDI_ADDRESS_INFO AddrInfo; TDI_PROVIDER_INFO ProviderInfo; TDI_PROVIDER_STATISTICS ProviderStats; } InfoBuf; uint InfoSize; CTELockHandle ConnTableHandle, TCBHandle, AddrHandle, AOHandle; #ifndef UDP_ONLY TCPConn *Conn; TCB *InfoTCB; #endif AddrObj *InfoAO; void *InfoPtr = NULL; uint Offset; uint Size; uint BytesCopied; switch (QueryType) { case TDI_QUERY_BROADCAST_ADDRESS: return TDI_INVALID_QUERY; break; case TDI_QUERY_PROVIDER_INFO: InfoBuf.ProviderInfo.Version = 0x100; #ifndef UDP_ONLY InfoBuf.ProviderInfo.MaxSendSize = 0xffffffff; #else InfoBuf.ProviderInfo.MaxSendSize = 0; #endif InfoBuf.ProviderInfo.MaxConnectionUserData = 0; InfoBuf.ProviderInfo.MaxDatagramSize = 0xffff - sizeof(UDPHeader); InfoBuf.ProviderInfo.ServiceFlags = MY_SERVICE_FLAGS; InfoBuf.ProviderInfo.MinimumLookaheadData = 1; InfoBuf.ProviderInfo.MaximumLookaheadData = 0xffff; InfoBuf.ProviderInfo.NumberOfResources = 0; InfoBuf.ProviderInfo.StartTime.LowPart = StartTime; InfoBuf.ProviderInfo.StartTime.HighPart = 0; InfoSize = sizeof(TDI_PROVIDER_INFO); InfoPtr = &InfoBuf.ProviderInfo; break; case TDI_QUERY_ADDRESS_INFO: InfoSize = sizeof(TDI_ADDRESS_INFO) - sizeof(TRANSPORT_ADDRESS) + TCP_TA_SIZE; CTEMemSet(&InfoBuf.AddrInfo, 0, TCP_TA_SIZE); InfoBuf.AddrInfo.ActivityCount = 1; // Since noone knows what // this means, we'll set // it to one. if (IsConn) { #ifdef UDP_ONLY return TDI_INVALID_QUERY; #else CTEGetLock(&AddrObjTableLock, &AddrHandle); CTEGetLock(&ConnTableLock, &ConnTableHandle); Conn = GetConnFromConnID((uint)Request->Handle.ConnectionContext); if (Conn != NULL) { CTEStructAssert(Conn, tc); InfoTCB = Conn->tc_tcb; // If we have a TCB we'll // return information about that TCB. Otherwise we'll return // info about the address object. if (InfoTCB != NULL) { CTEStructAssert(InfoTCB, tcb); CTEGetLock(&InfoTCB->tcb_lock, &TCBHandle); CTEFreeLock(&ConnTableLock, TCBHandle); CTEFreeLock(&AddrObjTableLock, ConnTableHandle); BuildTDIAddress((uchar *)&InfoBuf.AddrInfo.Address, InfoTCB->tcb_saddr, InfoTCB->tcb_sport); CTEFreeLock(&InfoTCB->tcb_lock, AddrHandle); InfoPtr = &InfoBuf.AddrInfo; break; } else { // No TCB, return info on the AddrObj. InfoAO = Conn->tc_ao; if (InfoAO != NULL) { // We have an AddrObj. CTEStructAssert(InfoAO, ao); CTEGetLock(&InfoAO->ao_lock, &AOHandle); BuildTDIAddress((uchar *)&InfoBuf.AddrInfo.Address, InfoAO->ao_addr, InfoAO->ao_port); CTEFreeLock(&InfoAO->ao_lock, AOHandle); CTEFreeLock(&ConnTableLock, ConnTableHandle); CTEFreeLock(&AddrObjTableLock, AddrHandle); InfoPtr = &InfoBuf.AddrInfo; break; } } } // Fall through to here when we can't find the connection, or // the connection isn't associated. CTEFreeLock(&ConnTableLock, ConnTableHandle); CTEFreeLock(&AddrObjTableLock, AddrHandle); return TDI_INVALID_CONNECTION; break; #endif } else { // Asking for information on an addr. object. #ifdef VXD InfoAO = GetIndexedAO((uint)Request->Handle.AddressHandle); if (InfoAO == NULL) return TDI_ADDR_INVALID; #else InfoAO = Request->Handle.AddressHandle; #endif CTEStructAssert(InfoAO, ao); CTEGetLock(&InfoAO->ao_lock, &AOHandle); if (!AO_VALID(InfoAO)) { CTEFreeLock(&InfoAO->ao_lock, AOHandle); return TDI_ADDR_INVALID; } BuildTDIAddress((uchar *)&InfoBuf.AddrInfo.Address, InfoAO->ao_addr, InfoAO->ao_port); CTEFreeLock(&InfoAO->ao_lock, AOHandle); InfoPtr = &InfoBuf.AddrInfo; break; } break; case TDI_QUERY_CONNECTION_INFO: #ifndef UDP_ONLY InfoSize = sizeof(TDI_CONNECTION_INFO); CTEGetLock(&ConnTableLock, &ConnTableHandle); Conn = GetConnFromConnID((uint)Request->Handle.ConnectionContext); if (Conn != NULL) { CTEStructAssert(Conn, tc); InfoTCB = Conn->tc_tcb; // If we have a TCB we'll return the information. Otherwise // we'll error out. if (InfoTCB != NULL) { ulong TotalTime; ulong BPS, PathBPS; IP_STATUS IPStatus; CTEULargeInt TempULargeInt; CTEStructAssert(InfoTCB, tcb); CTEGetLock(&InfoTCB->tcb_lock, &TCBHandle); CTEFreeLock(&ConnTableLock, TCBHandle); CTEMemSet(&InfoBuf.ConnInfo, 0, sizeof(TDI_CONNECTION_INFO)); InfoBuf.ConnInfo.State = (ulong)InfoTCB->tcb_state; IPStatus = (*LocalNetInfo.ipi_getpinfo)(InfoTCB->tcb_daddr, InfoTCB->tcb_saddr, NULL, &PathBPS); if (IPStatus != IP_SUCCESS) { InfoBuf.ConnInfo.Throughput.LowPart = 0xFFFFFFFF; InfoBuf.ConnInfo.Throughput.HighPart = 0xFFFFFFFF; } else { InfoBuf.ConnInfo.Throughput.HighPart = 0; TotalTime = InfoTCB->tcb_totaltime / (1000 / MS_PER_TICK); if (TotalTime != 0) { TempULargeInt.LowPart = InfoTCB->tcb_bcountlow; TempULargeInt.HighPart = InfoTCB->tcb_bcounthi; BPS = CTEEnlargedUnsignedDivide(TempULargeInt, TotalTime, NULL); InfoBuf.ConnInfo.Throughput.LowPart = MIN(BPS, PathBPS); } else InfoBuf.ConnInfo.Throughput.LowPart = PathBPS; } // To figure the delay we use the rexmit timeout. Our // rexmit timeout is roughly the round trip time plus // some slop, so we use half of that as the one way delay. #ifdef VXD InfoBuf.ConnInfo.Delay.LowPart = (REXMIT_TO(InfoTCB) * MS_PER_TICK) / 2; InfoBuf.ConnInfo.Throughput.HighPart = 0; #else // VXD InfoBuf.ConnInfo.Delay.LowPart = (REXMIT_TO(InfoTCB) * MS_PER_TICK) / 2; InfoBuf.ConnInfo.Delay.HighPart = 0; // // Convert milliseconds to 100ns and negate for relative // time. // InfoBuf.ConnInfo.Delay = RtlExtendedIntegerMultiply( InfoBuf.ConnInfo.Delay, 10000 ); CTEAssert(InfoBuf.ConnInfo.Delay.HighPart == 0); InfoBuf.ConnInfo.Delay.QuadPart = -InfoBuf.ConnInfo.Delay.QuadPart; #endif // VXD CTEFreeLock(&InfoTCB->tcb_lock, ConnTableHandle); InfoPtr = &InfoBuf.ConnInfo; break; } } // Come through here if we can't find the connection or it has // no TCB. CTEFreeLock(&ConnTableLock, ConnTableHandle); return TDI_INVALID_CONNECTION; break; #else // UDP_ONLY return TDI_INVALID_QUERY; break; #endif // UDP_ONLY case TDI_QUERY_PROVIDER_STATISTICS: CTEMemSet(&InfoBuf.ProviderStats, 0, sizeof(TDI_PROVIDER_STATISTICS)); InfoBuf.ProviderStats.Version = 0x100; InfoSize = sizeof(TDI_PROVIDER_STATISTICS); InfoPtr = &InfoBuf.ProviderStats; break; default: return TDI_INVALID_QUERY; break; } // When we get here, we've got the pointers set up and the information // filled in. CTEAssert(InfoPtr != NULL); Offset = 0; Size = *BufferSize; (void)CopyFlatToNdis(Buffer, InfoPtr, MIN(InfoSize, Size), &Offset, &BytesCopied); if (Size < InfoSize) return TDI_BUFFER_OVERFLOW; else { *BufferSize = InfoSize; return TDI_SUCCESS; } }
/****************************************************************************** * RtlSecondsSince1980ToTime [NTDLL.@] */ void WINAPI RtlSecondsSince1980ToTime( DWORD time, LARGE_INTEGER *res ) { LONGLONG secs = time + SECS_1601_to_1980; res->QuadPart = RtlExtendedIntegerMultiply( secs, 10000000 ); }
LARGE_INTEGER SoundGetTime( VOID ) /*++ Routine Description: Get an accurate estimate of the current time by calling KeQueryPerformanceCounter and converting the result to 100ns units NOTE: A driver should call this once during init to get the thing safely started if it can be called from more than one device at a time Arguments: None Return Value: --*/ { static struct { LARGE_INTEGER StartTime100ns, StartTimeTicks, TicksPerSecond; ULONG Multiplier; BOOLEAN Initialized; } s = { 1 }; // Move from BSS to reduce size ULONG Remainder; if (!s.Initialized) { KeQuerySystemTime(&s.StartTime100ns); s.StartTimeTicks = KeQueryPerformanceCounter(&s.TicksPerSecond); s.Multiplier = 10000000; while (s.TicksPerSecond.HighPart != 0) { s.Multiplier = s.Multiplier / 10; s.TicksPerSecond = RtlExtendedLargeIntegerDivide(s.TicksPerSecond, 10, &Remainder); } s.Initialized = TRUE; } // // Convert ticks to 100ns units (and hope we don't overflow!) // return RtlLargeIntegerAdd( RtlExtendedLargeIntegerDivide( RtlExtendedIntegerMultiply( RtlLargeIntegerSubtract( KeQueryPerformanceCounter(NULL), s.StartTimeTicks ), s.Multiplier ), s.TicksPerSecond.LowPart, &Remainder ), s.StartTime100ns ); }