diff --git a/project/common.mk b/project/common.mk
index 3b9d693..9868db3 100644
--- a/project/common.mk
+++ b/project/common.mk
@@ -22,6 +22,7 @@ COMMON_SRCS = \
 	src/internal/ptycon_memfn_impl.c \
 	src/internal/ptycon_nolibc_impl.c \
 	src/internal/ptycon_ntaio_impl.c \
+	src/internal/ptycon_open_impl.c \
 	src/pty/ptyc_pty_ctx.c \
 	src/skin/ptyc_skin_default.c \
 
diff --git a/src/debug/ptyc_dbg_cat.c b/src/debug/ptyc_dbg_cat.c
index 9cb54f6..e8cfb16 100644
--- a/src/debug/ptyc_dbg_cat.c
+++ b/src/debug/ptyc_dbg_cat.c
@@ -11,57 +11,6 @@
 #include <ptycon/ptycon.h>
 #include "ptycon_driver_impl.h"
 
-static int32_t ptyc_open(void ** hfile, void * hat, const char * arg)
-{
-	int32_t						status;
-	nt_oa						oa;
-	nt_iosb						iosb;
-	nt_unicode_string				path;
-	nt_unicode_conversion_params_utf8_to_utf16	params = {0,0,0,0,0,0,0,0,0};
-	wchar16_t					buffer[4096];
-	wchar16_t *					wch;
-	size_t						nbytes;
-
-	/* utf-8 --> utf-16 */
-	params.src		= (const unsigned char *)arg;
-	params.src_size_in_bytes= ntapi->tt_string_null_offset_multibyte(arg);
-	params.dst		= buffer;
-	params.dst_size_in_bytes= sizeof(buffer);
-
-	if ((status = ntapi->uc_convert_unicode_stream_utf8_to_utf16(&params)))
-		return status;
-
-	/* convenience */
-	for (wch=buffer, nbytes=params.bytes_written; nbytes; ) {
-		if (*wch == '/')
-			*wch = '\\';
-
-		nbytes -= sizeof(wchar16_t);
-		wch++;
-	}
-
-	/* path */
-	path.maxlen = 0;
-	path.strlen = (uint16_t)params.bytes_written;
-	path.buffer = buffer;
-
-	/* oa */
-	oa.len      = sizeof(nt_oa);
-	oa.root_dir = hat;
-	oa.obj_name = &path;
-	oa.obj_attr = 0;
-	oa.sec_desc = 0;
-	oa.sec_qos  = 0;
-
-	/* open */
-	return ntapi->zw_open_file(
-		hfile,
-		NT_SEC_SYNCHRONIZE | NT_FILE_READ_ATTRIBUTES | NT_FILE_READ_DATA,
-		&oa,&iosb,
-		NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE | NT_FILE_SHARE_DELETE,
-		NT_FILE_NON_DIRECTORY_FILE | NT_FILE_SYNCHRONOUS_IO_ALERT);
-}
-
 static int32_t ptyc_cat(
 	struct ptyc_driver_ctx* dctx,
 	void *			hat,
@@ -75,7 +24,7 @@ static int32_t ptyc_cat(
 	uintptr_t	buffer[32768/sizeof(uintptr_t)];
 	char *		ch;
 
-	if ((status = ptyc_open(&hfile,hat,unit)))
+	if ((status = ptyc_open_file(&hfile,hat,unit,true)))
 		return status;
 
 	status = ntapi->zw_read_file(
diff --git a/src/internal/ptycon_driver_impl.h b/src/internal/ptycon_driver_impl.h
index 03f0c9b..67393ff 100644
--- a/src/internal/ptycon_driver_impl.h
+++ b/src/internal/ptycon_driver_impl.h
@@ -61,4 +61,7 @@ static inline struct ptyc_driver_ctx_impl * ptyc_get_driver_ictx(struct ptyc_dri
 	return 0;
 }
 
+int32_t ptyc_open_file(void ** hfile, void * hat, const char * arg, bool fprivate);
+int32_t ptyc_open_dir(void ** hfile, void * hat, const char * arg, bool fprivate);
+
 #endif
diff --git a/src/internal/ptycon_open_impl.c b/src/internal/ptycon_open_impl.c
new file mode 100644
index 0000000..efda8bc
--- /dev/null
+++ b/src/internal/ptycon_open_impl.c
@@ -0,0 +1,78 @@
+/*********************************************************/
+/*  ptycon: a pty-console bridge                         */
+/*  Copyright (C) 2016  Z. Gilboa                        */
+/*  Released under GPLv2 and GPLv3; see COPYING.PTYCON.  */
+/*********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntcon/ntcon.h>
+#include <ntapi/ntapi.h>
+
+#include <ptycon/ptycon.h>
+#include "ptycon_driver_impl.h"
+
+static int32_t ptyc_open(
+	void **		hfile,
+	void *		hat,
+	const char *	arg,
+	uint32_t	options,
+	bool		fprivate)
+{
+	int32_t						status;
+	nt_oa						oa;
+	nt_iosb						iosb;
+	nt_unicode_string				path;
+	nt_unicode_conversion_params_utf8_to_utf16	params = {0,0,0,0,0,0,0,0,0};
+	wchar16_t					buffer[4096];
+	wchar16_t *					wch;
+	size_t						nbytes;
+
+	/* utf-8 --> utf-16 */
+	params.src		= (const unsigned char *)arg;
+	params.src_size_in_bytes= ntapi->tt_string_null_offset_multibyte(arg);
+	params.dst		= buffer;
+	params.dst_size_in_bytes= sizeof(buffer);
+
+	if ((status = ntapi->uc_convert_unicode_stream_utf8_to_utf16(&params)))
+		return status;
+
+	/* convenience */
+	for (wch=buffer, nbytes=params.bytes_written; nbytes; ) {
+		if (*wch == '/')
+			*wch = '\\';
+
+		nbytes -= sizeof(wchar16_t);
+		wch++;
+	}
+
+	/* path */
+	path.maxlen = 0;
+	path.strlen = (uint16_t)params.bytes_written;
+	path.buffer = buffer;
+
+	/* oa */
+	oa.len      = sizeof(nt_oa);
+	oa.root_dir = hat;
+	oa.obj_name = &path;
+	oa.obj_attr = fprivate ? 0 : NT_OBJ_INHERIT;
+	oa.sec_desc = 0;
+	oa.sec_qos  = 0;
+
+	/* open */
+	return ntapi->zw_open_file(
+		hfile,
+		NT_SEC_SYNCHRONIZE | NT_FILE_READ_ATTRIBUTES | NT_FILE_READ_DATA,
+		&oa,&iosb,
+		NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE | NT_FILE_SHARE_DELETE,
+		options | NT_FILE_SYNCHRONOUS_IO_ALERT);
+}
+
+int32_t ptyc_open_file(void ** hfile, void * hat, const char * arg, bool fprivate)
+{
+	return ptyc_open(hfile,hat,arg,NT_FILE_NON_DIRECTORY_FILE,fprivate);
+}
+
+int32_t ptyc_open_dir(void ** hfile, void * hat, const char * arg, bool fprivate)
+{
+	return ptyc_open(hfile,hat,arg,NT_FILE_DIRECTORY_FILE,fprivate);
+}