/* $Id$ * captive vfs utility functions for interface to reactos * Copyright (C) 2002-2003 Jan Kratochvil * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; exactly version 2 of June 1991 is required * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "lib.h" /* self */ #include #include #include "captive/macros.h" #include "reactos/ntos/rtl.h" /* for InitializeObjectAttributes() */ #include "captive/unicode.h" #include /* for gnome_vfs_unescape_string() */ #include "captive/options.h" #include /* Returns: g_malloc() allocated absolute pathname string */ gchar *captive_path_normalize(const gchar *raw_pathname) { gchar *r,*r_end,*s,*d; g_return_val_if_fail(raw_pathname!=NULL,NULL); g_return_val_if_fail(g_path_is_absolute(raw_pathname),NULL); r=g_strdup(raw_pathname); /* coalesce '/'es */ for (d=s=r;*s;s++) { if (*s==G_DIR_SEPARATOR && d>r && d[-1]==G_DIR_SEPARATOR) continue; *d++=*s; } g_assert(d>r); if (d>(r+1) && d[-1]==G_DIR_SEPARATOR) d--; *d++=G_DIR_SEPARATOR; r_end=d; /* 'r' is NOT NULL-terminated here! */ for (d=s=r+1;sr+1) { do { d--; } while (d[-1]!=G_DIR_SEPARATOR); } continue; } *d++=*s++; } g_assert(d[-1]==G_DIR_SEPARATOR); /* trailing '/' */ if (d>r+1) /* leave at least "/" */ d--; *d='\0'; g_assert(g_path_is_absolute(r)); return r; } /* function will leave g_malloc()ed 'ObjectAttributes->ObjectName'! */ GnomeVFSResult captive_ObjectAttributes_init(const gchar *pathname,OBJECT_ATTRIBUTES *ObjectAttributes) { gchar *w32_path,*s,*d; const gchar *media_root; gchar *pathname_normalized; g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(ObjectAttributes!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); /* Do not open "\Cdfs"(anything) as it is just the filesystem implementation. * ntoskrnl/io/fs.c/IoMountVolume() will map * FILE_DEVICE_CD_ROM -> FILE_DEVICE_CD_ROM_FILE_SYSTEM * for us automatically when opening the device itself. * If you put some trailing content (such as "\\.") there * IoCreateFile()->ObCreateObject()->ObFindObject() * will not leave 'ObCreateObject::RemainingPath' as NULL * and later IopCreateFile() would not consider it FO_DIRECT_DEVICE_OPEN (e.g. w/o any direct mount!). * On the other side it will somehow get managed automatically and it works even * without the trailing "\\." for root directory open - don't ask me why. :-) * Tested: \\Device\\CaptiveHarddisk0\\. FAIL * \\Device\\CaptiveHarddisk0\\ OK */ switch (captive_options->media) { case CAPTIVE_OPTION_MEDIA_CDROM: media_root="\\Device\\CdRom0"; break; /* libcaptive/storage/cdrom.c */ case CAPTIVE_OPTION_MEDIA_DISK: media_root="\\Device\\CaptiveHarddisk0"; break; /* libcaptive/storage/disk.c */ default: g_assert_not_reached(); media_root=""; } pathname_normalized=captive_path_normalize(pathname); w32_path=(gchar *)/* de-const it as we can modify it but we must not free() it */ captive_printf_alloca("%s\\%s",media_root,pathname_normalized); g_free(pathname_normalized); /* translate '/' -> '\' */ for (s=w32_path;(s=strchr(s,'/'));s++) *s='\\'; /* collapse multiple sequences of '\' as it is a no-no for W32 */ for (s=d=w32_path;*s;s++) if (d==w32_path || !(*s=='\\' && d[-1]=='\\')) *d++=*s; *d=0; InitializeObjectAttributes( ObjectAttributes, /* InitializedAttributes */ captive_utf8_to_UnicodeString_malloc(w32_path), /* ObjectName */ 0, /* Attributes; I hope no OBJ_KERNEL_HANDLE as we are 'system process' */ NULL, /* RootDirectory */ NULL); /* SecurityDescriptor; ignored */ return GNOME_VFS_OK; } void captive_giochannel_setup(GIOChannel *giochannel) { GIOStatus erriostatus; g_return_if_fail(giochannel!=NULL); if (g_io_channel_get_encoding(giochannel)) { if (!g_io_channel_get_buffered(giochannel)) /* Prevent: Need to have NULL encoding to set the buffering state ... */ g_io_channel_set_buffered(giochannel,TRUE); /* Prevent: Need to set the channel buffered before setting the encoding. */ erriostatus=g_io_channel_set_encoding(giochannel, NULL, /* encoding; force binary data */ NULL); /* error */ g_assert(erriostatus==G_IO_STATUS_NORMAL); } erriostatus=g_io_channel_flush(giochannel, NULL); /* error */ g_assert(erriostatus==G_IO_STATUS_NORMAL); g_io_channel_set_buffered(giochannel,FALSE); }