Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/include/ipc/ipc.h	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -43,6 +43,4 @@
 #include <typedefs.h>
 
-#define IPC_MAX_PHONES  64
-
 struct answerbox;
 struct task;
Index: kernel/generic/include/ipc/ipcrsc.h
===================================================================
--- kernel/generic/include/ipc/ipcrsc.h	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/include/ipc/ipcrsc.h	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -40,5 +40,6 @@
 
 extern call_t *get_call(sysarg_t);
-extern int phone_get(sysarg_t, phone_t **);
+extern phone_t *phone_get_current(int);
+extern phone_t *phone_get(task_t *, int);
 extern int phone_alloc(task_t *);
 extern bool phone_connect(int, answerbox_t *);
Index: kernel/generic/include/kobject/kobject.h
===================================================================
--- kernel/generic/include/kobject/kobject.h	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/include/kobject/kobject.h	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -37,4 +37,5 @@
 
 #include <typedefs.h>
+#include <ipc/ipc.h>
 
 #define MAX_KERNEL_OBJECTS  64
@@ -44,16 +45,22 @@
 typedef enum {
 	KOBJECT_TYPE_INVALID,
-	KOBJECT_TYPE_ALLOCATED
+	KOBJECT_TYPE_ALLOCATED,
+	KOBJECT_TYPE_PHONE
 } kobject_type_t;
 
-typedef struct {
+typedef struct kobject {
 	kobject_type_t type;
+	bool (* can_reclaim)(struct kobject *);
+
 	union {
+		phone_t phone;
 	};
 } kobject_t;
 
-extern kobject_t *kobject_get_local(int, kobject_type_t);
+struct task;
 
-struct task;
+extern void kobject_init(kobject_t *);
+extern kobject_t *kobject_get(struct task *, int, kobject_type_t);
+extern kobject_t *kobject_get_current(int, kobject_type_t);
 extern int kobject_alloc(struct task *);
 extern void kobject_free(struct task *, int);
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/include/proc/task.h	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -105,7 +105,4 @@
 	answerbox_t answerbox;
 
-	/** Sending communication endpoints */
-	phone_t phones[IPC_MAX_PHONES];
-
 	/** Spinlock protecting the active_calls list. */
 	SPINLOCK_DECLARE(active_calls_lock);
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/ipc.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -43,4 +43,5 @@
 #include <synch/waitq.h>
 #include <ipc/ipc.h>
+#include <ipc/ipcrsc.h>
 #include <abi/ipc/methods.h>
 #include <ipc/kbox.h>
@@ -740,8 +741,10 @@
 	 * Locking is needed as there may be connection handshakes in progress.
 	 */
-	for (i = 0; i < IPC_MAX_PHONES; i++) {
-		phone_t *phone = &TASK->phones[i];
-
-		mutex_lock(&phone->lock);	
+	for (i = 0; i < MAX_KERNEL_OBJECTS; i++) {
+		phone_t *phone = phone_get_current(i);
+		if (!phone)
+			continue;
+
+		mutex_lock(&phone->lock);
 		if ((phone->state == IPC_PHONE_HUNGUP) &&
 		    (atomic_get(&phone->active_calls) == 0)) {
@@ -784,5 +787,5 @@
 		
 	/* Got into cleanup */
-	if (i == IPC_MAX_PHONES)
+	if (i == MAX_KERNEL_OBJECTS)
 		return;
 		
@@ -816,6 +819,10 @@
 
 	/* Disconnect all our phones ('ipc_phone_hangup') */
-	for (size_t i = 0; i < IPC_MAX_PHONES; i++)
-		ipc_phone_hangup(&TASK->phones[i]);
+	for (int i = 0; i < MAX_KERNEL_OBJECTS; i++) {
+		phone_t *phone = phone_get_current(i);
+		if (!phone)
+			continue;
+		ipc_phone_hangup(phone);
+	}
 	
 	/* Unsubscribe from any event notifications. */
@@ -903,18 +910,22 @@
 	irq_spinlock_exchange(&tasks_lock, &task->lock);
 	
-	printf("[phone id] [calls] [state\n");
+	printf("[phone cap] [calls] [state\n");
 	
 	size_t i;
-	for (i = 0; i < IPC_MAX_PHONES; i++) {
-		if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) {
+	for (i = 0; i < MAX_KERNEL_OBJECTS; i++) {
+		phone_t *phone = phone_get(task, i);
+		if (!phone)
+			continue;
+
+		if (SYNCH_FAILED(mutex_trylock(&phone->lock))) {
 			printf("%-10zu (mutex busy)\n", i);
 			continue;
 		}
 		
-		if (task->phones[i].state != IPC_PHONE_FREE) {
-			printf("%-10zu %7" PRIun " ", i,
-			    atomic_get(&task->phones[i].active_calls));
+		if (phone->state != IPC_PHONE_FREE) {
+			printf("%-11zu %7" PRIun " ", i,
+			    atomic_get(&phone->active_calls));
 			
-			switch (task->phones[i].state) {
+			switch (phone->state) {
 			case IPC_PHONE_CONNECTING:
 				printf("connecting");
@@ -922,14 +933,12 @@
 			case IPC_PHONE_CONNECTED:
 				printf("connected to %" PRIu64 " (%s)",
-				    task->phones[i].callee->task->taskid,
-				    task->phones[i].callee->task->name);
+				    phone->callee->task->taskid,
+				    phone->callee->task->name);
 				break;
 			case IPC_PHONE_SLAMMED:
-				printf("slammed by %p",
-				    task->phones[i].callee);
+				printf("slammed by %p", phone->callee);
 				break;
 			case IPC_PHONE_HUNGUP:
-				printf("hung up by %p",
-				    task->phones[i].callee);
+				printf("hung up by %p", phone->callee);
 				break;
 			default:
@@ -940,5 +949,5 @@
 		}
 		
-		mutex_unlock(&task->phones[i].lock);
+		mutex_unlock(&phone->lock);
 	}
 	
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -162,96 +162,93 @@
 }
 
-/** Get phone from the current task by ID.
- *
- * @param phoneid Phone ID.
- * @param phone   Place to store pointer to phone.
- *
- * @return EOK on success, EINVAL if ID is invalid.
- *
- */
-int phone_get(sysarg_t phoneid, phone_t **phone)
-{
-	if (phoneid >= IPC_MAX_PHONES)
-		return EINVAL;
-	
-	*phone = &TASK->phones[phoneid];
-	return EOK;
-}
-
-/** Allocate new phone slot in the specified task.
- *
- * @param task Task for which to allocate a new phone.
- *
- * @return New phone handle or -1 if the phone handle limit is
- *         exceeded.
- *
+/** Get phone from the current task by capability.
+ *
+ * @param cap    Phone capability.
+ * @param phone  Place to store pointer to phone.
+ *
+ * @return  Address of the phone kernel object.
+ * @return  NULL if the capability is invalid.
+ *
+ */
+phone_t *phone_get(task_t *task, int cap)
+{
+	kobject_t *kobj = kobject_get(task, cap, KOBJECT_TYPE_PHONE);
+	if (!kobj)
+		return NULL;
+	
+	return &kobj->phone;
+}
+
+phone_t *phone_get_current(int cap)
+{
+	return phone_get(TASK, cap);
+}
+
+static bool phone_can_reclaim(kobject_t *kobj)
+{
+	assert(kobj->type == KOBJECT_TYPE_PHONE);
+
+	return (kobj->phone.state == IPC_PHONE_HUNGUP) &&
+	    (atomic_get(&kobj->phone.active_calls) == 0);
+}
+
+/** Allocate new phone in the specified task.
+ *
+ * @param task  Task for which to allocate a new phone.
+ *
+ * @return  New phone capability.
+ * @return  KOBJECT_INVALID_CAP if a new capability cannot be allocated.
  */
 int phone_alloc(task_t *task)
 {
-	irq_spinlock_lock(&task->lock, true);
-	
-	size_t i;
-	for (i = 0; i < IPC_MAX_PHONES; i++) {
-		phone_t *phone = &task->phones[i];
-
-		if ((phone->state == IPC_PHONE_HUNGUP) &&
-		    (atomic_get(&phone->active_calls) == 0))
-			phone->state = IPC_PHONE_FREE;
-		
-		if (phone->state == IPC_PHONE_FREE) {
-			phone->state = IPC_PHONE_CONNECTING;
-			break;
-		}
+	int cap = kobject_alloc(task);
+	if (cap != KOBJECT_INVALID_CAP) {
+		irq_spinlock_lock(&task->lock, true);
+		kobject_t *kobj = &task->kobject[cap];
+		ipc_phone_init(&kobj->phone, task);
+		kobj->type = KOBJECT_TYPE_PHONE;
+		kobj->can_reclaim = phone_can_reclaim;
+		kobj->phone.state = IPC_PHONE_CONNECTING;
+		irq_spinlock_unlock(&task->lock, true);
 	}
 	
-	irq_spinlock_unlock(&task->lock, true);
-	
-	if (i == IPC_MAX_PHONES)
-		return -1;
-	
-	return i;
-}
-
-/** Mark a phone structure free.
- *
- * @param phone Phone structure to be marked free.
- *
- */
-static void phone_deallocp(phone_t *phone)
-{
+	return cap;
+}
+
+/** Free slot from a disconnected phone.
+ *
+ * All already sent messages will be correctly processed.
+ *
+ * @param phoneid Phone handle of the phone to be freed.
+ *
+ */
+void phone_dealloc(int cap)
+{
+	phone_t *phone = phone_get_current(cap);
+	
+	assert(phone);
 	assert(phone->state == IPC_PHONE_CONNECTING);
-	
-	/* Atomic operation */
-	phone->state = IPC_PHONE_FREE;
-}
-
-/** Free slot from a disconnected phone.
- *
- * All already sent messages will be correctly processed.
- *
- * @param phoneid Phone handle of the phone to be freed.
- *
- */
-void phone_dealloc(int phoneid)
-{
-	phone_deallocp(&TASK->phones[phoneid]);
+
+	kobject_free(TASK, cap);
 }
 
 /** Connect phone to a given answerbox.
  *
- * @param phoneid Phone handle to be connected.
- * @param box     Answerbox to which to connect the phone handle.
- * @return        True if the phone was connected, false otherwise.
- *
- * The procedure _enforces_ that the user first marks the phone
- * busy (e.g. via phone_alloc) and then connects the phone, otherwise
- * race condition may appear.
- *
- */
-bool phone_connect(int phoneid, answerbox_t *box)
-{
-	phone_t *phone = &TASK->phones[phoneid];
-	
+ * @param cap  Phone capability to be connected.
+ * @param box  Answerbox to which to connect the phone capability.
+ * @return     True if the phone was connected, false otherwise.
+ *
+ * The procedure _enforces_ that the user first marks the phone busy (e.g. via
+ * phone_alloc) and then connects the phone, otherwise race condition may
+ * appear.
+ *
+ */
+bool phone_connect(int cap, answerbox_t *box)
+{
+	phone_t *phone = phone_get_current(cap);
+	
+	assert(phone);
 	assert(phone->state == IPC_PHONE_CONNECTING);
+	
 	return ipc_phone_connect(phone, box);
 }
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/kbox.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -206,5 +206,5 @@
  * cleanup code.
  *
- * @return Phone id on success, or negative error code.
+ * @return Phone capability on success, or negative error code.
  *
  */
@@ -236,6 +236,6 @@
 	}
 	
-	int newphid = phone_alloc(TASK);
-	if (newphid < 0) {
+	int cap = phone_alloc(TASK);
+	if (cap < 0) {
 		mutex_unlock(&task->kb.cleanup_lock);
 		return ELIMIT;
@@ -243,9 +243,9 @@
 	
 	/* Connect the newly allocated phone to the kbox */
-	(void) ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);
+	(void) ipc_phone_connect(phone_get_current(cap), &task->kb.box);
 	
 	if (task->kb.thread != NULL) {
 		mutex_unlock(&task->kb.cleanup_lock);
-		return newphid;
+		return cap;
 	}
 	
@@ -263,5 +263,5 @@
 	mutex_unlock(&task->kb.cleanup_lock);
 	
-	return newphid;
+	return cap;
 }
 
Index: kernel/generic/src/ipc/ops/conctmeto.c
===================================================================
--- kernel/generic/src/ipc/ops/conctmeto.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/ops/conctmeto.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -42,13 +42,13 @@
 static int request_preprocess(call_t *call, phone_t *phone)
 {
-	int newphid = phone_alloc(TASK);
+	int cap = phone_alloc(TASK);
 
-	/* Remember the phoneid or the error. */
-	call->priv = newphid;
-	if (newphid < 0)
+	/* Remember the phone capability or the error. */
+	call->priv = cap;
+	if (cap < 0)
 		return ELIMIT;
 		
 	/* Set arg5 for server */
-	IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
+	IPC_SET_ARG5(call->data, (sysarg_t) phone_get_current(cap));
 
 	return EOK;
@@ -74,16 +74,16 @@
 static int answer_process(call_t *answer)
 {
-	int newphid = (int) answer->priv;
+	int cap = (int) answer->priv;
 
 	if (IPC_GET_RETVAL(answer->data)) {
-		if (newphid >= 0) {
+		if (cap >= 0) {
 			/*
 			 * The phone was indeed allocated and now needs
 			 * to be deallocated.
 			 */
-			phone_dealloc(newphid);
+			phone_dealloc(cap);
 		}
 	} else {
-		IPC_SET_ARG5(answer->data, newphid);
+		IPC_SET_ARG5(answer->data, cap);
 	}
 	
Index: kernel/generic/src/ipc/ops/concttome.c
===================================================================
--- kernel/generic/src/ipc/ops/concttome.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/ops/concttome.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -42,7 +42,7 @@
 static int request_process(call_t *call, answerbox_t *box)
 {
-	int phoneid = phone_alloc(TASK);
+	int cap = phone_alloc(TASK);
 
-	IPC_SET_ARG5(call->data, phoneid);
+	IPC_SET_ARG5(call->data, cap);
 	
 	return EOK;
@@ -51,8 +51,8 @@
 static int answer_cleanup(call_t *answer, ipc_data_t *olddata)
 {
-	int phoneid = (int) IPC_GET_ARG5(*olddata);
+	int cap = (int) IPC_GET_ARG5(*olddata);
 
-	if (phoneid >= 0)
-		phone_dealloc(phoneid);
+	if (cap >= 0)
+		phone_dealloc(cap);
 
 	return EOK;
@@ -61,15 +61,15 @@
 static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
 {
-	int phoneid = (int) IPC_GET_ARG5(*olddata);
+	int cap = (int) IPC_GET_ARG5(*olddata);
 
 	if (IPC_GET_RETVAL(answer->data) != EOK) {
 		/* The connection was not accepted */
 		answer_cleanup(answer, olddata);
-	} else if (phoneid >= 0) {
+	} else if (cap >= 0) {
 		/* The connection was accepted */
-		if (phone_connect(phoneid, &answer->sender->answerbox)) {
+		if (phone_connect(cap, &answer->sender->answerbox)) {
 			/* Set 'phone hash' as arg5 of response */
 			IPC_SET_ARG5(answer->data,
-			    (sysarg_t) &TASK->phones[phoneid]);
+			    (sysarg_t) phone_get_current(cap));
 		} else {
 			/* The answerbox is shutting down. */
Index: kernel/generic/src/ipc/ops/connclone.c
===================================================================
--- kernel/generic/src/ipc/ops/connclone.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/ops/connclone.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -61,11 +61,10 @@
 static int request_preprocess(call_t *call, phone_t *phone)
 {
-	phone_t *cloned_phone;
-
-	if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
+	phone_t *cloned_phone = phone_get_current(IPC_GET_ARG1(call->data));
+	if (!cloned_phone)
 		return ENOENT;
-		
+	
 	phones_lock(cloned_phone, phone);
-		
+	
 	if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
 	    phone->state != IPC_PHONE_CONNECTED) {
@@ -73,5 +72,5 @@
 		return EINVAL;
 	}
-		
+	
 	/*
 	 * We can be pretty sure now that both tasks exist and we are
@@ -81,16 +80,16 @@
 	 *
 	 */
-	int newphid = phone_alloc(phone->callee->task);
-	if (newphid < 0) {
+	int cap = phone_alloc(phone->callee->task);
+	if (cap < 0) {
 		phones_unlock(cloned_phone, phone);
 		return ELIMIT;
 	}
-		
-	(void) ipc_phone_connect(&phone->callee->task->phones[newphid],
+	
+	(void) ipc_phone_connect(phone_get(phone->callee->task, cap),
 	    cloned_phone->callee);
 	phones_unlock(cloned_phone, phone);
-		
+	
 	/* Set the new phone for the callee. */
-	IPC_SET_ARG1(call->data, newphid);
+	IPC_SET_ARG1(call->data, cap);
 
 	return EOK;
@@ -99,6 +98,6 @@
 static int answer_cleanup(call_t *answer, ipc_data_t *olddata)
 {
-	int phoneid = (int) IPC_GET_ARG1(*olddata);
-	phone_t *phone = &TASK->phones[phoneid];
+	int cap = (int) IPC_GET_ARG1(*olddata);
+	phone_t *phone = phone_get_current(cap);
 
 	/*
Index: kernel/generic/src/ipc/ops/stchngath.c
===================================================================
--- kernel/generic/src/ipc/ops/stchngath.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/ops/stchngath.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -43,8 +43,8 @@
 static int request_preprocess(call_t *call, phone_t *phone)
 {
-	phone_t *sender_phone;
 	task_t *other_task_s;
 
-	if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
+	phone_t *sender_phone = phone_get_current(IPC_GET_ARG5(call->data));
+	if (!sender_phone)
 		return ENOENT;
 
@@ -75,7 +75,6 @@
 		task_t *other_task_r;
 
-		rc = phone_get(IPC_GET_ARG1(answer->data),
-		    &recipient_phone);
-		if (rc != EOK) {
+		recipient_phone = phone_get_current(IPC_GET_ARG1(answer->data));
+		if (!recipient_phone) {
 			IPC_SET_RETVAL(answer->data, ENOENT);
 			return ENOENT;
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/ipc/sysipc.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -264,7 +264,7 @@
 /** Make a call over IPC and wait for reply.
  *
- * @param phoneid     Phone handle for the call.
- * @param data[inout] Structure with request/reply data.
- * @param priv        Value to be stored in call->priv.
+ * @param phone_cap    Phone capability for the call.
+ * @param data[inout]  Structure with request/reply data.
+ * @param priv         Value to be stored in call->priv.
  *
  * @return EOK on success.
@@ -272,8 +272,8 @@
  *
  */
-int ipc_req_internal(int phoneid, ipc_data_t *data, sysarg_t priv)
-{
-	phone_t *phone;
-	if (phone_get(phoneid, &phone) != EOK)
+int ipc_req_internal(int phone_cap, ipc_data_t *data, sysarg_t priv)
+{
+	phone_t *phone = phone_get_current(phone_cap);
+	if (!phone)
 		return ENOENT;
 	
@@ -350,10 +350,10 @@
  * the generic function sys_ipc_call_async_slow().
  *
- * @param phoneid Phone handle for the call.
- * @param imethod Interface and method of the call.
- * @param arg1    Service-defined payload argument.
- * @param arg2    Service-defined payload argument.
- * @param arg3    Service-defined payload argument.
- * @param arg4    Service-defined payload argument.
+ * @param phone_cap  Phone capability for the call.
+ * @param imethod    Interface and method of the call.
+ * @param arg1       Service-defined payload argument.
+ * @param arg2       Service-defined payload argument.
+ * @param arg3       Service-defined payload argument.
+ * @param arg4       Service-defined payload argument.
  *
  * @return Call hash on success.
@@ -363,9 +363,9 @@
  *
  */
-sysarg_t sys_ipc_call_async_fast(sysarg_t phoneid, sysarg_t imethod,
+sysarg_t sys_ipc_call_async_fast(sysarg_t phone_cap, sysarg_t imethod,
     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
 {
-	phone_t *phone;
-	if (phone_get(phoneid, &phone) != EOK)
+	phone_t *phone = phone_get_current(phone_cap);
+	if (!phone)
 		return IPC_CALLRET_FATAL;
 	
@@ -398,14 +398,14 @@
 /** Make an asynchronous IPC call allowing to transmit the entire payload.
  *
- * @param phoneid Phone handle for the call.
- * @param data    Userspace address of call data with the request.
+ * @param phone_cap  Phone capability for the call.
+ * @param data       Userspace address of call data with the request.
  *
  * @return See sys_ipc_call_async_fast().
  *
  */
-sysarg_t sys_ipc_call_async_slow(sysarg_t phoneid, ipc_data_t *data)
-{
-	phone_t *phone;
-	if (phone_get(phoneid, &phone) != EOK)
+sysarg_t sys_ipc_call_async_slow(sysarg_t phone_cap, ipc_data_t *data)
+{
+	phone_t *phone = phone_get_current(phone_cap);
+	if (!phone)
 		return IPC_CALLRET_FATAL;
 
@@ -435,16 +435,16 @@
  * Common code for both the fast and the slow version.
  *
- * @param callid  Hash of the call to forward.
- * @param phoneid Phone handle to use for forwarding.
- * @param imethod New interface and method to use for the forwarded call.
- * @param arg1    New value of the first argument for the forwarded call.
- * @param arg2    New value of the second argument for the forwarded call.
- * @param arg3    New value of the third argument for the forwarded call.
- * @param arg4    New value of the fourth argument for the forwarded call.
- * @param arg5    New value of the fifth argument for the forwarded call.
- * @param mode    Flags that specify mode of the forward operation.
- * @param slow    If true, arg3, arg4 and arg5 are considered. Otherwise
- *                the function considers only the fast version arguments:
- *                i.e. arg1 and arg2.
+ * @param callid     Hash of the call to forward.
+ * @param phone_cap  Phone capability to use for forwarding.
+ * @param imethod    New interface and method to use for the forwarded call.
+ * @param arg1       New value of the first argument for the forwarded call.
+ * @param arg2       New value of the second argument for the forwarded call.
+ * @param arg3       New value of the third argument for the forwarded call.
+ * @param arg4       New value of the fourth argument for the forwarded call.
+ * @param arg5       New value of the fifth argument for the forwarded call.
+ * @param mode       Flags that specify mode of the forward operation.
+ * @param slow       If true, arg3, arg4 and arg5 are considered. Otherwise
+ *                   the function considers only the fast version arguments:
+ *                   i.e. arg1 and arg2.
  *
  * @return 0 on succes, otherwise an error code.
@@ -453,5 +453,5 @@
  *
  */
-static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t phoneid,
+static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t phone_cap,
     sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
     sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow)
@@ -468,7 +468,7 @@
 	bool after_forward = false;
 	int rc;
-	phone_t *phone;
-	
-	if (phone_get(phoneid, &phone) != EOK) {
+
+	phone_t *phone = phone_get_current(phone_cap);
+	if (!phone) {
 		rc = ENOENT;
 		goto error;
@@ -685,14 +685,13 @@
 /** Hang up a phone.
  *
- * @param Phone handle of the phone to be hung up.
+ * @param phone_cap  Phone capability of the phone to be hung up.
  *
  * @return 0 on success or an error code.
  *
  */
-sysarg_t sys_ipc_hangup(sysarg_t phoneid)
-{
-	phone_t *phone;
-	
-	if (phone_get(phoneid, &phone) != EOK)
+sysarg_t sys_ipc_hangup(sysarg_t phone_cap)
+{
+	phone_t *phone = phone_get_current(phone_cap);
+	if (!phone)
 		return ENOENT;
 	
Index: kernel/generic/src/kobject/kobject.c
===================================================================
--- kernel/generic/src/kobject/kobject.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/kobject/kobject.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -37,11 +37,22 @@
 #include <synch/spinlock.h>
 
-kobject_t *kobject_get_local(int cap, kobject_type_t type)
+void kobject_init(kobject_t *kobj)
+{
+	kobj->type = KOBJECT_TYPE_INVALID;
+	kobj->can_reclaim = NULL;
+}
+
+kobject_t *kobject_get(task_t *task, int cap, kobject_type_t type)
 {
 	if ((cap < 0) || (cap >= MAX_KERNEL_OBJECTS))
 		return NULL;
-	if (TASK->kobject[cap].type != type)
+	if (task->kobject[cap].type != type)
 		return NULL;
-	return &TASK->kobject[cap];
+	return &task->kobject[cap];
+}
+
+kobject_t *kobject_get_current(int cap, kobject_type_t type)
+{
+	return kobject_get(TASK, cap, type);
 }
 
@@ -52,6 +63,11 @@
 	irq_spinlock_lock(&task->lock, true);
 	for (cap = 0; cap < MAX_KERNEL_OBJECTS; cap++) {
-		if (task->kobject[cap].type == KOBJECT_TYPE_INVALID) {
-			task->kobject[cap].type = KOBJECT_TYPE_ALLOCATED;
+		kobject_t *kobj = &task->kobject[cap];
+		if (kobj->type > KOBJECT_TYPE_ALLOCATED) {
+			if (kobj->can_reclaim && kobj->can_reclaim(kobj))
+				kobject_init(kobj);
+		}
+		if (kobj->type == KOBJECT_TYPE_INVALID) {
+			kobj->type = KOBJECT_TYPE_ALLOCATED;
 			irq_spinlock_unlock(&task->lock, true);
 			return cap;
@@ -70,5 +86,5 @@
 
 	irq_spinlock_lock(&task->lock, true);
-	task->kobject[cap].type = KOBJECT_TYPE_INVALID;
+	kobject_init(&task->kobject[cap]);
 	irq_spinlock_unlock(&task->lock, true);
 }
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 7e3826d9e2baf0dbb07a924b5e30821ee79b8f0d)
+++ kernel/generic/src/proc/task.c	(revision 05ffb410774ff0c26682afbcb4c7bfc3e315749b)
@@ -166,11 +166,11 @@
 	
 	list_initialize(&task->threads);
+
+	int cap;
+	for (cap = 0; cap < MAX_KERNEL_OBJECTS; cap++)
+		kobject_init(&task->kobject[cap]);
 	
 	ipc_answerbox_init(&task->answerbox, task);
 	
-	size_t i;
-	for (i = 0; i < IPC_MAX_PHONES; i++)
-		ipc_phone_init(&task->phones[i], task);
-
 	spinlock_initialize(&task->active_calls_lock, "active_calls_lock");
 	list_initialize(&task->active_calls);
@@ -228,6 +228,9 @@
 	
 	if ((ipc_phone_0) &&
-	    (container_check(ipc_phone_0->task->container, task->container)))
-		(void) ipc_phone_connect(&task->phones[0], ipc_phone_0);
+	    (container_check(ipc_phone_0->task->container, task->container))) {
+		int cap = phone_alloc(task);
+		assert(cap == 0);
+		(void) ipc_phone_connect(phone_get(task, 0), ipc_phone_0);
+	}
 	
 	futex_task_init(task);
@@ -611,8 +614,9 @@
 	
 	if (*additional) {
-		size_t i;
-		for (i = 0; i < IPC_MAX_PHONES; i++) {
-			if (task->phones[i].callee)
-				printf(" %zu:%p", i, task->phones[i].callee);
+		int i;
+		for (i = 0; i < MAX_KERNEL_OBJECTS; i++) {
+			phone_t *phone = phone_get(task, i);
+			if (phone && phone->callee)
+				printf(" %d:%p", i, phone->callee);
 		}
 		printf("\n");
