/*
 * Server-side USER handles
 *
 * Copyright (C) 2001 Alexandre Julliard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "thread.h"
#include "user.h"
#include "request.h"

struct user_handle
{
    void          *ptr;          /* pointer to object */
    unsigned short type;         /* object type (0 if free) */
    unsigned short generation;   /* generation counter */
};

static struct user_handle *handles;
static struct user_handle *freelist;
static int nb_handles;
static int allocated_handles;

static struct user_handle *handle_to_entry( user_handle_t handle )
{
    unsigned short generation;
    int index = ((handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
    if (index < 0 || index >= nb_handles) return NULL;
    if (!handles[index].type) return NULL;
    generation = handle >> 16;
    if (generation == handles[index].generation || !generation || generation == 0xffff)
        return &handles[index];
    return NULL;
}

static inline user_handle_t entry_to_handle( struct user_handle *ptr )
{
    unsigned int index = ptr - handles;
    return (index << 1) + FIRST_USER_HANDLE + (ptr->generation << 16);
}

static inline struct user_handle *alloc_user_entry(void)
{
    struct user_handle *handle;

    if (freelist)
    {
        handle = freelist;
        freelist = handle->ptr;
        return handle;
    }
    if (nb_handles >= allocated_handles)  /* need to grow the array */
    {
        struct user_handle *new_handles;
        /* grow array by 50% (but at minimum 32 entries) */
        int growth = max( 32, allocated_handles / 2 );
        int new_size = min( allocated_handles + growth, (LAST_USER_HANDLE-FIRST_USER_HANDLE+1) >> 1 );
        if (new_size <= allocated_handles) return NULL;
        if (!(new_handles = realloc( handles, new_size * sizeof(*handles) )))
            return NULL;
        handles = new_handles;
        allocated_handles = new_size;
    }
    handle = &handles[nb_handles++];
    handle->generation = 0;
    return handle;
}

static inline void *free_user_entry( struct user_handle *ptr )
{
    void *ret;
    ret = ptr->ptr;
    ptr->ptr  = freelist;
    ptr->type = 0;
    freelist  = ptr;
    return ret;
}

/* allocate a user handle for a given object */
user_handle_t alloc_user_handle( void *ptr, enum user_object type )
{
    struct user_handle *entry = alloc_user_entry();
    if (!entry) return 0;
    entry->ptr  = ptr;
    entry->type = type;
    if (++entry->generation >= 0xffff) entry->generation = 1;
    return entry_to_handle( entry );
}

/* return a pointer to a user object from its handle */
void *get_user_object( user_handle_t handle, enum user_object type )
{
    struct user_handle *entry;

    if (!(entry = handle_to_entry( handle )) || entry->type != type) return NULL;
    return entry->ptr;
}

/* get the full handle for a possibly truncated handle */
user_handle_t get_user_full_handle( user_handle_t handle )
{
    struct user_handle *entry;

    if (handle >> 16) return handle;
    if (!(entry = handle_to_entry( handle ))) return handle;
    return entry_to_handle( entry );
}

/* same as get_user_object plus set the handle to the full 32-bit value */
void *get_user_object_handle( user_handle_t *handle, enum user_object type )
{
    struct user_handle *entry;

    if (!(entry = handle_to_entry( *handle )) || entry->type != type) return NULL;
    *handle = entry_to_handle( entry );
    return entry->ptr;
}

/* free a user handle and return a pointer to the object */
void *free_user_handle( user_handle_t handle )
{
    struct user_handle *entry;

    if (!(entry = handle_to_entry( handle )))
    {
        set_error( STATUS_INVALID_HANDLE );
        return NULL;
    }
    return free_user_entry( entry );
}

/* return the next user handle after 'handle' that is of a given type */
void *next_user_handle( user_handle_t *handle, enum user_object type )
{
    struct user_handle *entry;

    if (!*handle) entry = handles;
    else
    {
        int index = ((*handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
        if (index < 0 || index >= nb_handles) return NULL;
        entry = handles + index + 1;  /* start from the next one */
    }
    while (entry < handles + nb_handles)
    {
        if (!type || entry->type == type)
        {
            *handle = entry_to_handle( entry );
            return entry->ptr;
        }
        entry++;
    }
    return NULL;
}

/* free client-side user handles managed by the process */
void free_process_user_handles( struct process *process )
{
    unsigned int i;

    for (i = 0; i < nb_handles; i++)
        if (handles[i].type == USER_CLIENT && handles[i].ptr == process)
            free_user_entry( &handles[i] );
}

/* allocate an arbitrary user handle */
DECL_HANDLER(alloc_user_handle)
{
    reply->handle = alloc_user_handle( current->process, USER_CLIENT );
}


/* free an arbitrary user handle */
DECL_HANDLER(free_user_handle)
{
    struct user_handle *entry;

    if ((entry = handle_to_entry( req->handle )) && entry->type == USER_CLIENT)
        free_user_entry( entry );
    else
        set_error( STATUS_INVALID_HANDLE );
}
