Exemplo n.º 1
0
PSRV_TIMER
SrvAllocateTimer (
    VOID
    )

/*++

Routine Description:

    This routine allocates a timer structure.

Arguments:

    None.

Return Value:

    PSRV_TIMER -- pointer to the allocated timer structure, or NULL.

--*/

{
    PSINGLE_LIST_ENTRY entry;
    PSRV_TIMER timer;

    PAGED_CODE( );

    entry = ExInterlockedPopEntrySList( &SrvTimerList, &GLOBAL_SPIN_LOCK(Timer) );
    if ( entry == NULL ) {
        timer = ALLOCATE_NONPAGED_POOL( sizeof(SRV_TIMER), BlockTypeTimer );
        if ( timer != NULL ) {
            KeInitializeEvent( &timer->Event, NotificationEvent, FALSE );
            KeInitializeTimer( &timer->Timer );
        }
    } else {
        timer = CONTAINING_RECORD( entry, SRV_TIMER, Next );
    }

    return timer;

} // SrvAllocateTimer
Exemplo n.º 2
0
NOT PAGEABLE -- SrvRemoveEntryTable
#endif


VOID
SrvAllocateTable (
    IN PTABLE_HEADER TableHeader,
    IN CSHORT NumberOfEntries,
    IN BOOLEAN Nonpaged
    )

/*++

Routine Description:

    This routine allocates a table and sets those fields that it can.

Arguments:

    TableHeader - a pointer to the table header structure

    NumberOfEntries - the number of table entries to allocate

    Nonpaged - indicates whether the table should be allocated from
        nonpaged pool

Return Value:

    None.

--*/

{
    SHORT i;
    CLONG tableSize;
    PTABLE_ENTRY table;

    PAGED_CODE( );

    //
    // Allocate space for the table.
    //

    tableSize = sizeof(TABLE_ENTRY) * NumberOfEntries;

    if ( Nonpaged ) {
        table = ALLOCATE_NONPAGED_POOL( tableSize, BlockTypeTable );
    } else {
        table = ALLOCATE_HEAP( tableSize, BlockTypeTable );
    }

    if ( table == NULL ) {

        INTERNAL_ERROR(
            ERROR_LEVEL_EXPECTED,
            "SrvAllocateTable: Unable to allocate %d bytes from paged pool.",
            tableSize,
            NULL
            );

        TableHeader->Table = NULL;
        return;

    }

    IF_DEBUG(HEAP) {
        SrvPrint1( "SrvAllocateTable: Allocated table at %lx\n", table );
    }

    //
    // Initialize the table, creating a linked list of free entries.
    //

    RtlZeroMemory( table, tableSize );

    table[NumberOfEntries-1].NextFreeEntry = -1;

    for ( i = (SHORT)(NumberOfEntries - 2); i >= 0; i-- ) {
        table[i].NextFreeEntry = (SHORT)(i + 1);
    }

    //
    // Point the table header to the table and set the first and
    // free entry indexes.
    //

    TableHeader->Table = table;
    TableHeader->Nonpaged = Nonpaged;
    TableHeader->TableSize = NumberOfEntries;
    TableHeader->FirstFreeEntry = 0;
    TableHeader->LastFreeEntry = (SHORT)(NumberOfEntries-1);

    return;

} // SrvAllocateTable
Exemplo n.º 3
0
BOOLEAN
SrvGrowTable (
    IN PTABLE_HEADER TableHeader,
    IN CSHORT NumberOfNewEntries,
    IN CSHORT MaxNumberOfEntries
    )

/*++

Routine Description:

    This routine grows a table by the number of entries specified.  It
    allocates new space that is large enough to hold the expanded
    table, copies over the current table, initializes the entries
    that were added, and frees the old table.

    WARNING: The calling routine *must* hold a lock for the table to
    prevent access to the table while it is being copied over.

Arguments:

    TableHeader - a pointer to the table header structure

    NumberOfNewEntries - the number of table entries to add to the table

    MaxNumberOfEntries - the maximum allowable size for the table

Return Value:

    BOOLEAN - TRUE if the table was successfully grown, FALSE otherwise.

--*/

{
    CSHORT newTableSize, totalEntries, oldNumberOfEntries;
    CSHORT i;
    PTABLE_ENTRY table;

    oldNumberOfEntries = TableHeader->TableSize;
    totalEntries = oldNumberOfEntries + NumberOfNewEntries;

    //
    // If the table is already at the maximum size, kick out the request.
    //

    if ( oldNumberOfEntries == MaxNumberOfEntries ) {
        INTERNAL_ERROR(
            ERROR_LEVEL_EXPECTED,
            "SrvGrowTable: Unable to grow table at max size (%ld).",
            MaxNumberOfEntries,
            NULL
            );
        return FALSE;
    }

    //
    // If adding the requested number would put the table size over the
    // maximum, allocate to the maximum size.
    //

    if ( totalEntries > MaxNumberOfEntries ) {
        totalEntries = MaxNumberOfEntries;
        NumberOfNewEntries = totalEntries - oldNumberOfEntries;
    }

    newTableSize = (CSHORT)(totalEntries * sizeof(TABLE_ENTRY));

    //
    // Allocate space for the new table.
    //

    if ( TableHeader->Nonpaged ) {
        table = ALLOCATE_NONPAGED_POOL( newTableSize, BlockTypeTable );
    } else {
        table = ALLOCATE_HEAP( newTableSize, BlockTypeTable );
    }

    if ( table == NULL ) {
        INTERNAL_ERROR(
            ERROR_LEVEL_EXPECTED,
            "SrvGrowTable: Unable to allocate %d bytes from paged pool",
            sizeof( BLOCK_HEADER ) + newTableSize,
            NULL
            );
        return FALSE;
    }

    IF_DEBUG(HEAP) {
        SrvPrint1( "SrvGrowTable: Allocated new table at %lx\n", table );
    }

    //
    // Copy over the information from the old table.  Zero the remainder
    // of the table.
    //

    RtlCopyMemory(
        table,
        TableHeader->Table,
        oldNumberOfEntries * sizeof(TABLE_ENTRY)
        );

    RtlZeroMemory(
        (PCHAR)table + (oldNumberOfEntries * sizeof(TABLE_ENTRY)),
        (totalEntries - oldNumberOfEntries) * sizeof(TABLE_ENTRY)
        );

    //
    // Free the old table.
    //

    SrvFreeTable( TableHeader );

    //
    // Initialize the new table locations in the free list of the table.
    //

    table[totalEntries-1].NextFreeEntry = -1;

    for ( i = (CSHORT)(totalEntries-2); i >= oldNumberOfEntries; i-- ) {
        table[i].NextFreeEntry = (SHORT)(i + 1);
    }

    //
    // Reinitialize the fields of the table header.  It is assumed that
    // the table did not previously have any free entries.
    //

    TableHeader->Table = table;
    TableHeader->TableSize = totalEntries;
    TableHeader->FirstFreeEntry = oldNumberOfEntries;
    TableHeader->LastFreeEntry = (SHORT)(totalEntries-1);

    return TRUE;

} // SrvGrowTable
Exemplo n.º 4
0
NOT PAGEABLE -- WalkConnectionTable
#endif


VOID
SrvAllocateEndpoint (
    OUT PENDPOINT *Endpoint,
    IN PUNICODE_STRING NetworkName,
    IN PUNICODE_STRING TransportName,
    IN PANSI_STRING TransportAddress,
    IN PUNICODE_STRING DomainName
    )

/*++

Routine Description:

    This function allocates an Endpoint Block from the system nonpaged
    pool.

Arguments:

    Endpoint - Returns a pointer to the endpoint block, or NULL if no
        pool was available.

    NetworkName - Supplies a pointer to the network name (e.g., NET1).

    TransportName - The fully qualified name of the transport device.
        For example, "\Device\Nbf".

    TransportAddress - The fully qualified address (or name ) of the
        server's endpoint.  This name is used exactly as specified.  For
        NETBIOS-compatible networks, the caller must upcase and
        blank-fill the name.  E.g., "\Device\Nbf\NTSERVERbbbbbbbb".

    DomainName - the domain being serviced by this endpoint

Return Value:

    None.

--*/

{
    CLONG length;
    PENDPOINT endpoint;
    NTSTATUS status;

    PAGED_CODE( );

    //
    // Attempt to allocate from nonpaged pool.
    //

    length = sizeof(ENDPOINT) +
                NetworkName->Length + sizeof(*NetworkName->Buffer) +
                TransportName->Length + sizeof(*TransportName->Buffer) +
                TransportAddress->Length + sizeof(*TransportAddress->Buffer) +
                DomainName->Length + sizeof(*DomainName->Buffer) +
                RtlUnicodeStringToOemSize( DomainName ) + sizeof(CHAR);

    endpoint = ALLOCATE_NONPAGED_POOL( length, BlockTypeEndpoint );
    *Endpoint = endpoint;

    if ( endpoint == NULL ) {

        INTERNAL_ERROR (
            ERROR_LEVEL_EXPECTED,
            "SrvAllocateEndpoint: Unable to allocate %d bytes from nonpaged "
                "pool.",
            length,
            NULL
            );

        return;
    }

    IF_DEBUG(HEAP) {
        SrvPrint1( "SrvAllocateEndpoint: Allocated endpoint at %lx\n",
                    endpoint );
    }

    //
    // Initialize the endpoint block.  Zero it first.
    //

    RtlZeroMemory( endpoint, length );

    SET_BLOCK_TYPE_STATE_SIZE( endpoint, BlockTypeEndpoint, BlockStateActive, length );
    endpoint->BlockHeader.ReferenceCount = 2;       // allow for Active status
                                                    //  and caller's pointer

    //
    // Allocate connection table.
    //

    SrvAllocateTable(
        &endpoint->ConnectionTable,
        6, // !!!
        TRUE
        );
    if ( endpoint->ConnectionTable.Table == NULL ) {
        DEALLOCATE_NONPAGED_POOL( endpoint );
        *Endpoint = NULL;
        return;
    }

    InitializeListHead( &endpoint->FreeConnectionList );
#if SRVDBG29
    UpdateConnectionHistory( "INIT", endpoint, NULL );
#endif

    //
    // Copy the network name, transport name, and server address, and domain
    // name into the block.
    //

    endpoint->NetworkName.Length = NetworkName->Length;
    endpoint->NetworkName.MaximumLength =
            (SHORT)(NetworkName->Length + sizeof(*NetworkName->Buffer));
    endpoint->NetworkName.Buffer = (PWCH)(endpoint + 1);
    RtlCopyMemory(
        endpoint->NetworkName.Buffer,
        NetworkName->Buffer,
        NetworkName->Length
        );

    endpoint->TransportName.Length = TransportName->Length;
    endpoint->TransportName.MaximumLength =
            (SHORT)(TransportName->Length + sizeof(*TransportName->Buffer));
    endpoint->TransportName.Buffer =
                            (PWCH)((PCHAR)endpoint->NetworkName.Buffer +
                                    endpoint->NetworkName.MaximumLength);
    RtlCopyMemory(
        endpoint->TransportName.Buffer,
        TransportName->Buffer,
        TransportName->Length
        );

    endpoint->TransportAddress.Length = TransportAddress->Length;
    endpoint->TransportAddress.MaximumLength =
                                (SHORT)(TransportAddress->Length + 1);
    endpoint->TransportAddress.Buffer =
                            (PCHAR)endpoint->TransportName.Buffer +
                                    endpoint->TransportName.MaximumLength;
    RtlCopyMemory(
        endpoint->TransportAddress.Buffer,
        TransportAddress->Buffer,
        TransportAddress->Length
        );


    endpoint->DomainName.Length = DomainName->Length;
    endpoint->DomainName.MaximumLength = 
            (SHORT)(DomainName->Length + sizeof(*DomainName->Buffer));
    endpoint->DomainName.Buffer = (PWCH)((PCHAR)endpoint->TransportAddress.Buffer +
                                         TransportAddress->MaximumLength);
    RtlCopyMemory(
        endpoint->DomainName.Buffer,
        DomainName->Buffer,
        DomainName->Length
    );


    endpoint->OemDomainName.Length = (SHORT)RtlUnicodeStringToOemSize( DomainName );
    endpoint->OemDomainName.MaximumLength =
            endpoint->OemDomainName.Length + sizeof( CHAR );
    endpoint->OemDomainName.Buffer = (PCHAR)endpoint->DomainName.Buffer +
                                     DomainName->MaximumLength;
    status = RtlUnicodeStringToOemString(
                &endpoint->OemDomainName,
                &endpoint->DomainName,
                FALSE     // Do not allocate the OEM string
                );
    ASSERT( NT_SUCCESS(status) );
            

    //
    // Initialize the network address field.
    //

    endpoint->NetworkAddress.Buffer = endpoint->NetworkAddressData;
    endpoint->NetworkAddress.Length = sizeof( endpoint->NetworkAddressData ) -
                                      sizeof(endpoint->NetworkAddressData[0]);
    endpoint->NetworkAddress.MaximumLength = sizeof( endpoint->NetworkAddressData );

    //
    // Increment the count of endpoints in the server.
    //

    ACQUIRE_LOCK( &SrvEndpointLock );
    SrvEndpointCount++;
    RELEASE_LOCK( &SrvEndpointLock );

    INITIALIZE_REFERENCE_HISTORY( endpoint );

    INCREMENT_DEBUG_STAT( SrvDbgStatistics.EndpointInfo.Allocations );

    return;

} // SrvAllocateEndpoint
Exemplo n.º 5
0
VOID
SrvCacheDirectoryName (
    IN  PWORK_CONTEXT      WorkContext,
    IN  PUNICODE_STRING    DirectoryName
)
/*++

Routine Description:

    This routine remembers 'DirectoryName' for further fast processing of the CheckPath SMB

Arguments:

    WorkContext - Pointer to the work context block

    DirectoryName - Fully canonicalized name of the directory we're caching

++*/

{
    CLONG blockLength;
    PCACHED_DIRECTORY cd;
    KIRQL oldIrql;
    PCONNECTION connection = WorkContext->Connection;
    PLIST_ENTRY listEntry;
    LARGE_INTEGER timeNow;
    USHORT tid;

    if( SrvMaxCachedDirectory == 0 ) {
        return;
    }

    //
    // DirectoryName must point to memory in nonpaged pool, else we can't touch
    //   it under spinlock control.  If the incomming SMB is UNICODE, we know that
    //   the name is in the smb buffer, and is therefore in nonpaged pool.  Otherwise
    //   we can't trust it and we're better off just not trying to cache it.
    //
    if( !SMB_IS_UNICODE( WorkContext ) ) {
        return;
    }

    KeQueryTickCount( &timeNow );
    timeNow.LowPart -= ( SrvFiveSecondTickCount >> 1 );

    tid = WorkContext->TreeConnect->Tid;

    ACQUIRE_SPIN_LOCK( &connection->SpinLock, &oldIrql );

    //
    // Search the directory cache and see if this directory is already cached. If so,
    //  don't cache it again.
    //

top:
    for ( listEntry = connection->CachedDirectoryList.Flink;
            listEntry != &connection->CachedDirectoryList;
            listEntry = listEntry->Flink ) {

        cd = CONTAINING_RECORD( listEntry, CACHED_DIRECTORY, ListEntry );

        //
        // Is this element too old?
        //
        if( cd->TimeStamp < timeNow.LowPart ) {
            //
            // This element is more than 2.5 seconds old.  Toss it out
            //
            RemoveEntryList( listEntry );
            connection->CachedDirectoryCount--;
            DEALLOCATE_NONPAGED_POOL( cd );
            goto top;
        }

        if( cd->Tid != tid ) {
            continue;
        }

        //
        // Is the new entry a subdir of this cache entry?
        //
        if( DirectoryName->Length < cd->DirectoryName.Length &&
                RtlCompareMemory( DirectoryName->Buffer, cd->DirectoryName.Buffer,
                                  DirectoryName->Length ) == DirectoryName->Length &&
                cd->DirectoryName.Buffer[ DirectoryName->Length / sizeof( WCHAR ) ] == L'\\' ) {

            //
            // It is a subdir -- no need to cache it again
            //
            RELEASE_SPIN_LOCK( &connection->SpinLock, oldIrql );

            return;
        }

        //
        // Is the cache entry a subdir of the new entry?
        //
        if( cd->DirectoryName.Length < DirectoryName->Length &&
                RtlCompareMemory( DirectoryName->Buffer, cd->DirectoryName.Buffer,
                                  cd->DirectoryName.Length ) == cd->DirectoryName.Length &&
                DirectoryName->Buffer[ cd->DirectoryName.Length / sizeof( WCHAR ) ] == L'\\' ) {

            //
            // We can remove this entry
            //

            RemoveEntryList( listEntry );
            connection->CachedDirectoryCount--;
            DEALLOCATE_NONPAGED_POOL( cd );

            //
            // We want to cache this new longer entry
            //
            break;
        }

        //
        // Not a subdir -- is it an exact match?
        //
        if( cd->DirectoryName.Length == DirectoryName->Length &&
                RtlCompareMemory( cd->DirectoryName.Buffer, DirectoryName->Buffer,
                                  DirectoryName->Length ) == DirectoryName->Length ) {

            //
            // This entry is already in the cache -- no need to recache
            //
            RELEASE_SPIN_LOCK( &connection->SpinLock, oldIrql );
            return;
        }
    }

    //
    // This directory name is not already in the cache.  So add it.
    //

    blockLength = sizeof( CACHED_DIRECTORY ) + DirectoryName->Length + sizeof(WCHAR);

    cd = ALLOCATE_NONPAGED_POOL( blockLength, BlockTypeCachedDirectory );

    if( cd == NULL ) {

        RELEASE_SPIN_LOCK( &connection->SpinLock, oldIrql );

        INTERNAL_ERROR(
            ERROR_LEVEL_EXPECTED,
            "SrvCacheDirectoryName: Unable to allocate %d bytes from pool",
            blockLength,
            NULL
        );

        return;
    }

    cd->Type = BlockTypeCachedDirectory;
    cd->State = BlockStateActive;
    cd->Size = (USHORT)blockLength;
    // cd->ReferenceCount = 1;              // not used

    //
    // Set the timestamp of this entry.  Remember, we subtracted
    //  ticks up above from timeNow -- put them back in now.
    //
    cd->TimeStamp = timeNow.LowPart + ( SrvFiveSecondTickCount >> 1 );

    //
    // Store the directory name as it was passed into us
    //
    cd->DirectoryName.Length = DirectoryName->Length;
    cd->DirectoryName.MaximumLength = (USHORT)DirectoryName->MaximumLength;
    cd->DirectoryName.Buffer = (PWCH)(cd + 1);
    RtlCopyMemory( cd->DirectoryName.Buffer, DirectoryName->Buffer, DirectoryName->Length );

    cd->Tid = tid;

    InsertHeadList(
        &connection->CachedDirectoryList,
        &cd->ListEntry
    );

    //
    // Check the number of elements in the cache.  If getting too large, close oldest one.
    //
    if( connection->CachedDirectoryCount++ < SrvMaxCachedDirectory ) {
        RELEASE_SPIN_LOCK( &connection->SpinLock, oldIrql );
        return;
    }

    //
    // Remove the last entry from the cache
    //
    cd = CONTAINING_RECORD(
             connection->CachedDirectoryList.Blink,
             CACHED_DIRECTORY,
             ListEntry
         );

    RemoveEntryList( &cd->ListEntry );
    connection->CachedDirectoryCount--;

    RELEASE_SPIN_LOCK( &connection->SpinLock, oldIrql );

    DEALLOCATE_NONPAGED_POOL( cd );

    return;
}