* 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., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Vlad Grecescu <b100dian@gmail.com>
*
*/
-#define _WIN32_WINNT 0x0400
-
#include "config.h"
#include "gwin32directorymonitor.h"
-#include "giomodule.h"
#include <windows.h>
G_DEFINE_TYPE_WITH_CODE (GWin32DirectoryMonitor,
{
GWin32DirectoryMonitor *self;
self = G_WIN32_DIRECTORY_MONITOR (base);
-
- g_free (self->priv->file_notify_buffer);
- g_free (self->priv);
+
+ if (self->priv->hDirectory == INVALID_HANDLE_VALUE)
+ {
+ /* If we don't have a directory handle we can free
+ * self->priv->file_notify_buffer and self->priv here. The
+ * callback won't be called obviously any more (and presumably
+ * never has been called).
+ */
+ g_free (self->priv->file_notify_buffer);
+ self->priv->file_notify_buffer = NULL;
+ g_free (self->priv);
+ }
+ else
+ {
+ /* If we have a directory handle, the OVERLAPPED struct is
+ * passed once more to the callback as a result of the
+ * CloseHandle() done in the cancel method, so self->priv has to
+ * be kept around. The GWin32DirectoryMonitor object is
+ * disappearing, so can't leave a pointer to it in
+ * self->priv->self.
+ */
+ self->priv->self = NULL;
+ }
if (G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize)
(*G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize) (base);
GWin32DirectoryMonitor *self;
self = G_WIN32_DIRECTORY_MONITOR (base);
- /* This triggers a last callback() with nBytes=0 */
+ /* This triggers a last callback() with nBytes==0. */
+
+ /* Actually I am not so sure about that, it seems to trigger a last
+ * callback allright, but the way to recognize that it is the final
+ * one is not to check for nBytes==0, I think that was a
+ * misunderstanding.
+ */
if (self->priv->hDirectory != INVALID_HANDLE_VALUE)
CloseHandle (self->priv->hDirectory);
{
gulong offset;
PFILE_NOTIFY_INFORMATION pfile_notify_walker;
- gulong file_name_len;
+ glong file_name_len;
gchar *file_name;
gchar *path;
GFile *file;
G_FILE_MONITOR_EVENT_CREATED, /* FILE_ACTION_RENAMED_NEW_NAME */
};
- if (!nBytes) /* Monitor was cancelled/finalized */
- return;
-
- if (g_file_monitor_is_cancelled (G_FILE_MONITOR (priv->self)))
- return; /* and ReadDirectoryChangesW doesn't get called this time */
+ /* If priv->self is NULL the GWin32DirectoryMonitor object has been destroyed. */
+ if (priv->self == NULL ||
+ g_file_monitor_is_cancelled (priv->self) ||
+ priv->file_notify_buffer == NULL)
+ {
+ g_free (priv->file_notify_buffer);
+ g_free (priv);
+ return;
+ }
offset = 0;
do {
pfile_notify_walker = (PFILE_NOTIFY_INFORMATION)(priv->file_notify_buffer + offset);
+ if (pfile_notify_walker->Action > 0)
+ {
+ file_name = g_utf16_to_utf8 (pfile_notify_walker->FileName, pfile_notify_walker->FileNameLength / sizeof(WCHAR), NULL, &file_name_len, NULL);
+ path = g_build_filename(G_LOCAL_DIRECTORY_MONITOR (priv->self)->dirname, file_name, NULL);
+ file = g_file_new_for_path (path);
+ g_file_monitor_emit_event (priv->self, file, NULL, events [pfile_notify_walker->Action]);
+ g_object_unref (file);
+ g_free (path);
+ g_free (file_name);
+ }
offset += pfile_notify_walker->NextEntryOffset;
- file_name = g_utf16_to_utf8 (pfile_notify_walker->FileName, pfile_notify_walker->FileNameLength / sizeof(WCHAR), NULL, &file_name_len, NULL);
- path = g_build_filename(G_LOCAL_DIRECTORY_MONITOR (priv->self)->dirname, file_name, NULL);
- file = g_file_new_for_path (path);
- g_file_monitor_emit_event (priv->self, file, NULL, events [pfile_notify_walker->Action]);
- g_object_unref (file);
- g_free (path);
- g_free (file_name);
} while (pfile_notify_walker->NextEntryOffset);
ReadDirectoryChangesW (priv->hDirectory,
GObjectClass *parent_class;
GWin32DirectoryMonitor *self;
wchar_t *wdirname;
- gboolean result;
klass = G_WIN32_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_WIN32_DIRECTORY_MONITOR));
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
return obj;
}
- result = ReadDirectoryChangesW (self->priv->hDirectory,
- (gpointer)self->priv->file_notify_buffer,
- self->priv->buffer_allocated_bytes,
- FALSE,
- FILE_NOTIFY_CHANGE_FILE_NAME |
- FILE_NOTIFY_CHANGE_DIR_NAME |
- FILE_NOTIFY_CHANGE_ATTRIBUTES |
- FILE_NOTIFY_CHANGE_SIZE,
- &self->priv->buffer_filled_bytes,
- &self->priv->overlapped,
- g_win32_directory_monitor_callback);
+ ReadDirectoryChangesW (self->priv->hDirectory,
+ (gpointer)self->priv->file_notify_buffer,
+ self->priv->buffer_allocated_bytes,
+ FALSE,
+ FILE_NOTIFY_CHANGE_FILE_NAME |
+ FILE_NOTIFY_CHANGE_DIR_NAME |
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_SIZE,
+ &self->priv->buffer_filled_bytes,
+ &self->priv->overlapped,
+ g_win32_directory_monitor_callback);
/* Ignore errors */
return obj;