Exemplo n.º 1
0
BContactField*
BContactField::Duplicate(BContactField* from)
{
	BContactField* child = NULL;
	type_code childType = from->FieldType();
	ObjectDeleter<BContactField> deleter;

	switch (childType) {
		case B_CONTACT_NAME:
		case B_CONTACT_NICKNAME:
		case B_CONTACT_EMAIL:
		case B_CONTACT_NOTE:
		case B_CONTACT_ORGANIZATION:
		case B_CONTACT_IM:
		case B_CONTACT_URL:
		case B_CONTACT_PHONE:
			child = new BStringContactField(childType);
			break;
		case B_CONTACT_ADDRESS:
			child = new BAddressContactField();
			break;
		case B_CONTACT_PHOTO:
			child = new BPhotoContactField();
			break;
	}

	if (child != NULL && child->CopyDataFrom(from) == B_OK)
		return child;

	deleter.SetTo(child);
	return NULL;
}
BContactField*
BContactField::Duplicate(BContactField* from)
{
	BContactField* child = NULL;
	type_code childType = from->FieldType();
	ObjectDeleter<BContactField> deleter;

	child = BContactField::InstantiateChildClass(childType);

	if (child != NULL && child->CopyDataFrom(from) == B_OK)
		return child;

	deleter.SetTo(child);
	return NULL;
}
Exemplo n.º 3
0
// You cannot instantiate a pure BContactField
// so this method help to unflatten the correct 
// derived class
BContactField*
BContactField::UnflattenChildClass(const void* from, ssize_t size)
{
	BMemoryIO data(from, size);

	type_code childType;
	data.Read(&childType, sizeof(childType));
	ObjectDeleter<BContactField> deleter;
	BContactField* child = NULL;
	switch (childType) {
		case B_CONTACT_NAME:
		case B_CONTACT_NICKNAME:
		case B_CONTACT_EMAIL:
		case B_CONTACT_NOTE:
		case B_CONTACT_ORGANIZATION:
		case B_CONTACT_IM:
		case B_CONTACT_URL:
		case B_CONTACT_PHONE:
			child = new BStringContactField(childType);
			break;
		case B_CONTACT_ADDRESS:
			child = new BAddressContactField();
			break;
		case B_CONTACT_PHOTO:
			child = new BPhotoContactField();
			break;

		default:
			return NULL;
	}

	if (child == NULL)
		return NULL;

	status_t ret = child->Unflatten(B_CONTACT_FIELD_TYPE, from, size);
	if (ret == B_OK)
		return child;

	deleter.SetTo(child);
	return NULL;
}
// You cannot instantiate a pure BContactField
// so this method help to unflatten the correct 
// derived class
BContactField*
BContactField::UnflattenChildClass(const void* from, ssize_t size)
{
	BMemoryIO data(from, size);

	type_code childType;
	data.Read(&childType, sizeof(childType));
	ObjectDeleter<BContactField> deleter;
	BContactField* child = NULL;

	child = BContactField::InstantiateChildClass(childType);

	if (child == NULL)
		return NULL;

	status_t ret = child->Unflatten(B_CONTACT_FIELD_TYPE, from, size);
	if (ret == B_OK)
		return child;

	deleter.SetTo(child);
	return NULL;
}
Exemplo n.º 5
0
void
MemoryView::_HandleContextMenu(BPoint point)
{
	int32 offset = _GetOffsetAt(point);
	if (offset < fSelectionStart || offset > fSelectionEnd)
		return;

	BPopUpMenu* menu = new(std::nothrow) BPopUpMenu("Options");
	if (menu == NULL)
		return;

	ObjectDeleter<BPopUpMenu> menuDeleter(menu);
	ObjectDeleter<BMenuItem> itemDeleter;
	ObjectDeleter<BMessage> messageDeleter;
	BMessage* message = NULL;
	BMenuItem* item = NULL;
	if (fSelectionEnd - fSelectionStart == fTargetAddressSize / 2) {
		BMessage* message = new(std::nothrow) BMessage(MSG_INSPECT_ADDRESS);
		if (message == NULL)
			return;

		target_addr_t address;
		if (fTargetAddressSize == 8)
			address = *((uint32*)(fTargetBlock->Data() + fSelectionStart));
		else
			address = *((uint64*)(fTargetBlock->Data() + fSelectionStart));

		if (fCurrentEndianMode == EndianModeBigEndian)
			address = B_HOST_TO_BENDIAN_INT64(address);
		else
			address = B_HOST_TO_LENDIAN_INT64(address);

		messageDeleter.SetTo(message);
		message->AddUInt64("address", address);
		BMenuItem* item = new(std::nothrow) BMenuItem("Inspect", message);
		if (item == NULL)
			return;

		messageDeleter.Detach();
		itemDeleter.SetTo(item);
		if (!menu->AddItem(item))
			return;

		item->SetTarget(Looper());
		itemDeleter.Detach();
	}

	message = new(std::nothrow) BMessage(B_COPY);
	if (message == NULL)
		return;

	messageDeleter.SetTo(message);
	item = new(std::nothrow) BMenuItem("Copy", message);
	if (item == NULL)
		return;

	messageDeleter.Detach();
	itemDeleter.SetTo(item);
	if (!menu->AddItem(item))
		return;

	item->SetTarget(this);
	itemDeleter.Detach();
	menuDeleter.Detach();

	BPoint screenWhere(point);
	ConvertToScreen(&screenWhere);
	BRect mouseRect(screenWhere, screenWhere);
	mouseRect.InsetBy(-4.0, -4.0);
	menu->Go(screenWhere, true, false, mouseRect, true);
}
Exemplo n.º 6
0
status_t
BHttpRequest::_MakeRequest()
{
	delete fSocket;

	if (fSSL)
		fSocket = new(std::nothrow) CheckedSecureSocket(this);
	else
		fSocket = new(std::nothrow) BSocket();

	if (fSocket == NULL)
		return B_NO_MEMORY;

	_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection to %s on port %d.",
		fUrl.Authority().String(), fRemoteAddr.Port());
	status_t connectError = fSocket->Connect(fRemoteAddr);

	if (connectError != B_OK) {
		_EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR, "Socket connection error %s",
			strerror(connectError));
		return connectError;
	}

	//! ProtocolHook:ConnectionOpened
	if (fListener != NULL)
		fListener->ConnectionOpened(this);

	_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT,
		"Connection opened, sending request.");

	_SendRequest();
	_SendHeaders();
	fSocket->Write("\r\n", 2);
	_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Request sent.");

	_SendPostData();
	fRequestStatus = kRequestInitialState;



	// Receive loop
	bool receiveEnd = false;
	bool parseEnd = false;
	bool readByChunks = false;
	bool decompress = false;
	status_t readError = B_OK;
	ssize_t bytesRead = 0;
	ssize_t bytesReceived = 0;
	ssize_t bytesTotal = 0;
	off_t bytesUnpacked = 0;
	char* inputTempBuffer = new(std::nothrow) char[kHttpBufferSize];
	ssize_t inputTempSize = kHttpBufferSize;
	ssize_t chunkSize = -1;
	DynamicBuffer decompressorStorage;
	BDataIO* decompressingStream;
	ObjectDeleter<BDataIO> decompressingStreamDeleter;

	while (!fQuit && !(receiveEnd && parseEnd)) {
		if (!receiveEnd) {
			fSocket->WaitForReadable();
			BStackOrHeapArray<char, 4096> chunk(kHttpBufferSize);
			bytesRead = fSocket->Read(chunk, kHttpBufferSize);

			if (bytesRead < 0) {
				readError = bytesRead;
				break;
			} else if (bytesRead == 0)
				receiveEnd = true;

			fInputBuffer.AppendData(chunk, bytesRead);
		} else
			bytesRead = 0;

		if (fRequestStatus < kRequestStatusReceived) {
			_ParseStatus();

			//! ProtocolHook:ResponseStarted
			if (fRequestStatus >= kRequestStatusReceived && fListener != NULL)
				fListener->ResponseStarted(this);
		}

		if (fRequestStatus < kRequestHeadersReceived) {
			_ParseHeaders();

			if (fRequestStatus >= kRequestHeadersReceived) {
				_ResultHeaders() = fHeaders;

				//! ProtocolHook:HeadersReceived
				if (fListener != NULL)
					fListener->HeadersReceived(this);

				// Parse received cookies
				if (fContext != NULL) {
					for (int32 i = 0;  i < fHeaders.CountHeaders(); i++) {
						if (fHeaders.HeaderAt(i).NameIs("Set-Cookie")) {
							fContext->GetCookieJar().AddCookie(
								fHeaders.HeaderAt(i).Value(), fUrl);
						}
					}
				}

				if (BString(fHeaders["Transfer-Encoding"]) == "chunked")
					readByChunks = true;

				BString contentEncoding(fHeaders["Content-Encoding"]);
				// We don't advertise "deflate" support (see above), but we
				// still try to decompress it, if a server ever sends a deflate
				// stream despite it not being in our Accept-Encoding list.
				if (contentEncoding == "gzip"
						|| contentEncoding == "deflate") {
					decompress = true;
					readError = BZlibCompressionAlgorithm()
						.CreateDecompressingOutputStream(&decompressorStorage,
							NULL, decompressingStream);
					if (readError != B_OK)
						break;

					decompressingStreamDeleter.SetTo(decompressingStream);
				}

				int32 index = fHeaders.HasHeader("Content-Length");
				if (index != B_ERROR)
					bytesTotal = atoi(fHeaders.HeaderAt(index).Value());
				else
					bytesTotal = -1;
			}
		}

		if (fRequestStatus >= kRequestHeadersReceived) {
			// If Transfer-Encoding is chunked, we should read a complete
			// chunk in buffer before handling it
			if (readByChunks) {
				if (chunkSize >= 0) {
					if ((ssize_t)fInputBuffer.Size() >= chunkSize + 2) {
							// 2 more bytes to handle the closing CR+LF
						bytesRead = chunkSize;
						if (inputTempSize < chunkSize + 2) {
							delete[] inputTempBuffer;
							inputTempSize = chunkSize + 2;
							inputTempBuffer
								= new(std::nothrow) char[inputTempSize];
						}

						if (inputTempBuffer == NULL) {
							readError = B_NO_MEMORY;
							break;
						}

						fInputBuffer.RemoveData(inputTempBuffer,
							chunkSize + 2);
						chunkSize = -1;
					} else {
						// Not enough data, try again later
						bytesRead = -1;
					}
				} else {
					BString chunkHeader;
					if (_GetLine(chunkHeader) == B_ERROR) {
						chunkSize = -1;
						bytesRead = -1;
					} else {
						// Format of a chunk header:
						// <chunk size in hex>[; optional data]
						int32 semiColonIndex = chunkHeader.FindFirst(';', 0);

						// Cut-off optional data if present
						if (semiColonIndex != -1) {
							chunkHeader.Remove(semiColonIndex,
								chunkHeader.Length() - semiColonIndex);
						}

						chunkSize = strtol(chunkHeader.String(), NULL, 16);
						PRINT(("BHP[%p] Chunk %s=%ld\n", this,
							chunkHeader.String(), chunkSize));
						if (chunkSize == 0)
							fRequestStatus = kRequestContentReceived;

						bytesRead = -1;
					}
				}

				// A chunk of 0 bytes indicates the end of the chunked transfer
				if (bytesRead == 0)
					receiveEnd = true;
			} else {
				bytesRead = fInputBuffer.Size();

				if (bytesRead > 0) {
					if (inputTempSize < bytesRead) {
						inputTempSize = bytesRead;
						delete[] inputTempBuffer;
						inputTempBuffer = new(std::nothrow) char[bytesRead];
					}

					if (inputTempBuffer == NULL) {
						readError = B_NO_MEMORY;
						break;
					}
					fInputBuffer.RemoveData(inputTempBuffer, bytesRead);
				}
			}

			if (bytesRead >= 0) {
				bytesReceived += bytesRead;

				if (fListener != NULL) {
					if (decompress) {
						readError = decompressingStream->WriteExactly(
							inputTempBuffer, bytesRead);
						if (readError != B_OK)
							break;

						ssize_t size = decompressorStorage.Size();
						BStackOrHeapArray<char, 4096> buffer(size);
						size = decompressorStorage.Read(buffer, size);
						if (size > 0) {
							fListener->DataReceived(this, buffer, bytesUnpacked,
								size);
							bytesUnpacked += size;
						}
					} else if (bytesRead > 0) {
						fListener->DataReceived(this, inputTempBuffer,
							bytesReceived - bytesRead, bytesRead);
					}
					fListener->DownloadProgress(this, bytesReceived,
						std::max((ssize_t)0, bytesTotal));
				}

				if (bytesTotal >= 0 && bytesReceived >= bytesTotal)
					receiveEnd = true;

				if (decompress && receiveEnd) {
					readError = decompressingStream->Flush();

					if (readError == B_BUFFER_OVERFLOW)
						readError = B_OK;

					if (readError != B_OK)
						break;

					ssize_t size = decompressorStorage.Size();
					BStackOrHeapArray<char, 4096> buffer(size);
					size = decompressorStorage.Read(buffer, size);
					if (fListener != NULL && size > 0) {
						fListener->DataReceived(this, buffer,
							bytesUnpacked, size);
						bytesUnpacked += size;
					}
				}
			}
		}

		parseEnd = (fInputBuffer.Size() == 0);
	}

	fSocket->Disconnect();
	delete[] inputTempBuffer;

	if (readError != B_OK)
		return readError;

	return fQuit ? B_INTERRUPTED : B_OK;
}
Exemplo n.º 7
0
status_t
Architecture::CreateStackTrace(Team* team,
                               ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
                               StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace)
{
    BReference<CpuState> cpuStateReference(cpuState);

    StackTrace* stackTrace = NULL;
    ObjectDeleter<StackTrace> stackTraceDeleter;
    StackFrame* frame = NULL;

    if (useExistingTrace)
        stackTrace = _stackTrace;
    else {
        // create the object
        stackTrace = new(std::nothrow) StackTrace;
        if (stackTrace == NULL)
            return B_NO_MEMORY;
        stackTraceDeleter.SetTo(stackTrace);
    }

    // if we're passed an already existing partial stack trace,
    // attempt to continue building it from where it left off.
    if (stackTrace->CountFrames() > 0) {
        frame = stackTrace->FrameAt(stackTrace->CountFrames() - 1);
        cpuState = frame->GetCpuState();
    }

    while (cpuState != NULL) {
        // get the instruction pointer
        target_addr_t instructionPointer = cpuState->InstructionPointer();
        if (instructionPointer == 0)
            break;

        // get the image for the instruction pointer
        AutoLocker<Team> teamLocker(team);
        Image* image = team->ImageByAddress(instructionPointer);
        BReference<Image> imageReference(image);
        teamLocker.Unlock();

        // get the image debug info
        ImageDebugInfo* imageDebugInfo = NULL;
        if (image != NULL)
            imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo);
        BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo,
                true);

        // get the function
        teamLocker.Lock();
        FunctionInstance* function = NULL;
        FunctionDebugInfo* functionDebugInfo = NULL;
        if (imageDebugInfo != NULL) {
            function = imageDebugInfo->FunctionAtAddress(instructionPointer);
            if (function != NULL)
                functionDebugInfo = function->GetFunctionDebugInfo();
        }
        BReference<FunctionInstance> functionReference(function);
        teamLocker.Unlock();

        // If the CPU state's instruction pointer is actually the return address
        // of the next frame, we let the architecture fix that.
        if (frame != NULL
                && frame->ReturnAddress() == cpuState->InstructionPointer()) {
            UpdateStackFrameCpuState(frame, image,
                                     functionDebugInfo, cpuState);
        }

        // create the frame using the debug info
        StackFrame* previousFrame = NULL;
        CpuState* previousCpuState = NULL;
        if (function != NULL) {
            status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
                             ->CreateFrame(image, function, cpuState, previousFrame,
                                           previousCpuState);
            if (error != B_OK && error != B_UNSUPPORTED)
                break;
        }

        // If we have no frame yet, let the architecture create it.
        if (previousFrame == NULL) {
            status_t error = CreateStackFrame(image, functionDebugInfo,
                                              cpuState, frame == NULL, previousFrame, previousCpuState);
            if (error != B_OK)
                break;
        }

        cpuStateReference.SetTo(previousCpuState, true);

        previousFrame->SetImage(image);
        previousFrame->SetFunction(function);

        if (!stackTrace->AddFrame(previousFrame)) {
            delete previousFrame;
            return B_NO_MEMORY;
        }

        frame = previousFrame;
        cpuState = previousCpuState;
        if (--maxStackDepth == 0)
            break;
    }

    stackTraceDeleter.Detach();
    _stackTrace = stackTrace;
    return B_OK;
}
Exemplo n.º 8
0
/*static*/ status_t
Inode::Create(Transaction& transaction, Inode* parent, const char* name,
	int32 mode, int openMode, uint8 type, bool* _created, ino_t* _id,
	Inode** _inode, fs_vnode_ops* vnodeOps, uint32 publishFlags)
{
	TRACE("Inode::Create()\n");
	Volume* volume = transaction.GetVolume();

	DirectoryIterator* entries = NULL;
	ObjectDeleter<DirectoryIterator> entriesDeleter;

	if (parent != NULL) {
		parent->WriteLockInTransaction(transaction);

		TRACE("Inode::Create(): Looking up entry destination\n");
		HTree htree(volume, parent);

		status_t status = htree.Lookup(name, &entries);
		if (status == B_ENTRY_NOT_FOUND) {
			panic("We need to add the first node.\n");
			return B_ERROR;
		}
		if (status != B_OK)
			return status;
		entriesDeleter.SetTo(entries);

		TRACE("Inode::Create(): Looking up to see if file already exists\n");
		ino_t entryID;

		status = entries->FindEntry(name, &entryID);
		if (status == B_OK) {
			// File already exists
			TRACE("Inode::Create(): File already exists\n");
			if (S_ISDIR(mode) || S_ISLNK(mode) || (openMode & O_EXCL) != 0)
				return B_FILE_EXISTS;

			Vnode vnode(volume, entryID);
			Inode* inode;

			status = vnode.Get(&inode);
			if (status != B_OK) {
				TRACE("Inode::Create() Failed to get the inode from the "
					"vnode\n");
				return B_ENTRY_NOT_FOUND;
			}

			if (inode->IsDirectory() && (openMode & O_RWMASK) != O_RDONLY)
				return B_IS_A_DIRECTORY;
			if ((openMode & O_DIRECTORY) != 0 && !inode->IsDirectory())
				return B_NOT_A_DIRECTORY;

			if (inode->CheckPermissions(open_mode_to_access(openMode)
					| ((openMode & O_TRUNC) != 0 ? W_OK : 0)) != B_OK)
				return B_NOT_ALLOWED;

			if ((openMode & O_TRUNC) != 0) {
				// Truncate requested
				TRACE("Inode::Create(): Truncating file\n");
				inode->WriteLockInTransaction(transaction);

				status = inode->Resize(transaction, 0);
				if (status != B_OK)
					return status;
			}

			if (_created != NULL)
				*_created = false;
			if (_id != NULL)
				*_id = inode->ID();
			if (_inode != NULL)
				*_inode = inode;

			if (_id != NULL || _inode != NULL)
				vnode.Keep();

			TRACE("Inode::Create(): Done opening file\n");
			return B_OK;
		/*} else if ((mode & S_ATTR_DIR) == 0) {
			TRACE("Inode::Create(): (mode & S_ATTR_DIR) == 0\n");
			return B_BAD_VALUE;*/
		} else if ((openMode & O_DIRECTORY) != 0) {
			TRACE("Inode::Create(): (openMode & O_DIRECTORY) != 0\n");
			return B_ENTRY_NOT_FOUND;
		}

		// Return to initial position
		TRACE("Inode::Create(): Restarting iterator\n");
		entries->Restart();
	}

	status_t status;
	if (parent != NULL) {
		status = parent->CheckPermissions(W_OK);
		if (status != B_OK)
			return status;
	}

	TRACE("Inode::Create(): Allocating inode\n");
	ino_t id;
	status = volume->AllocateInode(transaction, parent, mode, id);
	if (status != B_OK) {
		ERROR("Inode::Create(): AllocateInode() failed\n");
		return status;
	}

	if (entries != NULL) {
		size_t nameLength = strlen(name);
		status = entries->AddEntry(transaction, name, nameLength, id, type);
		if (status != B_OK) {
			ERROR("Inode::Create(): AddEntry() failed\n");
			return status;
		}
	}

	TRACE("Inode::Create(): Creating inode\n");
	Inode* inode = new(std::nothrow) Inode(volume);
	if (inode == NULL)
		return B_NO_MEMORY;

	TRACE("Inode::Create(): Getting node structure\n");
	ext2_inode& node = inode->Node();
	TRACE("Inode::Create(): Initializing inode data\n");
	memset(&node, 0, sizeof(ext2_inode));
	node.SetMode(mode);
	node.SetUserID(geteuid());
	node.SetGroupID(parent != NULL ? parent->Node().GroupID() : getegid());
	node.SetNumLinks(inode->IsDirectory() ? 2 : 1);
	TRACE("Inode::Create(): Updating time\n");
	struct timespec timespec;
	_BigtimeToTimespec(real_time_clock_usecs(), &timespec);
	inode->SetAccessTime(&timespec);
	inode->SetCreationTime(&timespec);
	inode->SetModificationTime(&timespec);
	node.SetFlags(parent->Flags() & EXT2_INODE_INHERITED);
	if (volume->HasExtentsFeature() 
		&& (inode->IsDirectory() || inode->IsFile())) {
		node.SetFlag(EXT2_INODE_EXTENTS);
		ExtentStream stream(volume, &node.extent_stream, 0);
		stream.Init();
		ASSERT(stream.Check());
	}

	if (sizeof(ext2_inode) < volume->InodeSize())
		node.SetExtraInodeSize(sizeof(ext2_inode) - EXT2_INODE_NORMAL_SIZE);

	TRACE("Inode::Create(): Updating ID\n");
	inode->fID = id;

	if (inode->IsDirectory()) {
		TRACE("Inode::Create(): Initializing directory\n");
		status = inode->InitDirectory(transaction, parent);
		if (status != B_OK) {
			ERROR("Inode::Create(): InitDirectory() failed\n");
			delete inode;
			return status;
		}
	}

	// TODO: Maybe it can be better
	/*if (volume->HasExtendedAttributes()) {
		TRACE("Inode::Create(): Initializing extended attributes\n");
		uint32 blockGroup = 0;
		uint32 pos = 0;
		uint32 allocated;

		status = volume->AllocateBlocks(transaction, 1, 1, blockGroup, pos,
			allocated);
		if (status != B_OK)
			return status;

		// Clear the new block
		uint32 blockNum = volume->FirstDataBlock() + pos +
			volume->BlocksPerGroup() * blockGroup;
		CachedBlock cached(volume);
		cached.SetToWritable(transaction, blockNum, true);

		node.SetExtendedAttributesBlock(blockNum);
	}*/

	TRACE("Inode::Create(): Saving inode\n");
	status = inode->WriteBack(transaction);
	if (status != B_OK) {
		delete inode;
		return status;
	}

	TRACE("Inode::Create(): Creating vnode\n");

	Vnode vnode;
	status = vnode.Publish(transaction, inode, vnodeOps, publishFlags);
	if (status != B_OK)
		return status;

	if (!inode->IsSymLink()) {
		// Vnode::Publish doesn't publish symlinks
		if (!inode->IsDirectory()) {
			status = inode->EnableFileCache();
			if (status != B_OK)
				return status;
		}

		inode->WriteLockInTransaction(transaction);
	}

	if (_created)
		*_created = true;
	if (_id != NULL)
		*_id = id;
	if (_inode != NULL)
		*_inode = inode;

	if (_id != NULL || _inode != NULL)
		vnode.Keep();

	TRACE("Inode::Create(): Deleting entries iterator\n");
	DirectoryIterator* iterator = entriesDeleter.Detach();
	TRACE("Inode::Create(): Entries iterator: %p\n", entries);
	delete iterator;
	TRACE("Inode::Create(): Done\n");

	return B_OK;
}
Exemplo n.º 9
0
status_t
MessagingService::_AllocateCommand(int32 commandWhat, int32 size,
	MessagingArea *&area, void *&data, bool &wasEmpty)
{
	if (!fFirstArea)
		return B_NO_INIT;

	if (!MessagingArea::CheckCommandSize(size))
		return B_BAD_VALUE;

	// delete the discarded areas (save one)
	ObjectDeleter<MessagingArea> discardedAreaDeleter;
	MessagingArea *discardedArea = NULL;

	while (fFirstArea != fLastArea) {
		area = fFirstArea;
		area->Lock();
		if (!area->IsEmpty()) {
			area->Unlock();
			break;
		}

		PRINT(("MessagingService::_AllocateCommand(): Discarding area: %p\n",
			area));

		fFirstArea = area->NextArea();
		area->SetNextArea(NULL);
		discardedArea = area;
		discardedAreaDeleter.SetTo(area);
	}

	// allocate space for the command in the last area
	area = fLastArea;
	area->Lock();
	data = area->AllocateCommand(commandWhat, size, wasEmpty);

	if (!data) {
		// not enough space in the last area: create a new area or reuse a
		// discarded one
		if (discardedArea) {
			area = discardedAreaDeleter.Detach();
			area->InitHeader();
			PRINT(("MessagingService::_AllocateCommand(): Not enough space "
				"left in current area. Recycling discarded one: %p\n", area));
		} else {
			area = MessagingArea::Create(fLockSem, fCounterSem);
			PRINT(("MessagingService::_AllocateCommand(): Not enough space "
				"left in current area. Allocated new one: %p\n", area));
		}
		if (!area) {
			fLastArea->Unlock();
			return B_NO_MEMORY;
		}

		// add the new area
		fLastArea->SetNextArea(area);
		fLastArea->Unlock();
		fLastArea = area;

		// allocate space for the command
		data = area->AllocateCommand(commandWhat, size, wasEmpty);

		if (!data) {
			// that should never happen
			area->Unlock();
			return B_NO_MEMORY;
		}
	}

	return B_OK;
}