void
globus_xio_system_socket_destroy(
    globus_xio_system_socket_handle_t   handle)
{
    unsigned long                       flag = 0;
    GlobusXIOName(globus_xio_system_socket_destroy);
    
    GlobusXIOSystemDebugEnterFD(handle->socket);
    
    globus_assert(!handle->read_info && !handle->write_info);
    
    /* no need to ensure entry is still registered, as I always return true
     * in the callback and this is only place i unregister
     */
    globus_i_xio_win32_event_lock(handle->event_entry);
    
    GlobusXIOSystemDebugPrintf(
        GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
        ("[%s] Unregistering event handle=%lu for socket %ld\n",
            _xio_name, (unsigned long) handle->event, (long) handle->socket));
            
    globus_i_xio_win32_event_unregister(handle->event_entry);
    globus_i_xio_win32_event_unlock(handle->event_entry);
    
    WSAEventSelect(handle->socket, 0, 0);
    ioctlsocket(handle->socket, FIONBIO, &flag);
    WSACloseEvent(handle->event);
    win32_mutex_destroy(&handle->lock);
    
    GlobusXIOSystemDebugExitFD(handle->socket);
    globus_free(handle);
}
int
globus_i_xio_win32_complete_activate(void)
{
    globus_result_t                     result;
    globus_reltime_t                    period;
    GlobusXIOName(globus_i_xio_win32_complete_activate);
    
    GlobusXIOSystemDebugEnter();
    
    if (!globus_i_am_only_thread())
    {
        goto skip_activate;
    }
    GlobusLWin32PollQueueInit();
    win32_mutex_init(&globus_l_xio_win32_poll_lock, 0);
    globus_l_xio_win32_poll_event_sleeping = GLOBUS_FALSE;
    globus_l_xio_win32_poll_event_pending = GLOBUS_FALSE;
    globus_l_xio_win32_poll_free = 0;
    
    globus_l_xio_win32_poll_event = CreateEvent(0, FALSE, FALSE, 0);
    if(globus_l_xio_win32_poll_event == 0)
    {
        goto error_event;
    }
    
    GlobusTimeReltimeSet(period, 0, 0);
    result = globus_callback_register_periodic(
        &globus_l_xio_win32_poll_handle,
        0,
        &period,
        globus_l_xio_win32_poll,
        0);
    if(result != GLOBUS_SUCCESS)
    {
        goto error_periodic;
    }
    
    globus_callback_add_wakeup_handler(
        globus_l_xio_win32_wakeup_handler, 0);
    
skip_activate:
    GlobusXIOSystemDebugExit();
    
    return GLOBUS_SUCCESS;
    
error_periodic:
    CloseHandle(globus_l_xio_win32_poll_event);
    globus_l_xio_win32_poll_event = 0;
error_event:
    win32_mutex_destroy(&globus_l_xio_win32_poll_lock);
    GlobusXIOSystemDebugExitWithError();
    return GLOBUS_FAILURE;
}
globus_result_t
globus_xio_system_socket_init(
    globus_xio_system_socket_handle_t * uhandle,
    globus_xio_system_socket_t          socket,
    globus_xio_system_type_t            type)
{
    globus_result_t                     result;
    globus_l_xio_win32_socket_t *       handle;
    unsigned long                       flag;
    GlobusXIOName(globus_xio_system_socket_init);
    
    GlobusXIOSystemDebugEnterFD(socket);
    
    handle = (globus_l_xio_win32_socket_t *)
        globus_calloc(1, sizeof(globus_l_xio_win32_socket_t));
    if(!handle)
    {
        result = GlobusXIOErrorMemory("handle");
        goto error_alloc;
    }
    
    handle->socket = socket;
    win32_mutex_init(&handle->lock, 0);
    handle->ready_events = FD_READ; /* to avoid winsock fd_close bug */
    
    handle->event = WSACreateEvent();
    if(handle->event == 0)
    {
        result = GlobusXIOErrorSystemError(
            "WSACreateEvent", WSAGetLastError());
        goto error_create;
    }
    
    flag = 1;
    if(ioctlsocket(socket, FIONBIO, &flag) == SOCKET_ERROR)
    {
        result = GlobusXIOErrorSystemError(
            "ioctlsocket", WSAGetLastError());
        goto error_ioctl;
    }
    
    result = globus_i_xio_win32_event_register(
        &handle->event_entry,
        handle->event,
        globus_l_xio_win32_socket_event_cb,
        handle);
    if(result != GLOBUS_SUCCESS)
    {
        result = GlobusXIOErrorWrapFailed(
            "globus_i_xio_win32_event_register", result);
        goto error_register;
    }
    
    GlobusXIOSystemDebugPrintf(
        GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
        ("[%s] Registered event handle=%lu\n",
            _xio_name, (unsigned long) handle->event));
        
    *uhandle = handle;
    
    GlobusXIOSystemDebugExitFD(socket);
    return GLOBUS_SUCCESS;

error_register:
    flag = 0;
    ioctlsocket(socket, FIONBIO, &flag);
error_ioctl:
    WSACloseEvent(handle->event);
error_create:
    win32_mutex_destroy(&handle->lock);
    globus_free(handle);
error_alloc:
    GlobusXIOSystemDebugExitWithErrorFD(socket);
    return result;
}
int
globus_i_xio_win32_complete_deactivate(void)
{
    globus_result_t                     result;
    globus_l_shutdown_info_t            info;
    GlobusXIOName(globus_i_xio_win32_complete_deactivate);
    
    GlobusXIOSystemDebugEnter();

    if (!globus_i_am_only_thread())
    {
        goto skip_deactivate;
    }

    globus_mutex_init(&info.mutex, NULL);
    globus_cond_init(&info.cond, NULL);
    
    globus_mutex_lock(&info.mutex);
    {
        result = globus_callback_unregister(
            globus_l_xio_win32_poll_handle,
            globus_l_xio_win32_unregister_poll_cb,
            &info,
            0);
            
        if(result == GLOBUS_SUCCESS)
        {
            /* unregister callback destroys this event object */
            while(globus_l_xio_win32_poll_event != 0)
            {
                globus_cond_wait(&info.cond, &info.mutex);
            }
        }
        else
        {
            globus_mutex_unlock(&info.mutex);
            globus_l_xio_win32_unregister_poll_cb(&info);
            globus_mutex_lock(&info.mutex);
        }
    }
    globus_mutex_unlock(&info.mutex);
    
    globus_cond_destroy(&info.cond);
    globus_mutex_destroy(&info.mutex);
    
    win32_mutex_destroy(&globus_l_xio_win32_poll_lock);
    
    while(globus_l_xio_win32_poll_free)
    {
        globus_l_xio_win32_poll_entry_t * next =
            globus_l_xio_win32_poll_free->next;
            
        globus_free(globus_l_xio_win32_poll_free);
        
        globus_l_xio_win32_poll_free = next;
    }
    
skip_deactivate:
    GlobusXIOSystemDebugExit();
    
    return GLOBUS_SUCCESS;
}