/*
 * Win32 file change notification functions
 *
 * Copyright 1998 Ulrich Weigand
 *
 * 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 "config.h"

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#include "ntstatus.h"
#define WIN32_NO_STATUS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winternl.h"
#include "kernel_private.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(file);

/****************************************************************************
 *		FindFirstChangeNotificationA (KERNEL32.@)
 */
HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree,
                                            DWORD dwNotifyFilter )
{
    WCHAR *pathW;

    if (!(pathW = FILE_name_AtoW( lpPathName, FALSE ))) return INVALID_HANDLE_VALUE;
    return FindFirstChangeNotificationW( pathW, bWatchSubtree, dwNotifyFilter );
}

/*
 * NtNotifyChangeDirectoryFile may write back to the IO_STATUS_BLOCK
 * asynchronously.  We don't care about the contents, but it can't
 * be placed on the stack since it will go out of scope when we return.
 */
static IO_STATUS_BLOCK FindFirstChange_iosb;

/****************************************************************************
 *		FindFirstChangeNotificationW (KERNEL32.@)
 */
HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree,
                                            DWORD dwNotifyFilter)
{
    UNICODE_STRING nt_name;
    OBJECT_ATTRIBUTES attr;
    NTSTATUS status;
    HANDLE handle = INVALID_HANDLE_VALUE;

    TRACE( "%s %d %x\n", debugstr_w(lpPathName), bWatchSubtree, dwNotifyFilter );

    if (!RtlDosPathNameToNtPathName_U( lpPathName, &nt_name, NULL, NULL ))
    {
        SetLastError( ERROR_PATH_NOT_FOUND );
        return handle;
    }

    attr.Length = sizeof(attr);
    attr.RootDirectory = 0;
    attr.Attributes = OBJ_CASE_INSENSITIVE;
    attr.ObjectName = &nt_name;
    attr.SecurityDescriptor = NULL;
    attr.SecurityQualityOfService = NULL;

    status = NtOpenFile( &handle, FILE_LIST_DIRECTORY | SYNCHRONIZE,
                         &attr, &FindFirstChange_iosb,
                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                         FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
    RtlFreeUnicodeString( &nt_name );

    if (status != STATUS_SUCCESS)
    {
        SetLastError( RtlNtStatusToDosError(status) );
        return INVALID_HANDLE_VALUE;
    }

    status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
                                          &FindFirstChange_iosb,
                                          NULL, 0, dwNotifyFilter, bWatchSubtree );
    if (status != STATUS_PENDING)
    {
        NtClose( handle );
        SetLastError( RtlNtStatusToDosError(status) );
        return INVALID_HANDLE_VALUE;
    }
    return handle;
}

/****************************************************************************
 *		FindNextChangeNotification (KERNEL32.@)
 */
BOOL WINAPI FindNextChangeNotification( HANDLE handle )
{
    NTSTATUS status;

    TRACE("%p\n",handle);

    status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
                                          &FindFirstChange_iosb,
                                          NULL, 0, FILE_NOTIFY_CHANGE_SIZE, 0 );
    if (status != STATUS_PENDING)
    {
        SetLastError( RtlNtStatusToDosError(status) );
        return FALSE;
    }
    return TRUE;
}

/****************************************************************************
 *		FindCloseChangeNotification (KERNEL32.@)
 */
BOOL WINAPI FindCloseChangeNotification( HANDLE handle )
{
    return CloseHandle( handle );
}

static void WINAPI invoke_completion(LPVOID ctx, IO_STATUS_BLOCK *ios, ULONG res)
{
    LPOVERLAPPED_COMPLETION_ROUTINE completion = ctx;
    completion(ios->u.Status, ios->Information, (LPOVERLAPPED)ios);
}

/****************************************************************************
 *		ReadDirectoryChangesW (KERNEL32.@)
 *
 * NOTES
 *
 *  The filter is remember from the first run and ignored on successive runs.
 *
 *  If there's no output buffer on the first run, it's ignored successive runs
 *   and STATUS_NOTIFY_ENUM_DIRECTORY is returned with an empty buffer.
 *
 *  If a NULL overlapped->hEvent is passed, the directory handle is used
 *   for signalling.
 */
BOOL WINAPI ReadDirectoryChangesW( HANDLE handle, LPVOID buffer, DWORD len, BOOL subtree,
                                   DWORD filter, LPDWORD returned, LPOVERLAPPED overlapped,
                                   LPOVERLAPPED_COMPLETION_ROUTINE completion )
{
    OVERLAPPED ov, *pov;
    IO_STATUS_BLOCK *ios;
    NTSTATUS status;
    BOOL ret = TRUE;
    LPVOID cvalue = NULL;

    TRACE("%p %p %08x %d %08x %p %p %p\n", handle, buffer, len, subtree, filter,
           returned, overlapped, completion );

    if (!overlapped)
    {
        memset( &ov, 0, sizeof ov );
        ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
        pov = &ov;
    }
    else
    {
        pov = overlapped;
        if(completion) cvalue = completion;
        else if (((ULONG_PTR)overlapped->hEvent & 1) == 0) cvalue = overlapped;
    }

    ios = (PIO_STATUS_BLOCK) pov;
    ios->u.Status = STATUS_PENDING;

    status = NtNotifyChangeDirectoryFile( handle, completion && overlapped ? NULL : pov->hEvent,
            completion && overlapped ? invoke_completion : NULL,
            cvalue, ios, buffer, len, filter, subtree );
    if (status == STATUS_PENDING)
    {
        if (overlapped)
            return TRUE;

        WaitForSingleObjectEx( ov.hEvent, INFINITE, TRUE );
        CloseHandle( ov.hEvent );
        if (returned)
            *returned = ios->Information;
        status = ios->u.Status;
    }

    if (status != STATUS_SUCCESS)
    {
        SetLastError( RtlNtStatusToDosError(status) );
        ret = FALSE;
    }

    return ret;
}
