/* * Win32 file change notification functions * * Copyright 1998 Ulrich Weigand */ #include #include #include #include #include #include "windows.h" #include "winbase.h" #include "winerror.h" #include "process.h" #include "thread.h" #include "heap.h" #include "debug.h" static BOOL32 CHANGE_Signaled( K32OBJ *obj, DWORD thread_id ); static BOOL32 CHANGE_Satisfied( K32OBJ *obj, DWORD thread_id ); static void CHANGE_AddWait( K32OBJ *obj, DWORD thread_id ); static void CHANGE_RemoveWait( K32OBJ *obj, DWORD thread_id ); static void CHANGE_Destroy( K32OBJ *obj ); const K32OBJ_OPS CHANGE_Ops = { CHANGE_Signaled, /* signaled */ CHANGE_Satisfied, /* satisfied */ CHANGE_AddWait, /* add_wait */ CHANGE_RemoveWait, /* remove_wait */ NULL, /* read */ NULL, /* write */ CHANGE_Destroy /* destroy */ }; /* The change notification object */ typedef struct { K32OBJ header; LPSTR lpPathName; BOOL32 bWatchSubtree; DWORD dwNotifyFilter; THREAD_QUEUE wait_queue; BOOL32 notify; } CHANGE_OBJECT; /*********************************************************************** * CHANGE_Signaled */ static BOOL32 CHANGE_Signaled( K32OBJ *obj, DWORD thread_id ) { CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj; assert( obj->type == K32OBJ_CHANGE ); return change->notify; } /*********************************************************************** * CHANGE_Satisfied * * Wait on this object has been satisfied. */ static BOOL32 CHANGE_Satisfied( K32OBJ *obj, DWORD thread_id ) { assert( obj->type == K32OBJ_CHANGE ); return FALSE; /* Not abandoned */ } /*********************************************************************** * CHANGE_AddWait * * Add thread to object wait queue. */ static void CHANGE_AddWait( K32OBJ *obj, DWORD thread_id ) { CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj; assert( obj->type == K32OBJ_CHANGE ); THREAD_AddQueue( &change->wait_queue, THREAD_ID_TO_THDB(thread_id) ); } /*********************************************************************** * CHANGE_RemoveWait * * Remove thread from object wait queue. */ static void CHANGE_RemoveWait( K32OBJ *obj, DWORD thread_id ) { CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj; assert( obj->type == K32OBJ_CHANGE ); THREAD_RemoveQueue( &change->wait_queue, THREAD_ID_TO_THDB(thread_id) ); } /**************************************************************************** * CHANGE_Destroy */ static void CHANGE_Destroy( K32OBJ *obj ) { CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj; assert( obj->type == K32OBJ_CHANGE ); if ( change->lpPathName ) { HeapFree( SystemHeap, 0, change->lpPathName ); change->lpPathName = NULL; } obj->type = K32OBJ_UNKNOWN; HeapFree( SystemHeap, 0, change ); } /**************************************************************************** * FindFirstChangeNotification32A (KERNEL32.248) */ HANDLE32 WINAPI FindFirstChangeNotification32A( LPCSTR lpPathName, BOOL32 bWatchSubtree, DWORD dwNotifyFilter ) { HANDLE32 handle; CHANGE_OBJECT *change; change = HeapAlloc( SystemHeap, 0, sizeof(CHANGE_OBJECT) ); if (!change) return INVALID_HANDLE_VALUE32; change->header.type = K32OBJ_CHANGE; change->header.refcount = 1; change->lpPathName = HEAP_strdupA( SystemHeap, 0, lpPathName ); change->bWatchSubtree = bWatchSubtree; change->dwNotifyFilter = dwNotifyFilter; change->wait_queue = NULL; change->notify = FALSE; handle = HANDLE_Alloc( PROCESS_Current(), &change->header, FILE_ALL_ACCESS /*FIXME*/, TRUE, -1 ); /* If the allocation failed, the object is already destroyed */ if (handle == INVALID_HANDLE_VALUE32) change = NULL; return handle; } /**************************************************************************** * FindFirstChangeNotification32W (KERNEL32.249) */ HANDLE32 WINAPI FindFirstChangeNotification32W( LPCWSTR lpPathName, BOOL32 bWatchSubtree, DWORD dwNotifyFilter) { LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpPathName ); HANDLE32 ret = FindFirstChangeNotification32A( nameA, bWatchSubtree, dwNotifyFilter ); if (nameA) HeapFree( GetProcessHeap(), 0, nameA ); return ret; } /**************************************************************************** * FindNextChangeNotification (KERNEL32.252) */ BOOL32 WINAPI FindNextChangeNotification( HANDLE32 handle ) { CHANGE_OBJECT *change; SYSTEM_LOCK(); if (!(change = (CHANGE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(), handle, K32OBJ_CHANGE, 0 /*FIXME*/, NULL )) ) { SYSTEM_UNLOCK(); return FALSE; } change->notify = FALSE; K32OBJ_DecCount( &change->header ); SYSTEM_UNLOCK(); return TRUE; } /**************************************************************************** * FindCloseChangeNotification (KERNEL32.247) */ BOOL32 WINAPI FindCloseChangeNotification( HANDLE32 handle) { return CloseHandle( handle ); }