xref: /haiku/src/kits/app/Message.cpp (revision fae7ea18b62865f5e1159e1678c851d3aa1ddce0)
1 /*
2  * Copyright 2005-2014 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz, mmlr@mlotz.ch
7  */
8 
9 
10 #include <Message.h>
11 #include <MessageAdapter.h>
12 #include <MessagePrivate.h>
13 #include <MessageUtils.h>
14 
15 #include <DirectMessageTarget.h>
16 #include <MessengerPrivate.h>
17 #include <TokenSpace.h>
18 #include <util/KMessage.h>
19 
20 #include <Alignment.h>
21 #include <Application.h>
22 #include <AppMisc.h>
23 #include <BlockCache.h>
24 #include <Entry.h>
25 #include <MessageQueue.h>
26 #include <Messenger.h>
27 #include <Path.h>
28 #include <Point.h>
29 #include <Rect.h>
30 #include <String.h>
31 #include <StringList.h>
32 
33 #include <assert.h>
34 #include <ctype.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include "tracing_config.h"
40 	// kernel tracing configuration
41 
42 //#define VERBOSE_DEBUG_OUTPUT
43 #ifdef VERBOSE_DEBUG_OUTPUT
44 #define DEBUG_FUNCTION_ENTER	\
45 	debug_printf("msg thread: %ld; this: %p; header: %p; fields: %p;" \
46 		" data: %p; what: 0x%08lx '%.4s'; line: %d; func: %s\n", \
47 		find_thread(NULL), this, fHeader, fFields, fData, what, (char*)&what, \
48 		__LINE__, __PRETTY_FUNCTION__);
49 
50 #define DEBUG_FUNCTION_ENTER2	\
51 	debug_printf("msg thread: %ld; line: %d: func: %s\n", find_thread(NULL), \
52 		__LINE__, __PRETTY_FUNCTION__);
53 #else
54 #define DEBUG_FUNCTION_ENTER	/* nothing */
55 #define DEBUG_FUNCTION_ENTER2	/* nothing */
56 #endif
57 
58 #if BMESSAGE_TRACING
59 #	define KTRACE(format...)	ktrace_printf(format)
60 #else
61 #	define KTRACE(format...)
62 #endif
63 
64 
65 const char* B_SPECIFIER_ENTRY = "specifiers";
66 const char* B_PROPERTY_ENTRY = "property";
67 const char* B_PROPERTY_NAME_ENTRY = "name";
68 
69 
70 static status_t handle_reply(port_id replyPort, int32* pCode,
71 	bigtime_t timeout, BMessage* reply);
72 
73 
74 extern "C" {
75 	// private os function to set the owning team of an area
76 	status_t _kern_transfer_area(area_id area, void** _address,
77 		uint32 addressSpec, team_id target);
78 }
79 
80 
81 BBlockCache* BMessage::sMsgCache = NULL;
82 port_id BMessage::sReplyPorts[sNumReplyPorts];
83 int32 BMessage::sReplyPortInUse[sNumReplyPorts];
84 
85 
86 template<typename Type>
87 static void
88 print_to_stream_type(uint8* pointer)
89 {
90 	Type* item = (Type*)pointer;
91 	item->PrintToStream();
92 }
93 
94 
95 template<typename Type>
96 static void
97 print_type(const char* format, uint8* pointer)
98 {
99 	Type* item = (Type*)pointer;
100 	printf(format,* item,* item);
101 }
102 
103 
104 template<typename Type>
105 static void
106 print_type3(const char* format, uint8* pointer)
107 {
108 	Type* item = (Type*)pointer;
109 	printf(format, *item, *item, *item);
110 }
111 
112 
113 static status_t
114 handle_reply(port_id replyPort, int32* _code, bigtime_t timeout,
115 	BMessage* reply)
116 {
117 	DEBUG_FUNCTION_ENTER2;
118 	ssize_t size;
119 	do {
120 		size = port_buffer_size_etc(replyPort, B_RELATIVE_TIMEOUT, timeout);
121 	} while (size == B_INTERRUPTED);
122 
123 	if (size < 0)
124 		return size;
125 
126 	status_t result;
127 	char* buffer = (char*)malloc(size);
128 	if (buffer == NULL)
129 		return B_NO_MEMORY;
130 
131 	do {
132 		result = read_port(replyPort, _code, buffer, size);
133 	} while (result == B_INTERRUPTED);
134 
135 	if (result < 0 || *_code != kPortMessageCode) {
136 		free(buffer);
137 		return result < 0 ? result : B_ERROR;
138 	}
139 
140 	result = reply->Unflatten(buffer);
141 	free(buffer);
142 	return result;
143 }
144 
145 
146 //	#pragma mark -
147 
148 
149 BMessage::BMessage()
150 {
151 	DEBUG_FUNCTION_ENTER;
152 	_InitCommon(true);
153 }
154 
155 
156 BMessage::BMessage(BMessage* other)
157 {
158 	DEBUG_FUNCTION_ENTER;
159 	_InitCommon(false);
160 	*this = *other;
161 }
162 
163 
164 BMessage::BMessage(uint32 _what)
165 {
166 	DEBUG_FUNCTION_ENTER;
167 	_InitCommon(true);
168 	fHeader->what = what = _what;
169 }
170 
171 
172 BMessage::BMessage(const BMessage& other)
173 {
174 	DEBUG_FUNCTION_ENTER;
175 	_InitCommon(false);
176 	*this = other;
177 }
178 
179 
180 BMessage::~BMessage()
181 {
182 	DEBUG_FUNCTION_ENTER;
183 	_Clear();
184 }
185 
186 
187 BMessage&
188 BMessage::operator=(const BMessage& other)
189 {
190 	DEBUG_FUNCTION_ENTER;
191 
192 	if (this == &other)
193 		return *this;
194 
195 	_Clear();
196 
197 	fHeader = (message_header*)malloc(sizeof(message_header));
198 	if (fHeader == NULL)
199 		return *this;
200 
201 	if (other.fHeader == NULL)
202 		return *this;
203 
204 	memcpy(fHeader, other.fHeader, sizeof(message_header));
205 
206 	// Clear some header flags inherited from the original message that don't
207 	// apply to the clone.
208 	fHeader->flags &= ~(MESSAGE_FLAG_REPLY_REQUIRED | MESSAGE_FLAG_REPLY_DONE
209 		| MESSAGE_FLAG_IS_REPLY | MESSAGE_FLAG_WAS_DELIVERED
210 		| MESSAGE_FLAG_PASS_BY_AREA);
211 	// Note, that BeOS R5 seems to keep the reply info.
212 
213 	if (fHeader->field_count > 0) {
214 		size_t fieldsSize = fHeader->field_count * sizeof(field_header);
215 		if (other.fFields != NULL)
216 			fFields = (field_header*)malloc(fieldsSize);
217 
218 		if (fFields == NULL) {
219 			fHeader->field_count = 0;
220 			fHeader->data_size = 0;
221 		} else
222 			memcpy(fFields, other.fFields, fieldsSize);
223 	}
224 
225 	if (fHeader->data_size > 0) {
226 		if (other.fData != NULL)
227 			fData = (uint8*)malloc(fHeader->data_size);
228 
229 		if (fData == NULL) {
230 			fHeader->field_count = 0;
231 			free(fFields);
232 			fFields = NULL;
233 		} else
234 			memcpy(fData, other.fData, fHeader->data_size);
235 	}
236 
237 	fHeader->what = what = other.what;
238 	fHeader->message_area = -1;
239 	fFieldsAvailable = 0;
240 	fDataAvailable = 0;
241 
242 	return *this;
243 }
244 
245 
246 void*
247 BMessage::operator new(size_t size)
248 {
249 	DEBUG_FUNCTION_ENTER2;
250 	return sMsgCache->Get(size);
251 }
252 
253 
254 void*
255 BMessage::operator new(size_t size, const std::nothrow_t& noThrow)
256 {
257 	DEBUG_FUNCTION_ENTER2;
258 	return sMsgCache->Get(size);
259 }
260 
261 
262 void*
263 BMessage::operator new(size_t, void* pointer)
264 {
265 	DEBUG_FUNCTION_ENTER2;
266 	return pointer;
267 }
268 
269 
270 void
271 BMessage::operator delete(void* pointer, size_t size)
272 {
273 	DEBUG_FUNCTION_ENTER2;
274 	if (pointer == NULL)
275 		return;
276 	sMsgCache->Save(pointer, size);
277 }
278 
279 
280 bool
281 BMessage::HasSameData(const BMessage& other, bool ignoreFieldOrder,
282 	bool deep) const
283 {
284 	if (this == &other)
285 		return true;
286 
287 	if (fHeader == NULL)
288 		return other.fHeader == NULL;
289 
290 	if (fHeader->field_count != other.fHeader->field_count)
291 		return false;
292 
293 	for (uint32 i = 0; i < fHeader->field_count; i++) {
294 		field_header* field = &fFields[i];
295 		field_header* otherField = NULL;
296 
297 		const char* name = (const char*)fData + field->offset;
298 		if (ignoreFieldOrder) {
299 			if (other._FindField(name, B_ANY_TYPE, &otherField) != B_OK)
300 				return false;
301 		} else {
302 			otherField = &other.fFields[i];
303 			if (otherField->name_length != field->name_length)
304 				return false;
305 
306 			const char* otherName = (const char*)other.fData
307 				+ otherField->offset;
308 			if (strncmp(name, otherName, field->name_length) != 0)
309 				return false;
310 		}
311 
312 		if (otherField->type != field->type
313 			|| otherField->count != field->count) {
314 			return false;
315 		}
316 
317 		uint8* data = fData + field->offset + field->name_length;
318 		uint8* otherData = other.fData + otherField->offset
319 			+ otherField->name_length;
320 
321 		bool needsMemCompare = true;
322 		if (deep && field->type == B_MESSAGE_TYPE) {
323 			BMessage message, otherMessage;
324 			if (message.Unflatten((const char*)data) == B_OK
325 				&& otherMessage.Unflatten((const char*)otherData) == B_OK) {
326 				if (!message.HasSameData(ignoreFieldOrder, deep))
327 					return false;
328 				needsMemCompare = false;
329 			}
330 		}
331 
332 		if (needsMemCompare) {
333 			if (otherField->data_size != field->data_size)
334 				return false;
335 			if (memcmp(data, otherData, field->data_size) != 0)
336 				return false;
337 		}
338 	}
339 
340 	return true;
341 }
342 
343 
344 status_t
345 BMessage::_InitCommon(bool initHeader)
346 {
347 	DEBUG_FUNCTION_ENTER;
348 	what = 0;
349 
350 	fHeader = NULL;
351 	fFields = NULL;
352 	fData = NULL;
353 
354 	fFieldsAvailable = 0;
355 	fDataAvailable = 0;
356 
357 	fOriginal = NULL;
358 	fQueueLink = NULL;
359 
360 	fArchivingPointer = NULL;
361 
362 	if (initHeader)
363 		return _InitHeader();
364 
365 	return B_OK;
366 }
367 
368 
369 status_t
370 BMessage::_InitHeader()
371 {
372 	DEBUG_FUNCTION_ENTER;
373 	if (fHeader == NULL) {
374 		fHeader = (message_header*)malloc(sizeof(message_header));
375 		if (fHeader == NULL)
376 			return B_NO_MEMORY;
377 	}
378 
379 	memset(fHeader, 0, sizeof(message_header) - sizeof(fHeader->hash_table));
380 
381 	fHeader->format = MESSAGE_FORMAT_HAIKU;
382 	fHeader->flags = MESSAGE_FLAG_VALID;
383 	fHeader->what = what;
384 	fHeader->current_specifier = -1;
385 	fHeader->message_area = -1;
386 
387 	fHeader->target = B_NULL_TOKEN;
388 	fHeader->reply_target = B_NULL_TOKEN;
389 	fHeader->reply_port = -1;
390 	fHeader->reply_team = -1;
391 
392 	// initializing the hash table to -1 because 0 is a valid index
393 	fHeader->hash_table_size = MESSAGE_BODY_HASH_TABLE_SIZE;
394 	memset(&fHeader->hash_table, 255, sizeof(fHeader->hash_table));
395 	return B_OK;
396 }
397 
398 
399 status_t
400 BMessage::_Clear()
401 {
402 	DEBUG_FUNCTION_ENTER;
403 	if (fHeader != NULL) {
404 		// We're going to destroy all information of this message. If there's
405 		// still someone waiting for a reply to this message, we have to send
406 		// one now.
407 		if (IsSourceWaiting())
408 			SendReply(B_NO_REPLY);
409 
410 		if (fHeader->message_area >= 0)
411 			_Dereference();
412 
413 		free(fHeader);
414 		fHeader = NULL;
415 	}
416 
417 	free(fFields);
418 	fFields = NULL;
419 	free(fData);
420 	fData = NULL;
421 
422 	fArchivingPointer = NULL;
423 
424 	fFieldsAvailable = 0;
425 	fDataAvailable = 0;
426 
427 	delete fOriginal;
428 	fOriginal = NULL;
429 
430 	return B_OK;
431 }
432 
433 
434 status_t
435 BMessage::GetInfo(type_code typeRequested, int32 index, char** nameFound,
436 	type_code* typeFound, int32* countFound) const
437 {
438 	DEBUG_FUNCTION_ENTER;
439 	if (fHeader == NULL)
440 		return B_NO_INIT;
441 
442 	if (index < 0 || (uint32)index >= fHeader->field_count)
443 		return B_BAD_INDEX;
444 
445 	if (typeRequested == B_ANY_TYPE) {
446 		if (nameFound != NULL)
447 			*nameFound = (char*)fData + fFields[index].offset;
448 		if (typeFound != NULL)
449 			*typeFound = fFields[index].type;
450 		if (countFound != NULL)
451 			*countFound = fFields[index].count;
452 		return B_OK;
453 	}
454 
455 	int32 counter = -1;
456 	field_header* field = fFields;
457 	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
458 		if (field->type == typeRequested)
459 			counter++;
460 
461 		if (counter == index) {
462 			if (nameFound != NULL)
463 				*nameFound = (char*)fData + field->offset;
464 			if (typeFound != NULL)
465 				*typeFound = field->type;
466 			if (countFound != NULL)
467 				*countFound = field->count;
468 			return B_OK;
469 		}
470 	}
471 
472 	if (counter == -1)
473 		return B_BAD_TYPE;
474 
475 	return B_BAD_INDEX;
476 }
477 
478 
479 status_t
480 BMessage::GetInfo(const char* name, type_code* typeFound,
481 	int32* countFound) const
482 {
483 	DEBUG_FUNCTION_ENTER;
484 	if (countFound != NULL)
485 		*countFound = 0;
486 
487 	field_header* field = NULL;
488 	status_t result = _FindField(name, B_ANY_TYPE, &field);
489 	if (result != B_OK)
490 		return result;
491 
492 	if (typeFound != NULL)
493 		*typeFound = field->type;
494 	if (countFound != NULL)
495 		*countFound = field->count;
496 
497 	return B_OK;
498 }
499 
500 
501 status_t
502 BMessage::GetInfo(const char* name, type_code* typeFound, bool* fixedSize)
503 	const
504 {
505 	DEBUG_FUNCTION_ENTER;
506 	field_header* field = NULL;
507 	status_t result = _FindField(name, B_ANY_TYPE, &field);
508 	if (result != B_OK)
509 		return result;
510 
511 	if (typeFound != NULL)
512 		*typeFound = field->type;
513 	if (fixedSize != NULL)
514 		*fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
515 
516 	return B_OK;
517 }
518 
519 
520 status_t
521 BMessage::GetInfo(const char* name, type_code* typeFound, int32* countFound,
522 	bool* fixedSize) const
523 {
524 	DEBUG_FUNCTION_ENTER;
525 	field_header* field = NULL;
526 	status_t result = _FindField(name, B_ANY_TYPE, &field);
527 	if (result != B_OK)
528 		return result;
529 
530 	if (typeFound != NULL)
531 		*typeFound = field->type;
532 	if (countFound != NULL)
533 		*countFound = field->count;
534 	if (fixedSize != NULL)
535 		*fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
536 
537 	return B_OK;
538 }
539 
540 
541 int32
542 BMessage::CountNames(type_code type) const
543 {
544 	DEBUG_FUNCTION_ENTER;
545 	if (fHeader == NULL)
546 		return 0;
547 
548 	if (type == B_ANY_TYPE)
549 		return fHeader->field_count;
550 
551 	int32 count = 0;
552 	field_header* field = fFields;
553 	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
554 		if (field->type == type)
555 			count++;
556 	}
557 
558 	return count;
559 }
560 
561 
562 bool
563 BMessage::IsEmpty() const
564 {
565 	DEBUG_FUNCTION_ENTER;
566 	return fHeader == NULL || fHeader->field_count == 0;
567 }
568 
569 
570 bool
571 BMessage::IsSystem() const
572 {
573 	DEBUG_FUNCTION_ENTER;
574 	char a = char(what >> 24);
575 	char b = char(what >> 16);
576 	char c = char(what >> 8);
577 	char d = char(what);
578 
579 	// The BeBook says:
580 	//		... we've adopted a strict convention for assigning values to all
581 	//		Be-defined constants.  The value assigned will always be formed by
582 	//		combining four characters into a multicharacter constant, with the
583 	//		characters limited to uppercase letters and the underbar
584 	// Between that and what's in AppDefs.h, this algo seems like a safe bet:
585 	if (a == '_' && isupper(b) && isupper(c) && isupper(d))
586 		return true;
587 
588 	return false;
589 }
590 
591 
592 bool
593 BMessage::IsReply() const
594 {
595 	DEBUG_FUNCTION_ENTER;
596 	return fHeader != NULL && (fHeader->flags & MESSAGE_FLAG_IS_REPLY) != 0;
597 }
598 
599 
600 void
601 BMessage::PrintToStream() const
602 {
603 	_PrintToStream("");
604 	printf("}\n");
605 }
606 
607 
608 void
609 BMessage::_PrintToStream(const char* indent) const
610 {
611 	DEBUG_FUNCTION_ENTER;
612 
613 	int32 value = B_BENDIAN_TO_HOST_INT32(what);
614 	printf("BMessage(");
615 	if (isprint(*(char*)&value))
616 		printf("'%.4s'", (char*)&value);
617 	else
618 		printf("0x%" B_PRIx32, what);
619 	printf(") {\n");
620 
621 	if (fHeader == NULL || fFields == NULL || fData == NULL)
622 		return;
623 
624 	field_header* field = fFields;
625 	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
626 		value = B_BENDIAN_TO_HOST_INT32(field->type);
627 		ssize_t size = 0;
628 		if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0 && field->count > 0)
629 			size = field->data_size / field->count;
630 
631 		uint8* pointer = fData + field->offset + field->name_length;
632 		for (uint32 j = 0; j < field->count; j++) {
633 			if (field->count == 1) {
634 				printf("%s        %s = ", indent,
635 					(char*)(fData + field->offset));
636 			} else {
637 				printf("%s        %s[%" B_PRIu32 "] = ", indent,
638 					(char*)(fData + field->offset), j);
639 			}
640 
641 			if ((field->flags & FIELD_FLAG_FIXED_SIZE) == 0) {
642 				size = *(uint32*)pointer;
643 				pointer += sizeof(uint32);
644 			}
645 
646 			switch (field->type) {
647 				case B_RECT_TYPE:
648 					print_to_stream_type<BRect>(pointer);
649 					break;
650 
651 				case B_POINT_TYPE:
652 					print_to_stream_type<BPoint>(pointer);
653 					break;
654 
655 				case B_STRING_TYPE:
656 					printf("string(\"%.*s\", %ld bytes)\n", (int)size,
657 						(char*)pointer, (long)size);
658 					break;
659 
660 				case B_INT8_TYPE:
661 					print_type3<int8>("int8(0x%hx or %d or '%c')\n",
662 						pointer);
663 					break;
664 
665 				case B_UINT8_TYPE:
666 					print_type3<uint8>("uint8(0x%hx or %u or '%c')\n",
667 						pointer);
668 					break;
669 
670 				case B_INT16_TYPE:
671 					print_type<int16>("int16(0x%x or %d)\n", pointer);
672 					break;
673 
674 				case B_UINT16_TYPE:
675 					print_type<uint16>("uint16(0x%x or %u\n", pointer);
676 					break;
677 
678 				case B_INT32_TYPE:
679 					print_type<int32>("int32(0x%lx or %ld)\n", pointer);
680 					break;
681 
682 				case B_UINT32_TYPE:
683 					print_type<uint32>("uint32(0x%lx or %lu\n", pointer);
684 					break;
685 
686 				case B_INT64_TYPE:
687 					print_type<int64>("int64(0x%Lx or %Ld)\n", pointer);
688 					break;
689 
690 				case B_UINT64_TYPE:
691 					print_type<uint64>("uint64(0x%Lx or %Ld\n", pointer);
692 					break;
693 
694 				case B_BOOL_TYPE:
695 					printf("bool(%s)\n", *((bool*)pointer) != 0
696 						? "true" : "false");
697 					break;
698 
699 				case B_FLOAT_TYPE:
700 					print_type<float>("float(%.4f)\n", pointer);
701 					break;
702 
703 				case B_DOUBLE_TYPE:
704 					print_type<double>("double(%.8f)\n", pointer);
705 					break;
706 
707 				case B_REF_TYPE:
708 				{
709 					entry_ref ref;
710 					BPrivate::entry_ref_unflatten(&ref, (char*)pointer, size);
711 
712 					printf("entry_ref(device=%d, directory=%" B_PRIdINO
713 						", name=\"%s\", ", (int)ref.device, ref.directory,
714 						ref.name);
715 
716 					BPath path(&ref);
717 					printf("path=\"%s\")\n", path.Path());
718 					break;
719 				}
720 
721 				case B_MESSAGE_TYPE:
722 				{
723 					char buffer[1024];
724 					snprintf(buffer, sizeof(buffer), "%s        ", indent);
725 
726 					BMessage message;
727 					status_t result = message.Unflatten((const char*)pointer);
728 					if (result != B_OK) {
729 						printf("failed unflatten: %s\n", strerror(result));
730 						break;
731 					}
732 
733 					message._PrintToStream(buffer);
734 					printf("%s        }\n", indent);
735 					break;
736 				}
737 
738 				default:
739 				{
740 					printf("(type = '%.4s')(size = %ld)\n", (char*)&value,
741 						(long)size);
742 					break;
743 				}
744 			}
745 
746 			pointer += size;
747 		}
748 	}
749 }
750 
751 
752 status_t
753 BMessage::Rename(const char* oldEntry, const char* newEntry)
754 {
755 	DEBUG_FUNCTION_ENTER;
756 	if (oldEntry == NULL || newEntry == NULL)
757 		return B_BAD_VALUE;
758 
759 	if (fHeader == NULL)
760 		return B_NO_INIT;
761 
762 	status_t result;
763 	if (fHeader->message_area >= 0) {
764 		result = _CopyForWrite();
765 		if (result != B_OK)
766 			return result;
767 	}
768 
769 	uint32 hash = _HashName(oldEntry) % fHeader->hash_table_size;
770 	int32* nextField = &fHeader->hash_table[hash];
771 
772 	while (*nextField >= 0) {
773 		field_header* field = &fFields[*nextField];
774 
775 		if (strncmp((const char*)(fData + field->offset), oldEntry,
776 			field->name_length) == 0) {
777 			// nextField points to the field for oldEntry, save it and unlink
778 			int32 index = *nextField;
779 			*nextField = field->next_field;
780 			field->next_field = -1;
781 
782 			hash = _HashName(newEntry) % fHeader->hash_table_size;
783 			nextField = &fHeader->hash_table[hash];
784 			while (*nextField >= 0)
785 				nextField = &fFields[*nextField].next_field;
786 			*nextField = index;
787 
788 			int32 newLength = strlen(newEntry) + 1;
789 			result = _ResizeData(field->offset + 1,
790 				newLength - field->name_length);
791 			if (result != B_OK)
792 				return result;
793 
794 			memcpy(fData + field->offset, newEntry, newLength);
795 			field->name_length = newLength;
796 			return B_OK;
797 		}
798 
799 		nextField = &field->next_field;
800 	}
801 
802 	return B_NAME_NOT_FOUND;
803 }
804 
805 
806 bool
807 BMessage::WasDelivered() const
808 {
809 	DEBUG_FUNCTION_ENTER;
810 	return fHeader != NULL
811 		&& (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) != 0;
812 }
813 
814 
815 bool
816 BMessage::IsSourceWaiting() const
817 {
818 	DEBUG_FUNCTION_ENTER;
819 	return fHeader != NULL
820 		&& (fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0
821 		&& (fHeader->flags & MESSAGE_FLAG_REPLY_DONE) == 0;
822 }
823 
824 
825 bool
826 BMessage::IsSourceRemote() const
827 {
828 	DEBUG_FUNCTION_ENTER;
829 	return fHeader != NULL
830 		&& (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) != 0
831 		&& fHeader->reply_team != BPrivate::current_team();
832 }
833 
834 
835 BMessenger
836 BMessage::ReturnAddress() const
837 {
838 	DEBUG_FUNCTION_ENTER;
839 	if (fHeader == NULL || (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
840 		return BMessenger();
841 
842 	BMessenger messenger;
843 	BMessenger::Private(messenger).SetTo(fHeader->reply_team,
844 		fHeader->reply_port, fHeader->reply_target);
845 	return messenger;
846 }
847 
848 
849 const BMessage*
850 BMessage::Previous() const
851 {
852 	DEBUG_FUNCTION_ENTER;
853 	/* ToDo: test if the "_previous_" field is used in R5 */
854 	if (fOriginal == NULL) {
855 		fOriginal = new BMessage();
856 
857 		if (FindMessage("_previous_", fOriginal) != B_OK) {
858 			delete fOriginal;
859 			fOriginal = NULL;
860 		}
861 	}
862 
863 	return fOriginal;
864 }
865 
866 
867 bool
868 BMessage::WasDropped() const
869 {
870 	DEBUG_FUNCTION_ENTER;
871 	return fHeader != NULL
872 		&& (fHeader->flags & MESSAGE_FLAG_WAS_DROPPED) != 0;
873 }
874 
875 
876 BPoint
877 BMessage::DropPoint(BPoint* offset) const
878 {
879 	DEBUG_FUNCTION_ENTER;
880 	if (offset != NULL)
881 		*offset = FindPoint("_drop_offset_");
882 
883 	return FindPoint("_drop_point_");
884 }
885 
886 
887 status_t
888 BMessage::SendReply(uint32 command, BHandler* replyTo)
889 {
890 	DEBUG_FUNCTION_ENTER;
891 	BMessage message(command);
892 	return SendReply(&message, replyTo);
893 }
894 
895 
896 status_t
897 BMessage::SendReply(BMessage* reply, BHandler* replyTo, bigtime_t timeout)
898 {
899 	DEBUG_FUNCTION_ENTER;
900 	BMessenger messenger(replyTo);
901 	return SendReply(reply, messenger, timeout);
902 }
903 
904 
905 status_t
906 BMessage::SendReply(BMessage* reply, BMessenger replyTo, bigtime_t timeout)
907 {
908 	DEBUG_FUNCTION_ENTER;
909 	if (fHeader == NULL)
910 		return B_NO_INIT;
911 
912 	BMessenger messenger;
913 	BMessenger::Private messengerPrivate(messenger);
914 	messengerPrivate.SetTo(fHeader->reply_team, fHeader->reply_port,
915 		fHeader->reply_target);
916 
917 	if ((fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0) {
918 		if ((fHeader->flags & MESSAGE_FLAG_REPLY_DONE) != 0)
919 			return B_DUPLICATE_REPLY;
920 
921 		fHeader->flags |= MESSAGE_FLAG_REPLY_DONE;
922 		reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
923 		status_t result = messenger.SendMessage(reply, replyTo, timeout);
924 		reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
925 
926 		if (result != B_OK) {
927 			if (set_port_owner(messengerPrivate.Port(),
928 				messengerPrivate.Team()) == B_BAD_TEAM_ID) {
929 				delete_port(messengerPrivate.Port());
930 			}
931 		}
932 
933 		return result;
934 	}
935 
936 	// no reply required
937 	if ((fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
938 		return B_BAD_REPLY;
939 
940 	reply->AddMessage("_previous_", this);
941 	reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
942 	status_t result = messenger.SendMessage(reply, replyTo, timeout);
943 	reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
944 	reply->RemoveName("_previous_");
945 	return result;
946 }
947 
948 
949 status_t
950 BMessage::SendReply(uint32 command, BMessage* replyToReply)
951 {
952 	DEBUG_FUNCTION_ENTER;
953 	BMessage message(command);
954 	return SendReply(&message, replyToReply);
955 }
956 
957 
958 status_t
959 BMessage::SendReply(BMessage* reply, BMessage* replyToReply,
960 	bigtime_t sendTimeout, bigtime_t replyTimeout)
961 {
962 	DEBUG_FUNCTION_ENTER;
963 	if (fHeader == NULL)
964 		return B_NO_INIT;
965 
966 	BMessenger messenger;
967 	BMessenger::Private messengerPrivate(messenger);
968 	messengerPrivate.SetTo(fHeader->reply_team, fHeader->reply_port,
969 		fHeader->reply_target);
970 
971 	if ((fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0) {
972 		if ((fHeader->flags & MESSAGE_FLAG_REPLY_DONE) != 0)
973 			return B_DUPLICATE_REPLY;
974 
975 		fHeader->flags |= MESSAGE_FLAG_REPLY_DONE;
976 		reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
977 		status_t result = messenger.SendMessage(reply, replyToReply,
978 			sendTimeout, replyTimeout);
979 		reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
980 
981 		if (result != B_OK) {
982 			if (set_port_owner(messengerPrivate.Port(),
983 				messengerPrivate.Team()) == B_BAD_TEAM_ID) {
984 				delete_port(messengerPrivate.Port());
985 			}
986 		}
987 
988 		return result;
989 	}
990 
991 	// no reply required
992 	if ((fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
993 		return B_BAD_REPLY;
994 
995 	reply->AddMessage("_previous_", this);
996 	reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
997 	status_t result = messenger.SendMessage(reply, replyToReply, sendTimeout,
998 		replyTimeout);
999 	reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
1000 	reply->RemoveName("_previous_");
1001 	return result;
1002 }
1003 
1004 
1005 ssize_t
1006 BMessage::FlattenedSize() const
1007 {
1008 	DEBUG_FUNCTION_ENTER;
1009 	if (fHeader == NULL)
1010 		return B_NO_INIT;
1011 
1012 	return sizeof(message_header) + fHeader->field_count * sizeof(field_header)
1013 		+ fHeader->data_size;
1014 }
1015 
1016 
1017 status_t
1018 BMessage::Flatten(char* buffer, ssize_t size) const
1019 {
1020 	DEBUG_FUNCTION_ENTER;
1021 	if (buffer == NULL || size < 0)
1022 		return B_BAD_VALUE;
1023 
1024 	if (fHeader == NULL)
1025 		return B_NO_INIT;
1026 
1027 	if (size < FlattenedSize())
1028 		return B_BUFFER_OVERFLOW;
1029 
1030 	/* we have to sync the what code as it is a public member */
1031 	fHeader->what = what;
1032 
1033 	memcpy(buffer, fHeader, sizeof(message_header));
1034 	buffer += sizeof(message_header);
1035 
1036 	size_t fieldsSize = fHeader->field_count * sizeof(field_header);
1037 	memcpy(buffer, fFields, fieldsSize);
1038 	buffer += fieldsSize;
1039 
1040 	memcpy(buffer, fData, fHeader->data_size);
1041 
1042 	return B_OK;
1043 }
1044 
1045 
1046 status_t
1047 BMessage::Flatten(BDataIO* stream, ssize_t* size) const
1048 {
1049 	DEBUG_FUNCTION_ENTER;
1050 	if (stream == NULL)
1051 		return B_BAD_VALUE;
1052 
1053 	if (fHeader == NULL)
1054 		return B_NO_INIT;
1055 
1056 	/* we have to sync the what code as it is a public member */
1057 	fHeader->what = what;
1058 
1059 	ssize_t result1 = stream->Write(fHeader, sizeof(message_header));
1060 	if (result1 != sizeof(message_header))
1061 		return result1 < 0 ? result1 : B_ERROR;
1062 
1063 	ssize_t result2 = 0;
1064 	if (fHeader->field_count > 0) {
1065 		ssize_t fieldsSize = fHeader->field_count * sizeof(field_header);
1066 		result2 = stream->Write(fFields, fieldsSize);
1067 		if (result2 != fieldsSize)
1068 			return result2 < 0 ? result2 : B_ERROR;
1069 	}
1070 
1071 	ssize_t result3 = 0;
1072 	if (fHeader->data_size > 0) {
1073 		result3 = stream->Write(fData, fHeader->data_size);
1074 		if (result3 != (ssize_t)fHeader->data_size)
1075 			return result3 < 0 ? result3 : B_ERROR;
1076 	}
1077 
1078 	if (size)
1079 		*size = result1 + result2 + result3;
1080 
1081 	return B_OK;
1082 }
1083 
1084 
1085 /*	The concept of message sending by area:
1086 
1087 	The traditional way of sending a message is to send it by flattening it to
1088 	a buffer, pushing it through a port, reading it into the outputbuffer and
1089 	unflattening it from there (copying the data again). While this works ok
1090 	for small messages it does not make any sense for larger ones and may even
1091 	hit some port capacity limit.
1092 	Often in the life of a BMessage, it will be sent to someone. Almost as
1093 	often the one receiving the message will not need to change the message
1094 	in any way, but uses it "read only" to get information from it. This means
1095 	that all that copying is pretty pointless in the first place since we
1096 	could simply pass the original buffers on.
1097 	It's obviously not exactly as simple as this, since we cannot just use the
1098 	memory of one application in another - but we can share areas with
1099 	eachother.
1100 	Therefore instead of flattening into a buffer, we copy the message data
1101 	into an area, put this information into the message header and only push
1102 	this through the port. The receiving looper then builds a BMessage from
1103 	the header, that only references the data in the area (not copying it),
1104 	allowing read only access to it.
1105 	Only if write access is necessary the message will be copyed from the area
1106 	to its own buffers (like in the unflatten step before).
1107 	The double copying is reduced to a single copy in most cases and we safe
1108 	the slower route of moving the data through a port.
1109 	Additionally we save us the reference counting with the use of areas that
1110 	are reference counted internally. So we don't have to worry about leaving
1111 	an area behind or deleting one that is still in use.
1112 */
1113 
1114 status_t
1115 BMessage::_FlattenToArea(message_header** _header) const
1116 {
1117 	DEBUG_FUNCTION_ENTER;
1118 	if (fHeader == NULL)
1119 		return B_NO_INIT;
1120 
1121 	message_header* header = (message_header*)malloc(sizeof(message_header));
1122 	if (header == NULL)
1123 		return B_NO_MEMORY;
1124 
1125 	memcpy(header, fHeader, sizeof(message_header));
1126 
1127 	header->what = what;
1128 	header->message_area = -1;
1129 	*_header = header;
1130 
1131 	if (header->field_count == 0 && header->data_size == 0)
1132 		return B_OK;
1133 
1134 	char* address = NULL;
1135 	size_t fieldsSize = header->field_count * sizeof(field_header);
1136 	size_t size = fieldsSize + header->data_size;
1137 	size = (size + B_PAGE_SIZE) & ~(B_PAGE_SIZE - 1);
1138 	area_id area = create_area("BMessage data", (void**)&address,
1139 		B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1140 
1141 	if (area < 0) {
1142 		free(header);
1143 		*_header = NULL;
1144 		return area;
1145 	}
1146 
1147 	memcpy(address, fFields, fieldsSize);
1148 	memcpy(address + fieldsSize, fData, fHeader->data_size);
1149 	header->flags |= MESSAGE_FLAG_PASS_BY_AREA;
1150 	header->message_area = area;
1151 	return B_OK;
1152 }
1153 
1154 
1155 status_t
1156 BMessage::_Reference()
1157 {
1158 	DEBUG_FUNCTION_ENTER;
1159 	if (fHeader == NULL)
1160 		return B_NO_INIT;
1161 
1162 	fHeader->flags &= ~MESSAGE_FLAG_PASS_BY_AREA;
1163 
1164 	/* if there is no data at all we don't need the area */
1165 	if (fHeader->field_count == 0 && fHeader->data_size == 0)
1166 		return B_OK;
1167 
1168 	area_info areaInfo;
1169 	status_t result = get_area_info(fHeader->message_area, &areaInfo);
1170 	if (result != B_OK)
1171 		return result;
1172 
1173 	if (areaInfo.team != BPrivate::current_team())
1174 		return B_BAD_VALUE;
1175 
1176 	set_area_protection(fHeader->message_area, B_READ_AREA);
1177 
1178 	uint8* address = (uint8*)areaInfo.address;
1179 
1180 	fFields = (field_header*)address;
1181 	fData = address + fHeader->field_count * sizeof(field_header);
1182 	return B_OK;
1183 }
1184 
1185 
1186 status_t
1187 BMessage::_Dereference()
1188 {
1189 	DEBUG_FUNCTION_ENTER;
1190 	if (fHeader == NULL)
1191 		return B_NO_INIT;
1192 
1193 	delete_area(fHeader->message_area);
1194 	fHeader->message_area = -1;
1195 	fFields = NULL;
1196 	fData = NULL;
1197 	return B_OK;
1198 }
1199 
1200 
1201 status_t
1202 BMessage::_CopyForWrite()
1203 {
1204 	DEBUG_FUNCTION_ENTER;
1205 	if (fHeader == NULL)
1206 		return B_NO_INIT;
1207 
1208 	field_header* newFields = NULL;
1209 	uint8* newData = NULL;
1210 
1211 	if (fHeader->field_count > 0) {
1212 		size_t fieldsSize = fHeader->field_count * sizeof(field_header);
1213 		newFields = (field_header*)malloc(fieldsSize);
1214 		if (newFields == NULL)
1215 			return B_NO_MEMORY;
1216 
1217 		memcpy(newFields, fFields, fieldsSize);
1218 	}
1219 
1220 	if (fHeader->data_size > 0) {
1221 		newData = (uint8*)malloc(fHeader->data_size);
1222 		if (newData == NULL) {
1223 			free(newFields);
1224 			return B_NO_MEMORY;
1225 		}
1226 
1227 		memcpy(newData, fData, fHeader->data_size);
1228 	}
1229 
1230 	_Dereference();
1231 
1232 	fFieldsAvailable = 0;
1233 	fDataAvailable = 0;
1234 
1235 	fFields = newFields;
1236 	fData = newData;
1237 	return B_OK;
1238 }
1239 
1240 
1241 status_t
1242 BMessage::_ValidateMessage()
1243 {
1244 	DEBUG_FUNCTION_ENTER;
1245 	if (fHeader == NULL)
1246 		return B_NO_INIT;
1247 
1248 	if (fHeader->field_count == 0)
1249 		return B_OK;
1250 
1251 	if (fFields == NULL)
1252 		return B_NO_INIT;
1253 
1254 	for (uint32 i = 0; i < fHeader->field_count; i++) {
1255 		field_header* field = &fFields[i];
1256 		if ((field->next_field >= 0
1257 				&& (uint32)field->next_field > fHeader->field_count)
1258 			|| (field->offset + field->name_length + field->data_size
1259 				> fHeader->data_size)) {
1260 			// the message is corrupt
1261 			MakeEmpty();
1262 			return B_BAD_VALUE;
1263 		}
1264 	}
1265 
1266 	return B_OK;
1267 }
1268 
1269 
1270 status_t
1271 BMessage::Unflatten(const char* flatBuffer)
1272 {
1273 	DEBUG_FUNCTION_ENTER;
1274 	if (flatBuffer == NULL)
1275 		return B_BAD_VALUE;
1276 
1277 	uint32 format = *(uint32*)flatBuffer;
1278 	if (format != MESSAGE_FORMAT_HAIKU)
1279 		return BPrivate::MessageAdapter::Unflatten(format, this, flatBuffer);
1280 
1281 	// native message unflattening
1282 
1283 	_Clear();
1284 
1285 	fHeader = (message_header*)malloc(sizeof(message_header));
1286 	if (fHeader == NULL)
1287 		return B_NO_MEMORY;
1288 
1289 	memcpy(fHeader, flatBuffer, sizeof(message_header));
1290 	flatBuffer += sizeof(message_header);
1291 
1292 	if (fHeader->format != MESSAGE_FORMAT_HAIKU
1293 		|| (fHeader->flags & MESSAGE_FLAG_VALID) == 0) {
1294 		_InitHeader();
1295 		return B_BAD_VALUE;
1296 	}
1297 
1298 	what = fHeader->what;
1299 
1300 	if ((fHeader->flags & MESSAGE_FLAG_PASS_BY_AREA) != 0
1301 		&& fHeader->message_area >= 0) {
1302 		status_t result = _Reference();
1303 		if (result != B_OK) {
1304 			_InitHeader();
1305 			return result;
1306 		}
1307 	} else {
1308 		fHeader->message_area = -1;
1309 
1310 		if (fHeader->field_count > 0) {
1311 			size_t fieldsSize = fHeader->field_count * sizeof(field_header);
1312 			fFields = (field_header*)malloc(fieldsSize);
1313 			if (fFields == NULL) {
1314 				_InitHeader();
1315 				return B_NO_MEMORY;
1316 			}
1317 
1318 			memcpy(fFields, flatBuffer, fieldsSize);
1319 			flatBuffer += fieldsSize;
1320 		}
1321 
1322 		if (fHeader->data_size > 0) {
1323 			fData = (uint8*)malloc(fHeader->data_size);
1324 			if (fData == NULL) {
1325 				free(fFields);
1326 				fFields = NULL;
1327 				_InitHeader();
1328 				return B_NO_MEMORY;
1329 			}
1330 
1331 			memcpy(fData, flatBuffer, fHeader->data_size);
1332 		}
1333 	}
1334 
1335 	return _ValidateMessage();
1336 }
1337 
1338 
1339 status_t
1340 BMessage::Unflatten(BDataIO* stream)
1341 {
1342 	DEBUG_FUNCTION_ENTER;
1343 	if (stream == NULL)
1344 		return B_BAD_VALUE;
1345 
1346 	uint32 format = 0;
1347 	stream->Read(&format, sizeof(uint32));
1348 	if (format != MESSAGE_FORMAT_HAIKU)
1349 		return BPrivate::MessageAdapter::Unflatten(format, this, stream);
1350 
1351 	// native message unflattening
1352 
1353 	_Clear();
1354 
1355 	fHeader = (message_header*)malloc(sizeof(message_header));
1356 	if (fHeader == NULL)
1357 		return B_NO_MEMORY;
1358 
1359 	fHeader->format = format;
1360 	uint8* header = (uint8*)fHeader;
1361 	ssize_t result = stream->Read(header + sizeof(uint32),
1362 		sizeof(message_header) - sizeof(uint32));
1363 	if (result != sizeof(message_header) - sizeof(uint32)
1364 		|| (fHeader->flags & MESSAGE_FLAG_VALID) == 0) {
1365 		_InitHeader();
1366 		return result < 0 ? result : B_BAD_VALUE;
1367 	}
1368 
1369 	what = fHeader->what;
1370 
1371 	fHeader->message_area = -1;
1372 
1373 	if (fHeader->field_count > 0) {
1374 		ssize_t fieldsSize = fHeader->field_count * sizeof(field_header);
1375 		fFields = (field_header*)malloc(fieldsSize);
1376 		if (fFields == NULL) {
1377 			_InitHeader();
1378 			return B_NO_MEMORY;
1379 		}
1380 
1381 		result = stream->Read(fFields, fieldsSize);
1382 		if (result != fieldsSize)
1383 			return result < 0 ? result : B_BAD_VALUE;
1384 	}
1385 
1386 	if (fHeader->data_size > 0) {
1387 		fData = (uint8*)malloc(fHeader->data_size);
1388 		if (fData == NULL) {
1389 			free(fFields);
1390 			fFields = NULL;
1391 			_InitHeader();
1392 			return B_NO_MEMORY;
1393 		}
1394 
1395 		result = stream->Read(fData, fHeader->data_size);
1396 		if (result != (ssize_t)fHeader->data_size)
1397 			return result < 0 ? result : B_BAD_VALUE;
1398 	}
1399 
1400 	return _ValidateMessage();
1401 }
1402 
1403 
1404 status_t
1405 BMessage::AddSpecifier(const char* property)
1406 {
1407 	DEBUG_FUNCTION_ENTER;
1408 	BMessage message(B_DIRECT_SPECIFIER);
1409 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1410 	if (result != B_OK)
1411 		return result;
1412 
1413 	return AddSpecifier(&message);
1414 }
1415 
1416 
1417 status_t
1418 BMessage::AddSpecifier(const char* property, int32 index)
1419 {
1420 	DEBUG_FUNCTION_ENTER;
1421 	BMessage message(B_INDEX_SPECIFIER);
1422 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1423 	if (result != B_OK)
1424 		return result;
1425 
1426 	result = message.AddInt32("index", index);
1427 	if (result != B_OK)
1428 		return result;
1429 
1430 	return AddSpecifier(&message);
1431 }
1432 
1433 
1434 status_t
1435 BMessage::AddSpecifier(const char* property, int32 index, int32 range)
1436 {
1437 	DEBUG_FUNCTION_ENTER;
1438 	if (range < 0)
1439 		return B_BAD_VALUE;
1440 
1441 	BMessage message(B_RANGE_SPECIFIER);
1442 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1443 	if (result != B_OK)
1444 		return result;
1445 
1446 	result = message.AddInt32("index", index);
1447 	if (result != B_OK)
1448 		return result;
1449 
1450 	result = message.AddInt32("range", range);
1451 	if (result != B_OK)
1452 		return result;
1453 
1454 	return AddSpecifier(&message);
1455 }
1456 
1457 
1458 status_t
1459 BMessage::AddSpecifier(const char* property, const char* name)
1460 {
1461 	DEBUG_FUNCTION_ENTER;
1462 	BMessage message(B_NAME_SPECIFIER);
1463 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1464 	if (result != B_OK)
1465 		return result;
1466 
1467 	result = message.AddString(B_PROPERTY_NAME_ENTRY, name);
1468 	if (result != B_OK)
1469 		return result;
1470 
1471 	return AddSpecifier(&message);
1472 }
1473 
1474 
1475 status_t
1476 BMessage::AddSpecifier(const BMessage* specifier)
1477 {
1478 	DEBUG_FUNCTION_ENTER;
1479 	status_t result = AddMessage(B_SPECIFIER_ENTRY, specifier);
1480 	if (result != B_OK)
1481 		return result;
1482 
1483 	fHeader->current_specifier++;
1484 	fHeader->flags |= MESSAGE_FLAG_HAS_SPECIFIERS;
1485 	return B_OK;
1486 }
1487 
1488 
1489 status_t
1490 BMessage::SetCurrentSpecifier(int32 index)
1491 {
1492 	DEBUG_FUNCTION_ENTER;
1493 	if (index < 0)
1494 		return B_BAD_INDEX;
1495 
1496 	type_code type;
1497 	int32 count;
1498 	status_t result = GetInfo(B_SPECIFIER_ENTRY, &type, &count);
1499 	if (result != B_OK)
1500 		return result;
1501 
1502 	if (index > count)
1503 		return B_BAD_INDEX;
1504 
1505 	fHeader->current_specifier = index;
1506 	return B_OK;
1507 }
1508 
1509 
1510 status_t
1511 BMessage::GetCurrentSpecifier(int32* index, BMessage* specifier, int32* _what,
1512 	const char** property) const
1513 {
1514 	DEBUG_FUNCTION_ENTER;
1515 	if (fHeader == NULL)
1516 		return B_NO_INIT;
1517 
1518 	if (index != NULL)
1519 		*index = fHeader->current_specifier;
1520 
1521 	if (fHeader->current_specifier < 0
1522 		|| (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
1523 		return B_BAD_SCRIPT_SYNTAX;
1524 
1525 	if (specifier) {
1526 		if (FindMessage(B_SPECIFIER_ENTRY, fHeader->current_specifier,
1527 			specifier) != B_OK)
1528 			return B_BAD_SCRIPT_SYNTAX;
1529 
1530 		if (_what != NULL)
1531 			*_what = specifier->what;
1532 
1533 		if (property) {
1534 			if (specifier->FindString(B_PROPERTY_ENTRY, property) != B_OK)
1535 				return B_BAD_SCRIPT_SYNTAX;
1536 		}
1537 	}
1538 
1539 	return B_OK;
1540 }
1541 
1542 
1543 bool
1544 BMessage::HasSpecifiers() const
1545 {
1546 	DEBUG_FUNCTION_ENTER;
1547 	return fHeader != NULL
1548 		&& (fHeader->flags & MESSAGE_FLAG_HAS_SPECIFIERS) != 0;
1549 }
1550 
1551 
1552 status_t
1553 BMessage::PopSpecifier()
1554 {
1555 	DEBUG_FUNCTION_ENTER;
1556 	if (fHeader == NULL)
1557 		return B_NO_INIT;
1558 
1559 	if (fHeader->current_specifier < 0 ||
1560 		(fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
1561 		return B_BAD_VALUE;
1562 
1563 	if (fHeader->current_specifier >= 0)
1564 		fHeader->current_specifier--;
1565 
1566 	return B_OK;
1567 }
1568 
1569 
1570 status_t
1571 BMessage::_ResizeData(uint32 offset, int32 change)
1572 {
1573 	if (change == 0)
1574 		return B_OK;
1575 
1576 	/* optimize for the most usual case: appending data */
1577 	if (offset < fHeader->data_size) {
1578 		field_header* field = fFields;
1579 		for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
1580 			if (field->offset >= offset)
1581 				field->offset += change;
1582 		}
1583 	}
1584 
1585 	if (change > 0) {
1586 		if (fDataAvailable >= (uint32)change) {
1587 			if (offset < fHeader->data_size) {
1588 				memmove(fData + offset + change, fData + offset,
1589 					fHeader->data_size - offset);
1590 			}
1591 
1592 			fDataAvailable -= change;
1593 			fHeader->data_size += change;
1594 			return B_OK;
1595 		}
1596 
1597 		size_t size = fHeader->data_size * 2;
1598 		size = min_c(size, fHeader->data_size + MAX_DATA_PREALLOCATION);
1599 		size = max_c(size, fHeader->data_size + change);
1600 
1601 		uint8* newData = (uint8*)realloc(fData, size);
1602 		if (size > 0 && newData == NULL)
1603 			return B_NO_MEMORY;
1604 
1605 		fData = newData;
1606 		if (offset < fHeader->data_size) {
1607 			memmove(fData + offset + change, fData + offset,
1608 				fHeader->data_size - offset);
1609 		}
1610 
1611 		fHeader->data_size += change;
1612 		fDataAvailable = size - fHeader->data_size;
1613 	} else {
1614 		ssize_t length = fHeader->data_size - offset + change;
1615 		if (length > 0)
1616 			memmove(fData + offset, fData + offset - change, length);
1617 
1618 		// change is negative
1619 		fHeader->data_size += change;
1620 		fDataAvailable -= change;
1621 
1622 		if (fDataAvailable > MAX_DATA_PREALLOCATION) {
1623 			ssize_t available = MAX_DATA_PREALLOCATION / 2;
1624 			ssize_t size = fHeader->data_size + available;
1625 			uint8* newData = (uint8*)realloc(fData, size);
1626 			if (size > 0 && newData == NULL) {
1627 				// this is strange, but not really fatal
1628 				return B_OK;
1629 			}
1630 
1631 			fData = newData;
1632 			fDataAvailable = available;
1633 		}
1634 	}
1635 
1636 	return B_OK;
1637 }
1638 
1639 
1640 uint32
1641 BMessage::_HashName(const char* name) const
1642 {
1643 	char ch;
1644 	uint32 result = 0;
1645 
1646 	while ((ch = *name++) != 0) {
1647 		result = (result << 7) ^ (result >> 24);
1648 		result ^= ch;
1649 	}
1650 
1651 	result ^= result << 12;
1652 	return result;
1653 }
1654 
1655 
1656 status_t
1657 BMessage::_FindField(const char* name, type_code type, field_header** result)
1658 	const
1659 {
1660 	if (name == NULL)
1661 		return B_BAD_VALUE;
1662 
1663 	if (fHeader == NULL)
1664 		return B_NO_INIT;
1665 
1666 	if (fHeader->field_count == 0 || fFields == NULL || fData == NULL)
1667 		return B_NAME_NOT_FOUND;
1668 
1669 	uint32 hash = _HashName(name) % fHeader->hash_table_size;
1670 	int32 nextField = fHeader->hash_table[hash];
1671 
1672 	while (nextField >= 0) {
1673 		field_header* field = &fFields[nextField];
1674 		if ((field->flags & FIELD_FLAG_VALID) == 0)
1675 			break;
1676 
1677 		if (strncmp((const char*)(fData + field->offset), name,
1678 			field->name_length) == 0) {
1679 			if (type != B_ANY_TYPE && field->type != type)
1680 				return B_BAD_TYPE;
1681 
1682 			*result = field;
1683 			return B_OK;
1684 		}
1685 
1686 		nextField = field->next_field;
1687 	}
1688 
1689 	return B_NAME_NOT_FOUND;
1690 }
1691 
1692 
1693 status_t
1694 BMessage::_AddField(const char* name, type_code type, bool isFixedSize,
1695 	field_header** result)
1696 {
1697 	if (fHeader == NULL)
1698 		return B_NO_INIT;
1699 
1700 	if (fFieldsAvailable <= 0) {
1701 		uint32 count = fHeader->field_count * 2 + 1;
1702 		count = min_c(count, fHeader->field_count + MAX_FIELD_PREALLOCATION);
1703 
1704 		field_header* newFields = (field_header*)realloc(fFields,
1705 			count * sizeof(field_header));
1706 		if (count > 0 && newFields == NULL)
1707 			return B_NO_MEMORY;
1708 
1709 		fFields = newFields;
1710 		fFieldsAvailable = count - fHeader->field_count;
1711 	}
1712 
1713 	uint32 hash = _HashName(name) % fHeader->hash_table_size;
1714 	int32* nextField = &fHeader->hash_table[hash];
1715 	while (*nextField >= 0)
1716 		nextField = &fFields[*nextField].next_field;
1717 	*nextField = fHeader->field_count;
1718 
1719 	field_header* field = &fFields[fHeader->field_count];
1720 	field->type = type;
1721 	field->count = 0;
1722 	field->data_size = 0;
1723 	field->next_field = -1;
1724 	field->offset = fHeader->data_size;
1725 	field->name_length = strlen(name) + 1;
1726 	status_t status = _ResizeData(field->offset, field->name_length);
1727 	if (status != B_OK)
1728 		return status;
1729 
1730 	memcpy(fData + field->offset, name, field->name_length);
1731 	field->flags = FIELD_FLAG_VALID;
1732 	if (isFixedSize)
1733 		field->flags |= FIELD_FLAG_FIXED_SIZE;
1734 
1735 	fFieldsAvailable--;
1736 	fHeader->field_count++;
1737 	*result = field;
1738 	return B_OK;
1739 }
1740 
1741 
1742 status_t
1743 BMessage::_RemoveField(field_header* field)
1744 {
1745 	status_t result = _ResizeData(field->offset, -(field->data_size
1746 		+ field->name_length));
1747 	if (result != B_OK)
1748 		return result;
1749 
1750 	int32 index = ((uint8*)field - (uint8*)fFields) / sizeof(field_header);
1751 	int32 nextField = field->next_field;
1752 	if (nextField > index)
1753 		nextField--;
1754 
1755 	int32* value = fHeader->hash_table;
1756 	for (uint32 i = 0; i < fHeader->hash_table_size; i++, value++) {
1757 		if (*value > index)
1758 			*value -= 1;
1759 		else if (*value == index)
1760 			*value = nextField;
1761 	}
1762 
1763 	field_header* other = fFields;
1764 	for (uint32 i = 0; i < fHeader->field_count; i++, other++) {
1765 		if (other->next_field > index)
1766 			other->next_field--;
1767 		else if (other->next_field == index)
1768 			other->next_field = nextField;
1769 	}
1770 
1771 	size_t size = (fHeader->field_count - index - 1) * sizeof(field_header);
1772 	memmove(fFields + index, fFields + index + 1, size);
1773 	fHeader->field_count--;
1774 	fFieldsAvailable++;
1775 
1776 	if (fFieldsAvailable > MAX_FIELD_PREALLOCATION) {
1777 		ssize_t available = MAX_FIELD_PREALLOCATION / 2;
1778 		size = (fHeader->field_count + available) * sizeof(field_header);
1779 		field_header* newFields = (field_header*)realloc(fFields, size);
1780 		if (size > 0 && newFields == NULL) {
1781 			// this is strange, but not really fatal
1782 			return B_OK;
1783 		}
1784 
1785 		fFields = newFields;
1786 		fFieldsAvailable = available;
1787 	}
1788 
1789 	return B_OK;
1790 }
1791 
1792 
1793 status_t
1794 BMessage::AddData(const char* name, type_code type, const void* data,
1795 	ssize_t numBytes, bool isFixedSize, int32 count)
1796 {
1797 	// Note that the "count" argument is only a hint at how many items
1798 	// the caller expects to add to this field. Since we do no item pre-
1799 	// allocation, we ignore this argument.
1800 	DEBUG_FUNCTION_ENTER;
1801 	if (numBytes <= 0 || data == NULL)
1802 		return B_BAD_VALUE;
1803 
1804 	if (fHeader == NULL)
1805 		return B_NO_INIT;
1806 
1807 	status_t result;
1808 	if (fHeader->message_area >= 0) {
1809 		result = _CopyForWrite();
1810 		if (result != B_OK)
1811 			return result;
1812 	}
1813 
1814 	field_header* field = NULL;
1815 	result = _FindField(name, type, &field);
1816 	if (result == B_NAME_NOT_FOUND)
1817 		result = _AddField(name, type, isFixedSize, &field);
1818 
1819 	if (result != B_OK)
1820 		return result;
1821 
1822 	if (field == NULL)
1823 		return B_ERROR;
1824 
1825 	uint32 offset = field->offset + field->name_length + field->data_size;
1826 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
1827 		if (field->count) {
1828 			ssize_t size = field->data_size / field->count;
1829 			if (size != numBytes)
1830 				return B_BAD_VALUE;
1831 		}
1832 
1833 		result = _ResizeData(offset, numBytes);
1834 		if (result != B_OK) {
1835 			if (field->count == 0)
1836 				_RemoveField(field);
1837 			return result;
1838 		}
1839 
1840 		memcpy(fData + offset, data, numBytes);
1841 		field->data_size += numBytes;
1842 	} else {
1843 		int32 change = numBytes + sizeof(uint32);
1844 		result = _ResizeData(offset, change);
1845 		if (result != B_OK) {
1846 			if (field->count == 0)
1847 				_RemoveField(field);
1848 			return result;
1849 		}
1850 
1851 		uint32 size = (uint32)numBytes;
1852 		memcpy(fData + offset, &size, sizeof(uint32));
1853 		memcpy(fData + offset + sizeof(uint32), data, size);
1854 		field->data_size += change;
1855 	}
1856 
1857 	field->count++;
1858 	return B_OK;
1859 }
1860 
1861 
1862 status_t
1863 BMessage::RemoveData(const char* name, int32 index)
1864 {
1865 	DEBUG_FUNCTION_ENTER;
1866 	if (index < 0)
1867 		return B_BAD_INDEX;
1868 
1869 	if (fHeader == NULL)
1870 		return B_NO_INIT;
1871 
1872 	status_t result;
1873 	if (fHeader->message_area >= 0) {
1874 		result = _CopyForWrite();
1875 		if (result != B_OK)
1876 			return result;
1877 	}
1878 
1879 	field_header* field = NULL;
1880 	result = _FindField(name, B_ANY_TYPE, &field);
1881 	if (result != B_OK)
1882 		return result;
1883 
1884 	if ((uint32)index >= field->count)
1885 		return B_BAD_INDEX;
1886 
1887 	if (field->count == 1)
1888 		return _RemoveField(field);
1889 
1890 	uint32 offset = field->offset + field->name_length;
1891 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
1892 		ssize_t size = field->data_size / field->count;
1893 		result = _ResizeData(offset + index * size, -size);
1894 		if (result != B_OK)
1895 			return result;
1896 
1897 		field->data_size -= size;
1898 	} else {
1899 		uint8* pointer = fData + offset;
1900 		for (int32 i = 0; i < index; i++) {
1901 			offset += *(uint32*)pointer + sizeof(uint32);
1902 			pointer = fData + offset;
1903 		}
1904 
1905 		size_t currentSize = *(uint32*)pointer + sizeof(uint32);
1906 		result = _ResizeData(offset, -currentSize);
1907 		if (result != B_OK)
1908 			return result;
1909 
1910 		field->data_size -= currentSize;
1911 	}
1912 
1913 	field->count--;
1914 	return B_OK;
1915 }
1916 
1917 
1918 status_t
1919 BMessage::RemoveName(const char* name)
1920 {
1921 	DEBUG_FUNCTION_ENTER;
1922 	if (fHeader == NULL)
1923 		return B_NO_INIT;
1924 
1925 	status_t result;
1926 	if (fHeader->message_area >= 0) {
1927 		result = _CopyForWrite();
1928 		if (result != B_OK)
1929 			return result;
1930 	}
1931 
1932 	field_header* field = NULL;
1933 	result = _FindField(name, B_ANY_TYPE, &field);
1934 	if (result != B_OK)
1935 		return result;
1936 
1937 	return _RemoveField(field);
1938 }
1939 
1940 
1941 status_t
1942 BMessage::MakeEmpty()
1943 {
1944 	DEBUG_FUNCTION_ENTER;
1945 	_Clear();
1946 	return _InitHeader();
1947 }
1948 
1949 
1950 status_t
1951 BMessage::FindData(const char* name, type_code type, int32 index,
1952 	const void** data, ssize_t* numBytes) const
1953 {
1954 	DEBUG_FUNCTION_ENTER;
1955 	if (data == NULL)
1956 		return B_BAD_VALUE;
1957 
1958 	*data = NULL;
1959 	field_header* field = NULL;
1960 	status_t result = _FindField(name, type, &field);
1961 	if (result != B_OK)
1962 		return result;
1963 
1964 	if (index < 0 || (uint32)index >= field->count)
1965 		return B_BAD_INDEX;
1966 
1967 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
1968 		size_t bytes = field->data_size / field->count;
1969 		*data = fData + field->offset + field->name_length + index * bytes;
1970 		if (numBytes != NULL)
1971 			*numBytes = bytes;
1972 	} else {
1973 		uint8* pointer = fData + field->offset + field->name_length;
1974 		for (int32 i = 0; i < index; i++)
1975 			pointer += *(uint32*)pointer + sizeof(uint32);
1976 
1977 		*data = pointer + sizeof(uint32);
1978 		if (numBytes != NULL)
1979 			*numBytes = *(uint32*)pointer;
1980 	}
1981 
1982 	return B_OK;
1983 }
1984 
1985 
1986 status_t
1987 BMessage::ReplaceData(const char* name, type_code type, int32 index,
1988 	const void* data, ssize_t numBytes)
1989 {
1990 	DEBUG_FUNCTION_ENTER;
1991 	if (numBytes <= 0 || data == NULL)
1992 		return B_BAD_VALUE;
1993 
1994 	field_header* field = NULL;
1995 	status_t result = _FindField(name, type, &field);
1996 	if (result != B_OK)
1997 		return result;
1998 
1999 	if (index < 0 || (uint32)index >= field->count)
2000 		return B_BAD_INDEX;
2001 
2002 	if (fHeader->message_area >= 0) {
2003 		result = _CopyForWrite();
2004 		if (result != B_OK)
2005 			return result;
2006 	}
2007 
2008 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
2009 		ssize_t size = field->data_size / field->count;
2010 		if (size != numBytes)
2011 			return B_BAD_VALUE;
2012 
2013 		memcpy(fData + field->offset + field->name_length + index * size, data,
2014 			size);
2015 	} else {
2016 		uint32 offset = field->offset + field->name_length;
2017 		uint8* pointer = fData + offset;
2018 
2019 		for (int32 i = 0; i < index; i++) {
2020 			offset += *(uint32*)pointer + sizeof(uint32);
2021 			pointer = fData + offset;
2022 		}
2023 
2024 		size_t currentSize = *(uint32*)pointer;
2025 		int32 change = numBytes - currentSize;
2026 		result = _ResizeData(offset, change);
2027 		if (result != B_OK)
2028 			return result;
2029 
2030 		uint32 newSize = (uint32)numBytes;
2031 		memcpy(fData + offset, &newSize, sizeof(uint32));
2032 		memcpy(fData + offset + sizeof(uint32), data, newSize);
2033 		field->data_size += change;
2034 	}
2035 
2036 	return B_OK;
2037 }
2038 
2039 
2040 bool
2041 BMessage::HasData(const char* name, type_code type, int32 index) const
2042 {
2043 	DEBUG_FUNCTION_ENTER;
2044 	field_header* field = NULL;
2045 	status_t result = _FindField(name, type, &field);
2046 	if (result != B_OK)
2047 		return false;
2048 
2049 	if (index < 0 || (uint32)index >= field->count)
2050 		return false;
2051 
2052 	return true;
2053 }
2054 
2055 
2056 /* Static functions for cache initialization and cleanup */
2057 void
2058 BMessage::_StaticInit()
2059 {
2060 	DEBUG_FUNCTION_ENTER2;
2061 	sReplyPorts[0] = create_port(1, "tmp_rport0");
2062 	sReplyPorts[1] = create_port(1, "tmp_rport1");
2063 	sReplyPorts[2] = create_port(1, "tmp_rport2");
2064 
2065 	sReplyPortInUse[0] = 0;
2066 	sReplyPortInUse[1] = 0;
2067 	sReplyPortInUse[2] = 0;
2068 
2069 	sMsgCache = new BBlockCache(20, sizeof(BMessage), B_OBJECT_CACHE);
2070 }
2071 
2072 
2073 void
2074 BMessage::_StaticReInitForkedChild()
2075 {
2076 	DEBUG_FUNCTION_ENTER2;
2077 
2078 	// overwrite the inherited ports with a set of our own
2079 	sReplyPorts[0] = create_port(1, "tmp_rport0");
2080 	sReplyPorts[1] = create_port(1, "tmp_rport1");
2081 	sReplyPorts[2] = create_port(1, "tmp_rport2");
2082 
2083 	sReplyPortInUse[0] = 0;
2084 	sReplyPortInUse[1] = 0;
2085 	sReplyPortInUse[2] = 0;
2086 }
2087 
2088 
2089 void
2090 BMessage::_StaticCleanup()
2091 {
2092 	DEBUG_FUNCTION_ENTER2;
2093 	delete_port(sReplyPorts[0]);
2094 	sReplyPorts[0] = -1;
2095 	delete_port(sReplyPorts[1]);
2096 	sReplyPorts[1] = -1;
2097 	delete_port(sReplyPorts[2]);
2098 	sReplyPorts[2] = -1;
2099 }
2100 
2101 
2102 void
2103 BMessage::_StaticCacheCleanup()
2104 {
2105 	DEBUG_FUNCTION_ENTER2;
2106 	delete sMsgCache;
2107 	sMsgCache = NULL;
2108 }
2109 
2110 
2111 int32
2112 BMessage::_StaticGetCachedReplyPort()
2113 {
2114 	DEBUG_FUNCTION_ENTER2;
2115 	int index = -1;
2116 	for (int32 i = 0; i < sNumReplyPorts; i++) {
2117 		int32 old = atomic_add(&(sReplyPortInUse[i]), 1);
2118 		if (old == 0) {
2119 			// This entry is free
2120 			index = i;
2121 			break;
2122 		} else {
2123 			// This entry is being used.
2124 			atomic_add(&(sReplyPortInUse[i]), -1);
2125 		}
2126 	}
2127 
2128 	return index;
2129 }
2130 
2131 
2132 status_t
2133 BMessage::_SendMessage(port_id port, team_id portOwner, int32 token,
2134 	bigtime_t timeout, bool replyRequired, BMessenger& replyTo) const
2135 {
2136 	DEBUG_FUNCTION_ENTER;
2137 	ssize_t size = 0;
2138 	char* buffer = NULL;
2139 	message_header* header = NULL;
2140 	status_t result = B_OK;
2141 
2142 	BPrivate::BDirectMessageTarget* direct = NULL;
2143 	BMessage* copy = NULL;
2144 	if (portOwner == BPrivate::current_team())
2145 		BPrivate::gDefaultTokens.AcquireHandlerTarget(token, &direct);
2146 
2147 	if (direct != NULL) {
2148 		// We have a direct local message target - we can just enqueue the
2149 		// message in its message queue. This will also prevent possible
2150 		// deadlocks when the queue is full.
2151 		copy = new BMessage(*this);
2152 		if (copy != NULL) {
2153 			header = copy->fHeader;
2154 			header->flags = fHeader->flags;
2155 		} else {
2156 			direct->Release();
2157 			return B_NO_MEMORY;
2158 		}
2159 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
2160 	} else if (fHeader->data_size > B_PAGE_SIZE * 10) {
2161 		// ToDo: bind the above size to the max port message size
2162 		// use message passing by area for such a large message
2163 		result = _FlattenToArea(&header);
2164 		if (result != B_OK)
2165 			return result;
2166 
2167 		buffer = (char*)header;
2168 		size = sizeof(message_header);
2169 
2170 		if (header->message_area >= 0) {
2171 			team_id target = portOwner;
2172 			if (target < 0) {
2173 				port_info info;
2174 				result = get_port_info(port, &info);
2175 				if (result != B_OK) {
2176 					free(header);
2177 					return result;
2178 				}
2179 				target = info.team;
2180 			}
2181 
2182 			void* address = NULL;
2183 			area_id transfered = _kern_transfer_area(header->message_area,
2184 				&address, B_ANY_ADDRESS, target);
2185 			if (transfered < 0) {
2186 				delete_area(header->message_area);
2187 				free(header);
2188 				return transfered;
2189 			}
2190 
2191 			header->message_area = transfered;
2192 		}
2193 #endif
2194 	} else {
2195 		size = FlattenedSize();
2196 		buffer = (char*)malloc(size);
2197 		if (buffer == NULL)
2198 			return B_NO_MEMORY;
2199 
2200 		result = Flatten(buffer, size);
2201 		if (result != B_OK) {
2202 			free(buffer);
2203 			return result;
2204 		}
2205 
2206 		header = (message_header*)buffer;
2207 	}
2208 
2209 	if (!replyTo.IsValid()) {
2210 		BMessenger::Private(replyTo).SetTo(fHeader->reply_team,
2211 			fHeader->reply_port, fHeader->reply_target);
2212 
2213 		if (!replyTo.IsValid())
2214 			replyTo = be_app_messenger;
2215 	}
2216 
2217 	BMessenger::Private replyToPrivate(replyTo);
2218 
2219 	if (replyRequired) {
2220 		header->flags |= MESSAGE_FLAG_REPLY_REQUIRED;
2221 		header->flags &= ~MESSAGE_FLAG_REPLY_DONE;
2222 	}
2223 
2224 	header->target = token;
2225 	header->reply_team = replyToPrivate.Team();
2226 	header->reply_port = replyToPrivate.Port();
2227 	header->reply_target = replyToPrivate.Token();
2228 	header->flags |= MESSAGE_FLAG_WAS_DELIVERED;
2229 
2230 	if (direct == NULL) {
2231 		KTRACE("BMessage send remote: team: %ld, port: %ld, token: %ld, "
2232 			"message: '%c%c%c%c'", portOwner, port, token,
2233 			char(what >> 24), char(what >> 16), char(what >> 8), (char)what);
2234 
2235 		do {
2236 			result = write_port_etc(port, kPortMessageCode, (void*)buffer,
2237 				size, B_RELATIVE_TIMEOUT, timeout);
2238 		} while (result == B_INTERRUPTED);
2239 	}
2240 
2241 	if (result == B_OK && IsSourceWaiting()) {
2242 		// the forwarded message will handle the reply - we must not do
2243 		// this anymore
2244 		fHeader->flags |= MESSAGE_FLAG_REPLY_DONE;
2245 	}
2246 
2247 	// we need to do this last because it is possible our
2248 	// message might be destroyed after it's enqueued in the
2249 	// target looper. Thus we don't want to do any ops that depend on
2250 	// members of this after the enqueue.
2251 	if (direct != NULL) {
2252 		KTRACE("BMessage send direct: port: %ld, token: %ld, "
2253 			"message: '%c%c%c%c'", port, token,
2254 			char(what >> 24), char(what >> 16), char(what >> 8), (char)what);
2255 
2256 		// this is a local message transmission
2257 		direct->AddMessage(copy);
2258 		if (direct->Queue()->IsNextMessage(copy) && port_count(port) <= 0) {
2259 			// there is currently no message waiting, and we need to wakeup the
2260 			// looper
2261 			write_port_etc(port, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
2262 		}
2263 		direct->Release();
2264 	}
2265 
2266 	free(buffer);
2267 	return result;
2268 }
2269 
2270 
2271 // Sends a message and waits synchronously for a reply.
2272 status_t
2273 BMessage::_SendMessage(port_id port, team_id portOwner, int32 token,
2274 	BMessage* reply, bigtime_t sendTimeout, bigtime_t replyTimeout) const
2275 {
2276 	if (IsSourceWaiting()) {
2277 		// we can't forward this message synchronously when it's already
2278 		// waiting for a reply
2279 		return B_ERROR;
2280 	}
2281 
2282 	DEBUG_FUNCTION_ENTER;
2283 	const int32 cachedReplyPort = _StaticGetCachedReplyPort();
2284 	port_id replyPort = B_BAD_PORT_ID;
2285 	status_t result = B_OK;
2286 
2287 	if (cachedReplyPort < 0) {
2288 		// All the cached reply ports are in use; create a new one
2289 		replyPort = create_port(1 /* for one message */, "tmp_reply_port");
2290 		if (replyPort < 0)
2291 			return replyPort;
2292 	} else {
2293 		assert(cachedReplyPort < sNumReplyPorts);
2294 		replyPort = sReplyPorts[cachedReplyPort];
2295 	}
2296 
2297 	team_id team = B_BAD_TEAM_ID;
2298 	if (be_app != NULL)
2299 		team = be_app->Team();
2300 	else {
2301 		port_info portInfo;
2302 		result = get_port_info(replyPort, &portInfo);
2303 		if (result != B_OK)
2304 			goto error;
2305 
2306 		team = portInfo.team;
2307 	}
2308 
2309 	result = set_port_owner(replyPort, portOwner);
2310 	if (result != B_OK)
2311 		goto error;
2312 
2313 	// tests if the queue of the reply port is really empty
2314 #if 0
2315 	port_info portInfo;
2316 	if (get_port_info(replyPort, &portInfo) == B_OK
2317 		&& portInfo.queue_count > 0) {
2318 		debugger("reply port not empty!");
2319 		printf("  reply port not empty! %ld message(s) in queue\n",
2320 			portInfo.queue_count);
2321 
2322 		// fetch and print the messages
2323 		for (int32 i = 0; i < portInfo.queue_count; i++) {
2324 			char buffer[1024];
2325 			int32 code;
2326 			ssize_t size = read_port(replyPort, &code, buffer, sizeof(buffer));
2327 			if (size < 0) {
2328 				printf("failed to read message from reply port\n");
2329 				continue;
2330 			}
2331 			if (size >= (ssize_t)sizeof(buffer)) {
2332 				printf("message from reply port too big\n");
2333 				continue;
2334 			}
2335 
2336 			BMemoryIO stream(buffer, size);
2337 			BMessage reply;
2338 			if (reply.Unflatten(&stream) != B_OK) {
2339 				printf("failed to unflatten message from reply port\n");
2340 				continue;
2341 			}
2342 
2343 			printf("message %ld from reply port:\n", i);
2344 			reply.PrintToStream();
2345 		}
2346 	}
2347 #endif
2348 
2349 	{
2350 		BMessenger replyTarget;
2351 		BMessenger::Private(replyTarget).SetTo(team, replyPort,
2352 			B_PREFERRED_TOKEN);
2353 		// TODO: replying could also use a BDirectMessageTarget like mechanism
2354 		// for local targets
2355 		result = _SendMessage(port, -1, token, sendTimeout, true,
2356 			replyTarget);
2357 	}
2358 
2359 	if (result != B_OK)
2360 		goto error;
2361 
2362 	int32 code;
2363 	result = handle_reply(replyPort, &code, replyTimeout, reply);
2364 	if (result != B_OK && cachedReplyPort >= 0) {
2365 		delete_port(replyPort);
2366 		sReplyPorts[cachedReplyPort] = create_port(1, "tmp_rport");
2367 	}
2368 
2369 error:
2370 	if (cachedReplyPort >= 0) {
2371 		// Reclaim ownership of cached port
2372 		set_port_owner(replyPort, team);
2373 		// Flag as available
2374 		atomic_add(&sReplyPortInUse[cachedReplyPort], -1);
2375 		return result;
2376 	}
2377 
2378 	delete_port(replyPort);
2379 	return result;
2380 }
2381 
2382 
2383 status_t
2384 BMessage::_SendFlattenedMessage(void* data, int32 size, port_id port,
2385 	int32 token, bigtime_t timeout)
2386 {
2387 	DEBUG_FUNCTION_ENTER2;
2388 	if (data == NULL)
2389 		return B_BAD_VALUE;
2390 
2391 	uint32 magic = *(uint32*)data;
2392 
2393 	if (magic == MESSAGE_FORMAT_HAIKU
2394 		|| magic == MESSAGE_FORMAT_HAIKU_SWAPPED) {
2395 		message_header* header = (message_header*)data;
2396 		header->target = token;
2397 		header->flags |= MESSAGE_FLAG_WAS_DELIVERED;
2398 	} else if (magic == MESSAGE_FORMAT_R5) {
2399 		uint8* header = (uint8*)data;
2400 		header += sizeof(uint32) /* magic */ + sizeof(uint32) /* checksum */
2401 			+ sizeof(ssize_t) /* flattenedSize */ + sizeof(int32) /* what */
2402 			+ sizeof(uint8) /* flags */;
2403 		*(int32*)header = token;
2404 	} else if (((KMessage::Header*)data)->magic
2405 			== KMessage::kMessageHeaderMagic) {
2406 		KMessage::Header* header = (KMessage::Header*)data;
2407 		header->targetToken = token;
2408 	} else {
2409 		return B_NOT_A_MESSAGE;
2410 	}
2411 
2412 	// send the message
2413 	status_t result;
2414 
2415 	do {
2416 		result = write_port_etc(port, kPortMessageCode, data, size,
2417 			B_RELATIVE_TIMEOUT, timeout);
2418 	} while (result == B_INTERRUPTED);
2419 
2420 	return result;
2421 }
2422 
2423 
2424 void BMessage::_ReservedMessage1() {}
2425 void BMessage::_ReservedMessage2() {}
2426 void BMessage::_ReservedMessage3() {}
2427 
2428 
2429 // #pragma mark - Macro definitions for data access methods
2430 
2431 
2432 /* Relay functions from here on (Add... -> AddData, Find... -> FindData) */
2433 
2434 #define DEFINE_FUNCTIONS(type, typeName, typeCode)							\
2435 status_t																	\
2436 BMessage::Add##typeName(const char* name, type val)							\
2437 {																			\
2438 	return AddData(name, typeCode, &val, sizeof(type), true);				\
2439 }																			\
2440 																			\
2441 																			\
2442 status_t																	\
2443 BMessage::Find##typeName(const char* name, type* p) const					\
2444 {																			\
2445 	void* ptr = NULL;														\
2446 	ssize_t bytes = 0;														\
2447 	status_t error = B_OK;													\
2448 																			\
2449 	*p = type();															\
2450 	error = FindData(name, typeCode, 0, (const void**)&ptr, &bytes);		\
2451 																			\
2452 	if (error == B_OK)														\
2453 		memcpy(p, ptr, sizeof(type));										\
2454 																			\
2455 	return error;															\
2456 }																			\
2457 																			\
2458 																			\
2459 status_t																	\
2460 BMessage::Find##typeName(const char* name, int32 index, type* p) const		\
2461 {																			\
2462 	void* ptr = NULL;														\
2463 	ssize_t bytes = 0;														\
2464 	status_t error = B_OK;													\
2465 																			\
2466 	*p = type();															\
2467 	error = FindData(name, typeCode, index, (const void**)&ptr, &bytes);	\
2468 																			\
2469 	if (error == B_OK)														\
2470 		memcpy(p, ptr, sizeof(type));										\
2471 																			\
2472 	return error;															\
2473 }																			\
2474 																			\
2475 																			\
2476 status_t																	\
2477 BMessage::Replace##typeName(const char* name, type value)					\
2478 {																			\
2479 	return ReplaceData(name, typeCode, 0, &value, sizeof(type));			\
2480 }																			\
2481 																			\
2482 																			\
2483 status_t																	\
2484 BMessage::Replace##typeName(const char* name, int32 index, type value)		\
2485 {																			\
2486 	return ReplaceData(name, typeCode, index, &value, sizeof(type));		\
2487 }																			\
2488 																			\
2489 																			\
2490 bool																		\
2491 BMessage::Has##typeName(const char* name, int32 index) const				\
2492 {																			\
2493 	return HasData(name, typeCode, index);									\
2494 }
2495 
2496 DEFINE_FUNCTIONS(BPoint, Point, B_POINT_TYPE);
2497 DEFINE_FUNCTIONS(BRect, Rect, B_RECT_TYPE);
2498 DEFINE_FUNCTIONS(BSize, Size, B_SIZE_TYPE);
2499 DEFINE_FUNCTIONS(int8, Int8, B_INT8_TYPE);
2500 DEFINE_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE);
2501 DEFINE_FUNCTIONS(int16, Int16, B_INT16_TYPE);
2502 DEFINE_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE);
2503 DEFINE_FUNCTIONS(int32, Int32, B_INT32_TYPE);
2504 DEFINE_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE);
2505 DEFINE_FUNCTIONS(int64, Int64, B_INT64_TYPE);
2506 DEFINE_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE);
2507 DEFINE_FUNCTIONS(bool, Bool, B_BOOL_TYPE);
2508 DEFINE_FUNCTIONS(float, Float, B_FLOAT_TYPE);
2509 DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE);
2510 
2511 #undef DEFINE_FUNCTIONS
2512 
2513 #define DEFINE_HAS_FUNCTION(typeName, typeCode)								\
2514 bool																		\
2515 BMessage::Has##typeName(const char* name, int32 index) const				\
2516 {																			\
2517 	return HasData(name, typeCode, index);									\
2518 }
2519 
2520 
2521 DEFINE_HAS_FUNCTION(Alignment, B_ALIGNMENT_TYPE);
2522 DEFINE_HAS_FUNCTION(String, B_STRING_TYPE);
2523 DEFINE_HAS_FUNCTION(Pointer, B_POINTER_TYPE);
2524 DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE);
2525 DEFINE_HAS_FUNCTION(Ref, B_REF_TYPE);
2526 DEFINE_HAS_FUNCTION(Message, B_MESSAGE_TYPE);
2527 
2528 #undef DEFINE_HAS_FUNCTION
2529 
2530 
2531 #define DEFINE_LAZY_FIND_FUNCTION(type, typeName, initialize)				\
2532 type																		\
2533 BMessage::Find##typeName(const char* name, int32 index) const				\
2534 {																			\
2535 	type val = initialize;													\
2536 	Find##typeName(name, index, &val);										\
2537 	return val;																\
2538 }
2539 
2540 
2541 DEFINE_LAZY_FIND_FUNCTION(BRect, Rect, BRect());
2542 DEFINE_LAZY_FIND_FUNCTION(BPoint, Point, BPoint());
2543 DEFINE_LAZY_FIND_FUNCTION(const char*, String, NULL);
2544 DEFINE_LAZY_FIND_FUNCTION(int8, Int8, 0);
2545 DEFINE_LAZY_FIND_FUNCTION(int16, Int16, 0);
2546 DEFINE_LAZY_FIND_FUNCTION(int32, Int32, 0);
2547 DEFINE_LAZY_FIND_FUNCTION(int64, Int64, 0);
2548 DEFINE_LAZY_FIND_FUNCTION(bool, Bool, false);
2549 DEFINE_LAZY_FIND_FUNCTION(float, Float, 0);
2550 DEFINE_LAZY_FIND_FUNCTION(double, Double, 0);
2551 
2552 #undef DEFINE_LAZY_FIND_FUNCTION
2553 
2554 
2555 #define DEFINE_SET_GET_FUNCTIONS(type, typeName, typeCode)					\
2556 type																		\
2557 BMessage::Get##typeName(const char* name, type defaultValue) const			\
2558 {																			\
2559 	return Get##typeName(name, 0, defaultValue);							\
2560 }																			\
2561 																			\
2562 																			\
2563 type																		\
2564 BMessage::Get##typeName(const char* name, int32 index,						\
2565 	type defaultValue) const												\
2566 {																			\
2567 	type value;																\
2568 	if (Find##typeName(name, index, &value) == B_OK)						\
2569 		return value;														\
2570 																			\
2571 	return defaultValue;													\
2572 }																			\
2573 																			\
2574 																			\
2575 status_t																	\
2576 BMessage::Set##typeName(const char* name, type value)						\
2577 {																			\
2578 	return SetData(name, typeCode, &value, sizeof(type));					\
2579 }																			\
2580 
2581 
2582 DEFINE_SET_GET_FUNCTIONS(int8, Int8, B_INT8_TYPE);
2583 DEFINE_SET_GET_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE);
2584 DEFINE_SET_GET_FUNCTIONS(int16, Int16, B_INT16_TYPE);
2585 DEFINE_SET_GET_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE);
2586 DEFINE_SET_GET_FUNCTIONS(int32, Int32, B_INT32_TYPE);
2587 DEFINE_SET_GET_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE);
2588 DEFINE_SET_GET_FUNCTIONS(int64, Int64, B_INT64_TYPE);
2589 DEFINE_SET_GET_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE);
2590 DEFINE_SET_GET_FUNCTIONS(bool, Bool, B_BOOL_TYPE);
2591 DEFINE_SET_GET_FUNCTIONS(float, Float, B_FLOAT_TYPE);
2592 DEFINE_SET_GET_FUNCTIONS(double, Double, B_DOUBLE_TYPE);
2593 
2594 #undef DEFINE_SET_GET_FUNCTION
2595 
2596 
2597 #define DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(type, typeName, typeCode)		\
2598 type																		\
2599 BMessage::Get##typeName(const char* name, const type& defaultValue) const	\
2600 {																			\
2601 	return Get##typeName(name, 0, defaultValue);							\
2602 }																			\
2603 																			\
2604 																			\
2605 type																		\
2606 BMessage::Get##typeName(const char* name, int32 index,						\
2607 	const type& defaultValue) const											\
2608 {																			\
2609 	type value;																\
2610 	if (Find##typeName(name, index, &value) == B_OK)						\
2611 		return value;														\
2612 																			\
2613 	return defaultValue;													\
2614 }																			\
2615 																			\
2616 																			\
2617 status_t																	\
2618 BMessage::Set##typeName(const char* name, const type& value)				\
2619 {																			\
2620 	return SetData(name, typeCode, &value, sizeof(type));					\
2621 }																			\
2622 
2623 
2624 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BPoint, Point, B_POINT_TYPE);
2625 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BRect, Rect, B_RECT_TYPE);
2626 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BSize, Size, B_SIZE_TYPE);
2627 
2628 #undef DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS
2629 
2630 
2631 status_t
2632 BMessage::AddAlignment(const char* name, const BAlignment& alignment)
2633 {
2634 	int32 data[2] = { alignment.horizontal, alignment.vertical };
2635 	return AddData(name, B_ALIGNMENT_TYPE, data, sizeof(data));
2636 }
2637 
2638 
2639 status_t
2640 BMessage::AddString(const char* name, const char* string)
2641 {
2642 	return AddData(name, B_STRING_TYPE, string, string ? strlen(string) + 1 : 0,
2643 		false);
2644 }
2645 
2646 
2647 status_t
2648 BMessage::AddString(const char* name, const BString& string)
2649 {
2650 	return AddData(name, B_STRING_TYPE, string.String(), string.Length() + 1,
2651 		false);
2652 }
2653 
2654 
2655 status_t
2656 BMessage::AddStrings(const char* name, const BStringList& list)
2657 {
2658 	int32 count = list.CountStrings();
2659 	for (int32 i = 0; i < count; i++) {
2660 		status_t error = AddString(name, list.StringAt(i));
2661 		if (error != B_OK)
2662 			return error;
2663 	}
2664 
2665 	return B_OK;
2666 }
2667 
2668 
2669 status_t
2670 BMessage::AddPointer(const char* name, const void* pointer)
2671 {
2672 	return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer), true);
2673 }
2674 
2675 
2676 status_t
2677 BMessage::AddMessenger(const char* name, BMessenger messenger)
2678 {
2679 	return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger), true);
2680 }
2681 
2682 
2683 status_t
2684 BMessage::AddRef(const char* name, const entry_ref* ref)
2685 {
2686 	size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
2687 	char buffer[size];
2688 
2689 	status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref);
2690 
2691 	if (error >= B_OK)
2692 		error = AddData(name, B_REF_TYPE, buffer, size, false);
2693 
2694 	return error;
2695 }
2696 
2697 
2698 status_t
2699 BMessage::AddMessage(const char* name, const BMessage* message)
2700 {
2701 	if (message == NULL)
2702 		return B_BAD_VALUE;
2703 
2704 	// TODO: This and the following functions waste time by allocating and
2705 	// copying an extra buffer. Functions can be added that return a direct
2706 	// pointer into the message.
2707 
2708 	char stackBuffer[16384];
2709 	ssize_t size = message->FlattenedSize();
2710 
2711 	char* buffer;
2712 	if (size > (ssize_t)sizeof(stackBuffer)) {
2713 		buffer = (char*)malloc(size);
2714 		if (buffer == NULL)
2715 			return B_NO_MEMORY;
2716 	} else
2717 		buffer = stackBuffer;
2718 
2719 	status_t error = message->Flatten(buffer, size);
2720 
2721 	if (error >= B_OK)
2722 		error = AddData(name, B_MESSAGE_TYPE, buffer, size, false);
2723 
2724 	if (buffer != stackBuffer)
2725 		free(buffer);
2726 
2727 	return error;
2728 }
2729 
2730 
2731 status_t
2732 BMessage::AddFlat(const char* name, BFlattenable* object, int32 count)
2733 {
2734 	return AddFlat(name, (const BFlattenable*)object, count);
2735 }
2736 
2737 
2738 status_t
2739 BMessage::AddFlat(const char* name, const BFlattenable* object, int32 count)
2740 {
2741 	if (object == NULL)
2742 		return B_BAD_VALUE;
2743 
2744 	char stackBuffer[16384];
2745 	ssize_t size = object->FlattenedSize();
2746 
2747 	char* buffer;
2748 	if (size > (ssize_t)sizeof(stackBuffer)) {
2749 		buffer = (char*)malloc(size);
2750 		if (buffer == NULL)
2751 			return B_NO_MEMORY;
2752 	} else
2753 		buffer = stackBuffer;
2754 
2755 	status_t error = object->Flatten(buffer, size);
2756 
2757 	if (error >= B_OK)
2758 		error = AddData(name, object->TypeCode(), buffer, size, false);
2759 
2760 	if (buffer != stackBuffer)
2761 		free(buffer);
2762 
2763 	return error;
2764 }
2765 
2766 
2767 status_t
2768 BMessage::Append(const BMessage& other)
2769 {
2770 	field_header* field = other.fFields;
2771 	for (uint32 i = 0; i < other.fHeader->field_count; i++, field++) {
2772 		const char* name = (const char*)(other.fData + field->offset);
2773 		const void* data = (const void*)(other.fData + field->offset
2774 			+ field->name_length);
2775 		bool isFixed = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
2776 		size_t size = field->data_size / field->count;
2777 
2778 		for (uint32 j = 0; j < field->count; j++) {
2779 			if (!isFixed) {
2780 				size = *(uint32*)data;
2781 				data = (const void*)((const char*)data + sizeof(uint32));
2782 			}
2783 
2784 			status_t status = AddData(name, field->type, data, size,
2785 				isFixed, 1);
2786 			if (status != B_OK)
2787 				return status;
2788 
2789 			data = (const void*)((const char*)data + size);
2790 		}
2791 	}
2792 	return B_OK;
2793 }
2794 
2795 
2796 status_t
2797 BMessage::FindAlignment(const char* name, BAlignment* alignment) const
2798 {
2799 	return FindAlignment(name, 0, alignment);
2800 }
2801 
2802 
2803 status_t
2804 BMessage::FindAlignment(const char* name, int32 index, BAlignment* alignment)
2805 	const
2806 {
2807 	if (!alignment)
2808 		return B_BAD_VALUE;
2809 
2810 	int32* data;
2811 	ssize_t bytes;
2812 
2813 	status_t err = FindData(name, B_ALIGNMENT_TYPE, index,
2814 		(const void**)&data, &bytes);
2815 
2816 	if (err == B_OK) {
2817 		if (bytes != sizeof(int32[2]))
2818 			return B_ERROR;
2819 
2820 		alignment->horizontal = (enum alignment)(*data);
2821 		alignment->vertical = (vertical_alignment)*(data + 1);
2822 	}
2823 
2824 	return err;
2825 }
2826 
2827 
2828 status_t
2829 BMessage::FindString(const char* name, const char** string) const
2830 {
2831 	return FindString(name, 0, string);
2832 }
2833 
2834 
2835 status_t
2836 BMessage::FindString(const char* name, int32 index, const char** string) const
2837 {
2838 	ssize_t bytes;
2839 	return FindData(name, B_STRING_TYPE, index, (const void**)string, &bytes);
2840 }
2841 
2842 
2843 status_t
2844 BMessage::FindString(const char* name, BString* string) const
2845 {
2846 	return FindString(name, 0, string);
2847 }
2848 
2849 
2850 status_t
2851 BMessage::FindString(const char* name, int32 index, BString* string) const
2852 {
2853 	if (string == NULL)
2854 		return B_BAD_VALUE;
2855 
2856 	const char* value;
2857 	status_t error = FindString(name, index, &value);
2858 
2859 	// Find*() clobbers the object even on failure
2860 	string->SetTo(value);
2861 	return error;
2862 }
2863 
2864 
2865 status_t
2866 BMessage::FindStrings(const char* name, BStringList* list) const
2867 {
2868 	if (list == NULL)
2869 		return B_BAD_VALUE;
2870 
2871 	list->MakeEmpty();
2872 
2873 	// get the number of items
2874 	type_code type;
2875 	int32 count;
2876 	if (GetInfo(name, &type, &count) != B_OK)
2877 		return B_NAME_NOT_FOUND;
2878 
2879 	if (type != B_STRING_TYPE)
2880 		return B_BAD_DATA;
2881 
2882 	for (int32 i = 0; i < count; i++) {
2883 		BString string;
2884 		status_t error = FindString(name, i, &string);
2885 		if (error != B_OK)
2886 			return error;
2887 		if (!list->Add(string))
2888 			return B_NO_MEMORY;
2889 	}
2890 
2891 	return B_OK;
2892 }
2893 
2894 
2895 status_t
2896 BMessage::FindPointer(const char* name, void** pointer) const
2897 {
2898 	return FindPointer(name, 0, pointer);
2899 }
2900 
2901 
2902 status_t
2903 BMessage::FindPointer(const char* name, int32 index, void** pointer) const
2904 {
2905 	if (pointer == NULL)
2906 		return B_BAD_VALUE;
2907 
2908 	void** data = NULL;
2909 	ssize_t size = 0;
2910 	status_t error = FindData(name, B_POINTER_TYPE, index,
2911 		(const void**)&data, &size);
2912 
2913 	if (error == B_OK)
2914 		*pointer = *data;
2915 	else
2916 		*pointer = NULL;
2917 
2918 	return error;
2919 }
2920 
2921 
2922 status_t
2923 BMessage::FindMessenger(const char* name, BMessenger* messenger) const
2924 {
2925 	return FindMessenger(name, 0, messenger);
2926 }
2927 
2928 
2929 status_t
2930 BMessage::FindMessenger(const char* name, int32 index,
2931 	BMessenger* messenger) const
2932 {
2933 	if (messenger == NULL)
2934 		return B_BAD_VALUE;
2935 
2936 	void* data = NULL;
2937 	ssize_t size = 0;
2938 	status_t error = FindData(name, B_MESSENGER_TYPE, index,
2939 		(const void**)&data, &size);
2940 
2941 	if (error == B_OK)
2942 		memcpy(messenger, data, sizeof(BMessenger));
2943 	else
2944 		*messenger = BMessenger();
2945 
2946 	return error;
2947 }
2948 
2949 
2950 status_t
2951 BMessage::FindRef(const char* name, entry_ref* ref) const
2952 {
2953 	return FindRef(name, 0, ref);
2954 }
2955 
2956 
2957 status_t
2958 BMessage::FindRef(const char* name, int32 index, entry_ref* ref) const
2959 {
2960 	if (ref == NULL)
2961 		return B_BAD_VALUE;
2962 
2963 	void* data = NULL;
2964 	ssize_t size = 0;
2965 	status_t error = FindData(name, B_REF_TYPE, index,
2966 		(const void**)&data, &size);
2967 
2968 	if (error == B_OK)
2969 		error = BPrivate::entry_ref_unflatten(ref, (char*)data, size);
2970 	else
2971 		*ref = entry_ref();
2972 
2973 	return error;
2974 }
2975 
2976 
2977 status_t
2978 BMessage::FindMessage(const char* name, BMessage* message) const
2979 {
2980 	return FindMessage(name, 0, message);
2981 }
2982 
2983 
2984 status_t
2985 BMessage::FindMessage(const char* name, int32 index, BMessage* message) const
2986 {
2987 	if (message == NULL)
2988 		return B_BAD_VALUE;
2989 
2990 	void* data = NULL;
2991 	ssize_t size = 0;
2992 	status_t error = FindData(name, B_MESSAGE_TYPE, index,
2993 		(const void**)&data, &size);
2994 
2995 	if (error == B_OK)
2996 		error = message->Unflatten((const char*)data);
2997 	else
2998 		*message = BMessage();
2999 
3000 	return error;
3001 }
3002 
3003 
3004 status_t
3005 BMessage::FindFlat(const char* name, BFlattenable* object) const
3006 {
3007 	return FindFlat(name, 0, object);
3008 }
3009 
3010 
3011 status_t
3012 BMessage::FindFlat(const char* name, int32 index, BFlattenable* object) const
3013 {
3014 	if (object == NULL)
3015 		return B_BAD_VALUE;
3016 
3017 	void* data = NULL;
3018 	ssize_t numBytes = 0;
3019 	status_t error = FindData(name, object->TypeCode(), index,
3020 		(const void**)&data, &numBytes);
3021 
3022 	if (error == B_OK)
3023 		error = object->Unflatten(object->TypeCode(), data, numBytes);
3024 
3025 	return error;
3026 }
3027 
3028 
3029 status_t
3030 BMessage::FindData(const char* name, type_code type, const void** data,
3031 	ssize_t* numBytes) const
3032 {
3033 	return FindData(name, type, 0, data, numBytes);
3034 }
3035 
3036 
3037 status_t
3038 BMessage::ReplaceAlignment(const char* name, const BAlignment& alignment)
3039 {
3040 	int32 data[2] = {alignment.horizontal, alignment.vertical};
3041 	return ReplaceData(name, B_ALIGNMENT_TYPE, 0, data, sizeof(data));
3042 }
3043 
3044 
3045 status_t
3046 BMessage::ReplaceAlignment(const char* name, int32 index,
3047 	const BAlignment& alignment)
3048 {
3049 	int32 data[2] = {alignment.horizontal, alignment.vertical};
3050 	return ReplaceData(name, B_ALIGNMENT_TYPE, index, data, sizeof(data));
3051 }
3052 
3053 
3054 status_t
3055 BMessage::ReplaceString(const char* name, const char* string)
3056 {
3057 	if (string == NULL)
3058 		return B_BAD_VALUE;
3059 
3060 	return ReplaceData(name, B_STRING_TYPE, 0, string, strlen(string) + 1);
3061 }
3062 
3063 
3064 status_t
3065 BMessage::ReplaceString(const char* name, int32 index, const char* string)
3066 {
3067 	if (string == NULL)
3068 		return B_BAD_VALUE;
3069 
3070 	return ReplaceData(name, B_STRING_TYPE, index, string, strlen(string) + 1);
3071 }
3072 
3073 
3074 status_t
3075 BMessage::ReplaceString(const char* name, const BString& string)
3076 {
3077 	return ReplaceData(name, B_STRING_TYPE, 0, string.String(),
3078 		string.Length() + 1);
3079 }
3080 
3081 
3082 status_t
3083 BMessage::ReplaceString(const char* name, int32 index, const BString& string)
3084 {
3085 	return ReplaceData(name, B_STRING_TYPE, index, string.String(),
3086 		string.Length() + 1);
3087 }
3088 
3089 
3090 status_t
3091 BMessage::ReplacePointer(const char* name, const void* pointer)
3092 {
3093 	return ReplaceData(name, B_POINTER_TYPE, 0, &pointer, sizeof(pointer));
3094 }
3095 
3096 
3097 status_t
3098 BMessage::ReplacePointer(const char* name, int32 index, const void* pointer)
3099 {
3100 	return ReplaceData(name, B_POINTER_TYPE, index, &pointer, sizeof(pointer));
3101 }
3102 
3103 
3104 status_t
3105 BMessage::ReplaceMessenger(const char* name, BMessenger messenger)
3106 {
3107 	return ReplaceData(name, B_MESSENGER_TYPE, 0, &messenger,
3108 		sizeof(BMessenger));
3109 }
3110 
3111 
3112 status_t
3113 BMessage::ReplaceMessenger(const char* name, int32 index, BMessenger messenger)
3114 {
3115 	return ReplaceData(name, B_MESSENGER_TYPE, index, &messenger,
3116 		sizeof(BMessenger));
3117 }
3118 
3119 
3120 status_t
3121 BMessage::ReplaceRef(const char* name, const entry_ref* ref)
3122 {
3123 	return ReplaceRef(name, 0, ref);
3124 }
3125 
3126 
3127 status_t
3128 BMessage::ReplaceRef(const char* name, int32 index, const entry_ref* ref)
3129 {
3130 	size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
3131 	char buffer[size];
3132 
3133 	status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref);
3134 
3135 	if (error >= B_OK)
3136 		error = ReplaceData(name, B_REF_TYPE, index, &buffer, size);
3137 
3138 	return error;
3139 }
3140 
3141 
3142 status_t
3143 BMessage::ReplaceMessage(const char* name, const BMessage* message)
3144 {
3145 	return ReplaceMessage(name, 0, message);
3146 }
3147 
3148 
3149 status_t
3150 BMessage::ReplaceMessage(const char* name, int32 index, const BMessage* message)
3151 {
3152 	if (message == NULL)
3153 		return B_BAD_VALUE;
3154 
3155 	ssize_t size = message->FlattenedSize();
3156 	char buffer[size];
3157 
3158 	status_t error = message->Flatten(buffer, size);
3159 
3160 	if (error >= B_OK)
3161 		error = ReplaceData(name, B_MESSAGE_TYPE, index, &buffer, size);
3162 
3163 	return error;
3164 }
3165 
3166 
3167 status_t
3168 BMessage::ReplaceFlat(const char* name, BFlattenable* object)
3169 {
3170 	return ReplaceFlat(name, 0, object);
3171 }
3172 
3173 
3174 status_t
3175 BMessage::ReplaceFlat(const char* name, int32 index, BFlattenable* object)
3176 {
3177 	if (object == NULL)
3178 		return B_BAD_VALUE;
3179 
3180 	ssize_t size = object->FlattenedSize();
3181 	char buffer[size];
3182 
3183 	status_t error = object->Flatten(buffer, size);
3184 
3185 	if (error >= B_OK)
3186 		error = ReplaceData(name, object->TypeCode(), index, &buffer, size);
3187 
3188 	return error;
3189 }
3190 
3191 
3192 status_t
3193 BMessage::ReplaceData(const char* name, type_code type, const void* data,
3194 	ssize_t numBytes)
3195 {
3196 	return ReplaceData(name, type, 0, data, numBytes);
3197 }
3198 
3199 
3200 bool
3201 BMessage::HasFlat(const char* name, const BFlattenable* object) const
3202 {
3203 	return HasFlat(name, 0, object);
3204 }
3205 
3206 
3207 bool
3208 BMessage::HasFlat(const char* name, int32 index, const BFlattenable* object)
3209 	const
3210 {
3211 	return HasData(name, object->TypeCode(), index);
3212 }
3213 
3214 
3215 const char*
3216 BMessage::GetString(const char* name, const char* defaultValue) const
3217 {
3218 	return GetString(name, 0, defaultValue);
3219 }
3220 
3221 
3222 const char*
3223 BMessage::GetString(const char* name, int32 index,
3224 	const char* defaultValue) const
3225 {
3226 	const char* value;
3227 	if (FindString(name, index, &value) == B_OK)
3228 		return value;
3229 
3230 	return defaultValue;
3231 }
3232 
3233 
3234 status_t
3235 BMessage::SetString(const char* name, const BString& value)
3236 {
3237 	return SetData(name, B_STRING_TYPE, value.String(), value.Length() + 1);
3238 }
3239 
3240 
3241 status_t
3242 BMessage::SetString(const char* name, const char* value)
3243 {
3244 	return SetData(name, B_STRING_TYPE, value, strlen(value) + 1);
3245 }
3246 
3247 
3248 status_t
3249 BMessage::SetData(const char* name, type_code type, const void* data,
3250 	ssize_t numBytes)
3251 {
3252 	if (numBytes <= 0 || data == NULL)
3253 		return B_BAD_VALUE;
3254 
3255 	if (ReplaceData(name, type, data, numBytes) == B_OK)
3256 		return B_OK;
3257 
3258 	return AddData(name, type, data, numBytes);
3259 }
3260