<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2019 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#define CAF_SUITE transport_worker_dispatcher

#include "caf/net/transport_worker_dispatcher.hpp"

#include "caf/test/dsl.hpp"

#include "host_fixture.hpp"

#include "caf/make_actor.hpp"
#include "caf/monitorable_actor.hpp"
#include "caf/node_id.hpp"
#include "caf/uri.hpp"

using namespace caf;
using namespace caf::net;

namespace {

struct dummy_actor : public monitorable_actor {
  dummy_actor(actor_config& cfg) : monitorable_actor(cfg) {
    // nop
  }

  void enqueue(mailbox_element_ptr, execution_unit*) override {
    // nop
  }
};

class dummy_application {
public:
  dummy_application(std::shared_ptr<std::vector<byte>> rec_buf, uint8_t id)
    : rec_buf_(std::move(rec_buf)),
      id_(id){
        // nop
      };

  ~dummy_application() = default;

  template <class Parent>
  error init(Parent&) {
    return none;
  }

  template <class Transport>
  void write_message(Transport&, std::unique_ptr<endpoint_manager::message>) {
    rec_buf_->push_back(static_cast<byte>(id_));
  }

  template <class Parent>
  void handle_data(Parent&, span<const byte>) {
    rec_buf_->push_back(static_cast<byte>(id_));
  }

  template <class Manager>
  void resolve(Manager&, const std::string&, actor) {
    // nop
  }

  template <class Transport>
  void timeout(Transport&, atom_value, uint64_t) {
    // nop
  }

  void handle_error(sec) {
    // nop
  }

  static expected<std::vector<byte>> serialize(actor_system&,
                                               const type_erased_tuple&) {
    return std::vector<byte>{};
    // nop
  }

private:
  std::shared_ptr<std::vector<byte>> rec_buf_;
  uint8_t id_;
};

struct dummy_application_factory {
public:
  using application_type = dummy_application;

  dummy_application_factory(std::shared_ptr<std::vector<byte>> buf)
    : buf_(buf), application_cnt_(0) {
    // nop
  }

  dummy_application make() {
    return dummy_application{buf_, application_cnt_++};
  }

private:
  std::shared_ptr<std::vector<byte>> buf_;
  uint8_t application_cnt_;
};

struct testdata {
  testdata(uint8_t worker_id, node_id id, ip_endpoint ep)
    : worker_id(worker_id), nid(id), ep(ep) {
    // nop
  }

  uint8_t worker_id;
  node_id nid;
  ip_endpoint ep;
};

struct dummy {
  using transport_type = dummy;

  using application_type = dummy_application;
};

// TODO: switch to std::operator""s when switching to C++14
ip_endpoint operator"" _ep(const char* cstr, size_t cstr_len) {
  ip_endpoint ep;
  string_view str(cstr, cstr_len);
  if (auto err = parse(str, ep))
    CAF_FAIL("parse returned error: " << err);
  return ep;
}

uri operator"" _u(const char* cstr, size_t cstr_len) {
  uri result;
  string_view str{cstr, cstr_len};
  auto err = parse(str, result);
  if (err)
    CAF_FAIL("error while parsing " << str << ": " << to_string(err));
  return result;
}

struct fixture : host_fixture {
  using dispatcher_type = transport_worker_dispatcher<dummy_application_factory,
                                                      ip_endpoint>;

  fixture()
    : buf{std::make_shared<std::vector<byte>>()},
      dispatcher{dummy_application_factory{buf}} {
    // nop
  }

  std::unique_ptr<net::endpoint_manager::message>
  make_dummy_message(node_id nid) {
    actor_id aid = 42;
    actor_config cfg;
    auto p = make_actor<dummy_actor, strong_actor_ptr>(aid, nid, &sys, cfg);
    std::vector<byte> payload;
    auto strong_actor = actor_cast<strong_actor_ptr>(p);
    mailbox_element::forwarding_stack stack;
    auto elem = make_mailbox_element(std::move(strong_actor),
                                     make_message_id(12345), std::move(stack),
                                     make_message());
    return detail::make_unique<endpoint_manager::message>(std::move(elem),
                                                          payload);
  }

  template <class Application, class IdType>
  void add_new_workers(
    transport_worker_dispatcher<Application, IdType>& dispatcher) {
    for (auto& data : test_data) {
      dispatcher.add_new_worker(data.nid, data.ep);
    }
  }

  void test_write_message(testdata& testcase) {
    auto msg = make_dummy_message(testcase.nid);
    if (!msg->msg->sender)
      CAF_FAIL("sender is null");
    dispatcher.add_new_worker(testcase.nid, "[::1]:1"_ep);
    dispatcher.write_message(dummy, std::move(msg));
  }

  actor_system_config cfg{};
  actor_system sys{cfg};

  std::shared_ptr<std::vector<byte>> buf;
  dispatcher_type dispatcher;
  dummy dummy;

  std::vector<testdata> test_data{
    {0, make_node_id("http:file"_u), "[::1]:1"_ep},
    {1, make_node_id("http:file?a=1&b=2"_u), "[fe80::2:34]:12345"_ep},
    {2, make_node_id("http:file#42"_u), "[1234::17]:4444"_ep},
    {3, make_node_id("http:file?a=1&b=2#42"_u), "[2332::1]:12"_ep},
  };
};

#define CHECK_HANDLE_DATA(dispatcher, dummy, testcase, buf)                    \
  dispatcher.handle_data(dummy, span<byte>{}, testcase.ep);                    \
  CAF_CHECK_EQUAL(buf->size(), 1u);                                            \
  CAF_CHECK_EQUAL(static_cast<byte>(testcase.worker_id), buf->at(0));          \
  buf->clear();

#define CHECK_WRITE_MESSAGE(dispatcher, dummy, testcase, buf)                  \
  test_write_message(testcase);                                                \
  CAF_CHECK_EQUAL(buf->size(), 1u);                                            \
  CAF_CHECK_EQUAL(static_cast<byte>(testcase.worker_id), buf->at(0));          \
  buf->clear();

} // namespace

CAF_TEST_FIXTURE_SCOPE(transport_worker_dispatcher_test, fixture)

CAF_TEST(handle_data) {
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(0), buf);
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(1), buf);
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(2), buf);
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(3), buf);
}

CAF_TEST(write_message) {
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(0), buf);
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(1), buf);
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(2), buf);
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(3), buf);
}

CAF_TEST_FIXTURE_SCOPE_END()
<commit_msg>Fix Linux builds<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2019 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#define CAF_SUITE transport_worker_dispatcher

#include "caf/net/transport_worker_dispatcher.hpp"

#include "caf/test/dsl.hpp"

#include "host_fixture.hpp"

#include "caf/make_actor.hpp"
#include "caf/monitorable_actor.hpp"
#include "caf/node_id.hpp"
#include "caf/uri.hpp"

using namespace caf;
using namespace caf::net;

namespace {

struct dummy_actor : public monitorable_actor {
  dummy_actor(actor_config& cfg) : monitorable_actor(cfg) {
    // nop
  }

  void enqueue(mailbox_element_ptr, execution_unit*) override {
    // nop
  }
};

class dummy_application {
public:
  dummy_application(std::shared_ptr<std::vector<byte>> rec_buf, uint8_t id)
    : rec_buf_(std::move(rec_buf)),
      id_(id){
        // nop
      };

  ~dummy_application() = default;

  template <class Parent>
  error init(Parent&) {
    return none;
  }

  template <class Transport>
  void write_message(Transport&, std::unique_ptr<endpoint_manager::message>) {
    rec_buf_->push_back(static_cast<byte>(id_));
  }

  template <class Parent>
  void handle_data(Parent&, span<const byte>) {
    rec_buf_->push_back(static_cast<byte>(id_));
  }

  template <class Manager>
  void resolve(Manager&, const std::string&, actor) {
    // nop
  }

  template <class Transport>
  void timeout(Transport&, atom_value, uint64_t) {
    // nop
  }

  void handle_error(sec) {
    // nop
  }

  static expected<std::vector<byte>> serialize(actor_system&,
                                               const type_erased_tuple&) {
    return std::vector<byte>{};
    // nop
  }

private:
  std::shared_ptr<std::vector<byte>> rec_buf_;
  uint8_t id_;
};

struct dummy_application_factory {
public:
  using application_type = dummy_application;

  dummy_application_factory(std::shared_ptr<std::vector<byte>> buf)
    : buf_(buf), application_cnt_(0) {
    // nop
  }

  dummy_application make() {
    return dummy_application{buf_, application_cnt_++};
  }

private:
  std::shared_ptr<std::vector<byte>> buf_;
  uint8_t application_cnt_;
};

struct testdata {
  testdata(uint8_t worker_id, node_id id, ip_endpoint ep)
    : worker_id(worker_id), nid(id), ep(ep) {
    // nop
  }

  uint8_t worker_id;
  node_id nid;
  ip_endpoint ep;
};

struct dummy_transport {
  using transport_type = dummy_transport;

  using application_type = dummy_application;
};

// TODO: switch to std::operator""s when switching to C++14
ip_endpoint operator"" _ep(const char* cstr, size_t cstr_len) {
  ip_endpoint ep;
  string_view str(cstr, cstr_len);
  if (auto err = parse(str, ep))
    CAF_FAIL("parse returned error: " << err);
  return ep;
}

uri operator"" _u(const char* cstr, size_t cstr_len) {
  uri result;
  string_view str{cstr, cstr_len};
  auto err = parse(str, result);
  if (err)
    CAF_FAIL("error while parsing " << str << ": " << to_string(err));
  return result;
}

struct fixture : host_fixture {
  using dispatcher_type = transport_worker_dispatcher<dummy_application_factory,
                                                      ip_endpoint>;

  fixture()
    : buf{std::make_shared<std::vector<byte>>()},
      dispatcher{dummy_application_factory{buf}} {
    // nop
  }

  std::unique_ptr<net::endpoint_manager::message>
  make_dummy_message(node_id nid) {
    actor_id aid = 42;
    actor_config cfg;
    auto p = make_actor<dummy_actor, strong_actor_ptr>(aid, nid, &sys, cfg);
    std::vector<byte> payload;
    auto strong_actor = actor_cast<strong_actor_ptr>(p);
    mailbox_element::forwarding_stack stack;
    auto elem = make_mailbox_element(std::move(strong_actor),
                                     make_message_id(12345), std::move(stack),
                                     make_message());
    return detail::make_unique<endpoint_manager::message>(std::move(elem),
                                                          payload);
  }

  template <class Application, class IdType>
  void add_new_workers(
    transport_worker_dispatcher<Application, IdType>& dispatcher) {
    for (auto& data : test_data) {
      dispatcher.add_new_worker(data.nid, data.ep);
    }
  }

  void test_write_message(testdata& testcase) {
    auto msg = make_dummy_message(testcase.nid);
    if (!msg->msg->sender)
      CAF_FAIL("sender is null");
    dispatcher.add_new_worker(testcase.nid, "[::1]:1"_ep);
    dispatcher.write_message(dummy, std::move(msg));
  }

  actor_system_config cfg{};
  actor_system sys{cfg};

  std::shared_ptr<std::vector<byte>> buf;
  dispatcher_type dispatcher;
  dummy_transport dummy;

  std::vector<testdata> test_data{
    {0, make_node_id("http:file"_u), "[::1]:1"_ep},
    {1, make_node_id("http:file?a=1&b=2"_u), "[fe80::2:34]:12345"_ep},
    {2, make_node_id("http:file#42"_u), "[1234::17]:4444"_ep},
    {3, make_node_id("http:file?a=1&b=2#42"_u), "[2332::1]:12"_ep},
  };
};

#define CHECK_HANDLE_DATA(dispatcher, dummy, testcase, buf)                    \
  dispatcher.handle_data(dummy, span<byte>{}, testcase.ep);                    \
  CAF_CHECK_EQUAL(buf->size(), 1u);                                            \
  CAF_CHECK_EQUAL(static_cast<byte>(testcase.worker_id), buf->at(0));          \
  buf->clear();

#define CHECK_WRITE_MESSAGE(dispatcher, dummy, testcase, buf)                  \
  test_write_message(testcase);                                                \
  CAF_CHECK_EQUAL(buf->size(), 1u);                                            \
  CAF_CHECK_EQUAL(static_cast<byte>(testcase.worker_id), buf->at(0));          \
  buf->clear();

} // namespace

CAF_TEST_FIXTURE_SCOPE(transport_worker_dispatcher_test, fixture)

CAF_TEST(handle_data) {
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(0), buf);
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(1), buf);
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(2), buf);
  CHECK_HANDLE_DATA(dispatcher, dummy, test_data.at(3), buf);
}

CAF_TEST(write_message) {
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(0), buf);
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(1), buf);
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(2), buf);
  CHECK_WRITE_MESSAGE(dispatcher, dummy, test_data.at(3), buf);
}

CAF_TEST_FIXTURE_SCOPE_END()
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright 2016 [bk]door.maus

#include <limits>
#include <glm/gtc/type_ptr.hpp>
#include "glurg/resources/mesh/meshResource.hpp"
#include "glurg/resources/mesh/meshResourceBlob.hpp"

glurg::MeshResource::MeshResource(const MeshResourceBlob* blob)
{
	this->blob = blob;
}

std::size_t glurg::MeshResource::get_num_values() const
{
	std::size_t size = this->blob->get_vertex_data_size();
	auto description = this->blob->get_vertex_description();

	return size / description.stride;
}

glm::vec4 glurg::MeshResource::get_value(std::size_t index) const
{
	glm::vec4 v;
	get_values(index, 1, &v);

	return v;
}

template<typename Integer>
float glurg_next_integer_value(
	const std::uint8_t*& input_data, bool normalized)
{
	Integer v = *((const Integer*)input_data);
	input_data += sizeof(Integer);

	if (normalized)
	{
		if (v < 0)
		{
			return v * (-1.0f / std::numeric_limits<Integer>::min());
		}
		else if (v > 0)
		{
			return v * (1.0f / std::numeric_limits<Integer>::max());
		}
	}

	return v;
}

void glurg::MeshResource::get_values(
	std::size_t index, std::size_t count, glm::vec4 output[]) const
{
	if (index + count > get_num_values())
	{
		throw std::runtime_error("requested values exceeds bounds");
	}

	auto description = this->blob->get_vertex_description();
	const std::uint8_t* data =
		this->blob->get_vertex_data() + description.offset;
	for (std::size_t i = 0; i < count; ++i)
	{
		const std::uint8_t* element = data + ((i + index) * description.stride);

		glm::vec4 result(0.0f, 0.0f, 0.0f, 0.0f);
		auto r = glm::value_ptr(result);
		for (std::size_t j = 0; j < description.num_components; ++j)
		{
			bool n = (description.normalized ==
				VertexDescription::normalization_enabled);
			switch (description.format)
			{
				case VertexDescription::format_float:
					r[j] = *((const float*)element);
					element += sizeof(float);
					break;
				case VertexDescription::format_byte:
					r[j] = glurg_next_integer_value<std::int8_t>(element, n);
					break;
				case VertexDescription::format_unsigned_byte:
					r[j] = glurg_next_integer_value<std::uint8_t>(element, n);
					break;
				case VertexDescription::format_short:
					r[j] = glurg_next_integer_value<std::int16_t>(element, n);
					break;
				case VertexDescription::format_unsigned_short:
					r[j] = glurg_next_integer_value<std::uint16_t>(element, n);
					break;
				case VertexDescription::format_integer:
					r[j] = glurg_next_integer_value<std::int32_t>(element, n);
					break;
				case VertexDescription::format_unsigned_integer:
					r[j] = glurg_next_integer_value<std::uint32_t>(element, n);
					break;
				default:
					assert(false);
			}

			// Sanitize.
			if (std::isnan(r[j]))
			{
				r[j] = 0.0f;
			}
		}

		output[i] = result;
	}
}

const glurg::ResourceBlob* glurg::MeshResource::get_blob() const
{
	return this->blob;
}
<commit_msg>Also include sanitizing INF.<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright 2016 [bk]door.maus

#include <limits>
#include <glm/gtc/type_ptr.hpp>
#include "glurg/resources/mesh/meshResource.hpp"
#include "glurg/resources/mesh/meshResourceBlob.hpp"

glurg::MeshResource::MeshResource(const MeshResourceBlob* blob)
{
	this->blob = blob;
}

std::size_t glurg::MeshResource::get_num_values() const
{
	std::size_t size = this->blob->get_vertex_data_size();
	auto description = this->blob->get_vertex_description();

	return size / description.stride;
}

glm::vec4 glurg::MeshResource::get_value(std::size_t index) const
{
	glm::vec4 v;
	get_values(index, 1, &v);

	return v;
}

template<typename Integer>
float glurg_next_integer_value(
	const std::uint8_t*& input_data, bool normalized)
{
	Integer v = *((const Integer*)input_data);
	input_data += sizeof(Integer);

	if (normalized)
	{
		if (v < 0)
		{
			return v * (-1.0f / std::numeric_limits<Integer>::min());
		}
		else if (v > 0)
		{
			return v * (1.0f / std::numeric_limits<Integer>::max());
		}
	}

	return v;
}

void glurg::MeshResource::get_values(
	std::size_t index, std::size_t count, glm::vec4 output[]) const
{
	if (index + count > get_num_values())
	{
		throw std::runtime_error("requested values exceeds bounds");
	}

	auto description = this->blob->get_vertex_description();
	const std::uint8_t* data =
		this->blob->get_vertex_data() + description.offset;
	for (std::size_t i = 0; i < count; ++i)
	{
		const std::uint8_t* element = data + ((i + index) * description.stride);

		glm::vec4 result(0.0f, 0.0f, 0.0f, 0.0f);
		auto r = glm::value_ptr(result);
		for (std::size_t j = 0; j < description.num_components; ++j)
		{
			bool n = (description.normalized ==
				VertexDescription::normalization_enabled);
			switch (description.format)
			{
				case VertexDescription::format_float:
					r[j] = *((const float*)element);
					element += sizeof(float);
					break;
				case VertexDescription::format_byte:
					r[j] = glurg_next_integer_value<std::int8_t>(element, n);
					break;
				case VertexDescription::format_unsigned_byte:
					r[j] = glurg_next_integer_value<std::uint8_t>(element, n);
					break;
				case VertexDescription::format_short:
					r[j] = glurg_next_integer_value<std::int16_t>(element, n);
					break;
				case VertexDescription::format_unsigned_short:
					r[j] = glurg_next_integer_value<std::uint16_t>(element, n);
					break;
				case VertexDescription::format_integer:
					r[j] = glurg_next_integer_value<std::int32_t>(element, n);
					break;
				case VertexDescription::format_unsigned_integer:
					r[j] = glurg_next_integer_value<std::uint32_t>(element, n);
					break;
				default:
					assert(false);
			}

			// Sanitize.
			if (std::isnan(r[j]) || std::isinf(r[j]))
			{
				r[j] = 0.0f;
			}
		}

		output[i] = result;
	}
}

const glurg::ResourceBlob* glurg::MeshResource::get_blob() const
{
	return this->blob;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/ppb_font_proxy.h"

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_image_data_proxy.h"
#include "ppapi/proxy/serialized_var.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "ppapi/shared_impl/resource.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_image_data_api.h"
#include "ppapi/thunk/thunk.h"

using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Font_API;
using ppapi::thunk::PPB_Font_FunctionAPI;
using ppapi::thunk::PPB_ImageData_API;

namespace ppapi {
namespace proxy {

namespace {

bool PPTextRunToTextRun(const PP_TextRun_Dev* run,
                        WebKitForwarding::Font::TextRun* output) {
  StringVar* str = StringVar::FromPPVar(run->text);
  if (!str)
    return false;

  output->text = str->value();
  output->rtl = PP_ToBool(run->rtl);
  output->override_direction = PP_ToBool(run->override_direction);
  return true;
}

}  // namespace

PPB_Font_Proxy::PPB_Font_Proxy(Dispatcher* dispatcher)
    : InterfaceProxy(dispatcher) {
}

PPB_Font_Proxy::~PPB_Font_Proxy() {
}

PPB_Font_FunctionAPI* PPB_Font_Proxy::AsPPB_Font_FunctionAPI() {
  return this;
}

PP_Var PPB_Font_Proxy::GetFontFamilies(PP_Instance instance) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
  if (!dispatcher)
    return PP_MakeUndefined();

  // Assume the font families don't change, so we can cache the result globally.
  static std::string families;
  if (families.empty()) {
    dispatcher->SendToBrowser(
        new PpapiHostMsg_PPBFont_GetFontFamilies(&families));
  }

  return StringVar::StringToPPVar(0, families);
}

bool PPB_Font_Proxy::OnMessageReceived(const IPC::Message& msg) {
  // There aren't any font messages.
  NOTREACHED();
  return false;
}

Font::Font(const HostResource& resource,
           const PP_FontDescription_Dev& desc)
    : Resource(resource),
      webkit_event_(false, false) {
  TRACE_EVENT0("ppapi proxy", "Font::Font");
  StringVar* face = StringVar::FromPPVar(desc.face);

  PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
  WebKitForwarding* forwarding = dispatcher->GetWebKitForwarding();

  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::CreateFontForwarding,
                               base::Unretained(forwarding),
                               &webkit_event_, desc,
                               face ? face->value() : std::string(),
                               dispatcher->preferences(),
                               &font_forwarding_));
}

Font::~Font() {
  RunOnWebKitThread(false, base::Bind(&DeleteFontForwarding, font_forwarding_));
}

PPB_Font_API* Font::AsPPB_Font_API() {
  return this;
}

PP_Bool Font::Describe(PP_FontDescription_Dev* description,
                       PP_FontMetrics_Dev* metrics) {
  TRACE_EVENT0("ppapi proxy", "Font::Describe");
  std::string face;
  PP_Bool result = PP_FALSE;
  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::Font::Describe,
                               base::Unretained(font_forwarding_),
                               &webkit_event_, description, &face, metrics,
                               &result));

  if (PP_ToBool(result))
    description->face = StringVar::StringToPPVar(0, face);
  else
    description->face = PP_MakeUndefined();
  return result;
}

PP_Bool Font::DrawTextAt(PP_Resource pp_image_data,
                         const PP_TextRun_Dev* text,
                         const PP_Point* position,
                         uint32_t color,
                         const PP_Rect* clip,
                         PP_Bool image_data_is_opaque) {
  TRACE_EVENT0("ppapi proxy", "Font::DrawTextAt");
  // Convert to an ImageData object.
  EnterResourceNoLock<PPB_ImageData_API> enter(pp_image_data, true);
  if (enter.failed())
    return PP_FALSE;
  ImageData* image_data = static_cast<ImageData*>(enter.object());

  skia::PlatformCanvas* canvas = image_data->mapped_canvas();
  bool needs_unmapping = false;
  if (!canvas) {
    needs_unmapping = true;
    image_data->Map();
    canvas = image_data->mapped_canvas();
    if (!canvas)
      return PP_FALSE;  // Failure mapping.
  }

  WebKitForwarding::Font::TextRun run;
  if (!PPTextRunToTextRun(text, &run)) {
    if (needs_unmapping)
      image_data->Unmap();
    return PP_FALSE;
  }
  RunOnWebKitThread(
      true,
      base::Bind(&WebKitForwarding::Font::DrawTextAt,
                 base::Unretained(font_forwarding_), &webkit_event_,
                 WebKitForwarding::Font::DrawTextParams(canvas, run, position,
                                                        color, clip,
                                                        image_data_is_opaque)));

  if (needs_unmapping)
    image_data->Unmap();
  return PP_TRUE;
}

int32_t Font::MeasureText(const PP_TextRun_Dev* text) {
  TRACE_EVENT0("ppapi proxy", "Font::MeasureText");
  WebKitForwarding::Font::TextRun run;
  if (!PPTextRunToTextRun(text, &run))
    return -1;
  int32_t result = -1;
  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::Font::MeasureText,
                               base::Unretained(font_forwarding_),
                               &webkit_event_, run, &result));
  return result;
}

uint32_t Font::CharacterOffsetForPixel(const PP_TextRun_Dev* text,
                                       int32_t pixel_position) {
  TRACE_EVENT0("ppapi proxy", "Font::CharacterOffsetForPixel");
  WebKitForwarding::Font::TextRun run;
  if (!PPTextRunToTextRun(text, &run))
    return -1;
  uint32_t result = -1;
  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::Font::CharacterOffsetForPixel,
                               base::Unretained(font_forwarding_),
                               &webkit_event_, run, pixel_position, &result));
  return result;
}

int32_t Font::PixelOffsetForCharacter(const PP_TextRun_Dev* text,
                                      uint32_t char_offset) {
  TRACE_EVENT0("ppapi proxy", "Font::PixelOffsetForCharacter");
  WebKitForwarding::Font::TextRun run;
  if (!PPTextRunToTextRun(text, &run))
    return -1;
  int32_t result = -1;
  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::Font::PixelOffsetForCharacter,
                               base::Unretained(font_forwarding_),
                               &webkit_event_, run, char_offset, &result));
  return result;
}

void Font::RunOnWebKitThread(bool blocking, const base::Closure& task) {
  PluginDispatcher::GetForResource(this)->PostToWebKitThread(FROM_HERE, task);
  if (blocking)
    webkit_event_.Wait();
}

// static
void Font::DeleteFontForwarding(WebKitForwarding::Font* font_forwarding) {
  delete font_forwarding;
}

}  // namespace proxy
}  // namespace ppapi
<commit_msg>Add some checking for the font proxy.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/ppb_font_proxy.h"

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_image_data_proxy.h"
#include "ppapi/proxy/serialized_var.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "ppapi/shared_impl/resource.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_image_data_api.h"
#include "ppapi/thunk/thunk.h"

using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Font_API;
using ppapi::thunk::PPB_Font_FunctionAPI;
using ppapi::thunk::PPB_ImageData_API;

namespace ppapi {
namespace proxy {

namespace {

bool PPTextRunToTextRun(const PP_TextRun_Dev* run,
                        WebKitForwarding::Font::TextRun* output) {
  StringVar* str = StringVar::FromPPVar(run->text);
  if (!str)
    return false;

  output->text = str->value();
  output->rtl = PP_ToBool(run->rtl);
  output->override_direction = PP_ToBool(run->override_direction);
  return true;
}

}  // namespace

PPB_Font_Proxy::PPB_Font_Proxy(Dispatcher* dispatcher)
    : InterfaceProxy(dispatcher) {
}

PPB_Font_Proxy::~PPB_Font_Proxy() {
}

PPB_Font_FunctionAPI* PPB_Font_Proxy::AsPPB_Font_FunctionAPI() {
  return this;
}

PP_Var PPB_Font_Proxy::GetFontFamilies(PP_Instance instance) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
  if (!dispatcher)
    return PP_MakeUndefined();

  // Assume the font families don't change, so we can cache the result globally.
  static std::string families;
  if (families.empty()) {
    dispatcher->SendToBrowser(
        new PpapiHostMsg_PPBFont_GetFontFamilies(&families));
  }

  return StringVar::StringToPPVar(0, families);
}

bool PPB_Font_Proxy::OnMessageReceived(const IPC::Message& msg) {
  // There aren't any font messages.
  NOTREACHED();
  return false;
}

Font::Font(const HostResource& resource,
           const PP_FontDescription_Dev& desc)
    : Resource(resource),
      webkit_event_(false, false),
      font_forwarding_(NULL) {
  TRACE_EVENT0("ppapi proxy", "Font::Font");
  StringVar* face = StringVar::FromPPVar(desc.face);

  PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
  if (!dispatcher)
    return;
  WebKitForwarding* forwarding = dispatcher->GetWebKitForwarding();

  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::CreateFontForwarding,
                               base::Unretained(forwarding),
                               &webkit_event_, desc,
                               face ? face->value() : std::string(),
                               dispatcher->preferences(),
                               &font_forwarding_));
}

Font::~Font() {
  if (font_forwarding_) {
    RunOnWebKitThread(false,
                      base::Bind(&DeleteFontForwarding, font_forwarding_));
  }
}

PPB_Font_API* Font::AsPPB_Font_API() {
  return this;
}

PP_Bool Font::Describe(PP_FontDescription_Dev* description,
                       PP_FontMetrics_Dev* metrics) {
  TRACE_EVENT0("ppapi proxy", "Font::Describe");
  std::string face;
  PP_Bool result = PP_FALSE;
  if (font_forwarding_) {
    RunOnWebKitThread(true,
                      base::Bind(&WebKitForwarding::Font::Describe,
                                 base::Unretained(font_forwarding_),
                                 &webkit_event_, description, &face, metrics,
                                 &result));
  }

  if (PP_ToBool(result))
    description->face = StringVar::StringToPPVar(0, face);
  else
    description->face = PP_MakeUndefined();
  return result;
}

PP_Bool Font::DrawTextAt(PP_Resource pp_image_data,
                         const PP_TextRun_Dev* text,
                         const PP_Point* position,
                         uint32_t color,
                         const PP_Rect* clip,
                         PP_Bool image_data_is_opaque) {
  TRACE_EVENT0("ppapi proxy", "Font::DrawTextAt");
  if (!font_forwarding_)
    return PP_FALSE;

  // Convert to an ImageData object.
  EnterResourceNoLock<PPB_ImageData_API> enter(pp_image_data, true);
  if (enter.failed())
    return PP_FALSE;
  ImageData* image_data = static_cast<ImageData*>(enter.object());

  skia::PlatformCanvas* canvas = image_data->mapped_canvas();
  bool needs_unmapping = false;
  if (!canvas) {
    needs_unmapping = true;
    image_data->Map();
    canvas = image_data->mapped_canvas();
    if (!canvas)
      return PP_FALSE;  // Failure mapping.
  }

  WebKitForwarding::Font::TextRun run;
  if (!PPTextRunToTextRun(text, &run)) {
    if (needs_unmapping)
      image_data->Unmap();
    return PP_FALSE;
  }
  RunOnWebKitThread(
      true,
      base::Bind(&WebKitForwarding::Font::DrawTextAt,
                 base::Unretained(font_forwarding_), &webkit_event_,
                 WebKitForwarding::Font::DrawTextParams(canvas, run, position,
                                                        color, clip,
                                                        image_data_is_opaque)));

  if (needs_unmapping)
    image_data->Unmap();
  return PP_TRUE;
}

int32_t Font::MeasureText(const PP_TextRun_Dev* text) {
  TRACE_EVENT0("ppapi proxy", "Font::MeasureText");
  WebKitForwarding::Font::TextRun run;
  if (!font_forwarding_ || !PPTextRunToTextRun(text, &run))
    return -1;
  int32_t result = -1;
  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::Font::MeasureText,
                               base::Unretained(font_forwarding_),
                               &webkit_event_, run, &result));
  return result;
}

uint32_t Font::CharacterOffsetForPixel(const PP_TextRun_Dev* text,
                                       int32_t pixel_position) {
  TRACE_EVENT0("ppapi proxy", "Font::CharacterOffsetForPixel");
  WebKitForwarding::Font::TextRun run;
  if (!font_forwarding_ || !PPTextRunToTextRun(text, &run))
    return -1;
  uint32_t result = -1;
  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::Font::CharacterOffsetForPixel,
                               base::Unretained(font_forwarding_),
                               &webkit_event_, run, pixel_position, &result));
  return result;
}

int32_t Font::PixelOffsetForCharacter(const PP_TextRun_Dev* text,
                                      uint32_t char_offset) {
  TRACE_EVENT0("ppapi proxy", "Font::PixelOffsetForCharacter");
  WebKitForwarding::Font::TextRun run;
  if (!font_forwarding_ || !PPTextRunToTextRun(text, &run))
    return -1;
  int32_t result = -1;
  RunOnWebKitThread(true,
                    base::Bind(&WebKitForwarding::Font::PixelOffsetForCharacter,
                               base::Unretained(font_forwarding_),
                               &webkit_event_, run, char_offset, &result));
  return result;
}

void Font::RunOnWebKitThread(bool blocking, const base::Closure& task) {
  PluginDispatcher::GetForResource(this)->PostToWebKitThread(FROM_HERE, task);
  if (blocking)
    webkit_event_.Wait();
}

// static
void Font::DeleteFontForwarding(WebKitForwarding::Font* font_forwarding) {
  delete font_forwarding;
}

}  // namespace proxy
}  // namespace ppapi
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard String Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <ironbee/predicate/standard_string.hpp>

#include <ironbee/predicate/call_factory.hpp>
#include <ironbee/predicate/call_helpers.hpp>
#include <ironbee/predicate/functional.hpp>
#include <ironbee/predicate/validate.hpp>

#ifdef __clang__
#pragma clang diagnostic push
#if __has_warning("-Wunused-local-typedef")
#pragma clang diagnostic ignored "-Wunused-local-typedef"
#endif
#endif
#include <boost/regex.hpp>
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#include <boost/shared_ptr.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

/**
 * Regexp based replacement.
 *
 * First child is expression, second child is replacement, third child is
 * text.  Result is substitution applied to each string value of text child.
 **/
class StringReplaceRx :
    public Functional::Map
{
public:
    //! Constructor.
    StringReplaceRx() :
        Functional::Map(2, 1)
    {
        // nop
    }

protected:
    void validate_argument(
        int          n,
        Value        v,
        NodeReporter reporter
    ) const
    {
        if (n < 2 && v.type() != Value::STRING) {
            reporter.error("Must be of type string: " + v.to_s());
        }
    }

    bool prepare(
        MemoryManager                  mm,
        const Functional::value_vec_t& static_args,
        Environment                    environment,
        NodeReporter                   reporter
    )
    {
        ConstByteString expression = static_args[0].as_string();
        try {
            m_expression.assign(
                expression.const_data(), expression.length(),
                boost::regex_constants::normal
            );
        }
        catch (const boost::bad_expression& e) {
            reporter.error(
                "Could not compile regexp: " +
                expression.to_s() +
                " (" + e.what() + ")"
            );
            return false;
        }

        m_replacement = static_args[1].as_string().to_s();
        return true;
    }

    Value eval_map(
        MemoryManager                  mm,
        const Functional::value_vec_t& secondary_args,
        boost::any&                    map_state,
        Value                          subvalue
    ) const
    {
        /* If the subvalue we've been given is NULL, likewise return a NULL
         * subvalue. We can't change anything. */
        if (! subvalue) {
            return Value();
        }

        if (subvalue.type() != Value::STRING) {
            return Value();
        }

        ConstByteString text = subvalue.as_string();
        boost::shared_ptr<vector<char> > result(new vector<char>());
        // Ensure that result.data() is non-null, even if we never insert
        // anything.
        result->reserve(1);

        // value_to_data() ensures that a copy is associated with the memory
        // pool and will be deleted when the memory pool goes away.
        value_to_data(result, mm.ib());

        boost::regex_replace(
            back_inserter(*result),
            text.const_data(), text.const_data() + text.length(),
            m_expression,
            m_replacement
        );

        return Value::create_string(
            mm,
            subvalue.name(), subvalue.name_length(),
            ByteString::create_alias(
                mm,
                result->data(), result->size()
            )
        );
    }

private:
    boost::regex m_expression;
    string       m_replacement;
};

/**
 * Length of string.
 **/
class Length :
    public Functional::Map
{
public:
    //! Constructor.
    Length() : Functional::Map(0, 1) {}

protected:
    Value eval_map(
        MemoryManager                  mm,
        const Functional::value_vec_t& secondary_args,
        boost::any&                    map_state,
        Value                          subvalue
    ) const
    {
        if (subvalue.type() != Value::STRING) {
            return Value();
        }

        return Value::create_number(
            mm,
            subvalue.name(), subvalue.name_length(),
            subvalue.as_string().size()
        );
    }
};

void load_string(CallFactory& to)
{
    to
        .add("stringReplaceRx", Functional::generate<StringReplaceRx>)
        .add("length", Functional::generate<Length>)
        ;
}

} // Standard
} // Predicate
} // IronBee
<commit_msg>standard_string.cpp: Removing a shared pointer destructor call.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard String Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <ironbeepp/mm_ptr.hpp>

#include <ironbee/predicate/standard_string.hpp>
#include <ironbee/predicate/call_factory.hpp>
#include <ironbee/predicate/call_helpers.hpp>
#include <ironbee/predicate/functional.hpp>
#include <ironbee/predicate/validate.hpp>

#ifdef __clang__
#pragma clang diagnostic push
#if __has_warning("-Wunused-local-typedef")
#pragma clang diagnostic ignored "-Wunused-local-typedef"
#endif
#endif
#include <boost/regex.hpp>
#ifdef __clang__
#pragma clang diagnostic pop
#endif

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

/**
 * Regexp based replacement.
 *
 * First child is expression, second child is replacement, third child is
 * text.  Result is substitution applied to each string value of text child.
 **/
class StringReplaceRx :
    public Functional::Map
{
public:
    //! Constructor.
    StringReplaceRx() :
        Functional::Map(2, 1)
    {
        // nop
    }

protected:
    void validate_argument(
        int          n,
        Value        v,
        NodeReporter reporter
    ) const
    {
        if (n < 2 && v.type() != Value::STRING) {
            reporter.error("Must be of type string: " + v.to_s());
        }
    }

    bool prepare(
        MemoryManager                  mm,
        const Functional::value_vec_t& static_args,
        Environment                    environment,
        NodeReporter                   reporter
    )
    {
        ConstByteString expression = static_args[0].as_string();
        try {
            m_expression.assign(
                expression.const_data(), expression.length(),
                boost::regex_constants::normal
            );
        }
        catch (const boost::bad_expression& e) {
            reporter.error(
                "Could not compile regexp: " +
                expression.to_s() +
                " (" + e.what() + ")"
            );
            return false;
        }

        m_replacement = static_args[1].as_string().to_s();
        return true;
    }

    Value eval_map(
        MemoryManager                  mm,
        const Functional::value_vec_t& secondary_args,
        boost::any&                    map_state,
        Value                          subvalue
    ) const
    {
        /* If the subvalue we've been given is NULL, likewise return a NULL
         * subvalue. We can't change anything. */
        if (! subvalue) {
            return Value();
        }

        if (subvalue.type() != Value::STRING) {
            return Value();
        }

        ConstByteString text = subvalue.as_string();
        MMPtr<vector<char> > result(new vector<char>(), mm);
        result->reserve(1);

        boost::regex_replace(
            back_inserter(*result),
            text.const_data(), text.const_data() + text.length(),
            m_expression,
            m_replacement
        );

        return Value::create_string(
            mm,
            subvalue.name(), subvalue.name_length(),
            ByteString::create_alias(
                mm,
                result->data(), result->size()
            )
        );
    }

private:
    boost::regex m_expression;
    string       m_replacement;
};

/**
 * Length of string.
 **/
class Length :
    public Functional::Map
{
public:
    //! Constructor.
    Length() : Functional::Map(0, 1) {}

protected:
    Value eval_map(
        MemoryManager                  mm,
        const Functional::value_vec_t& secondary_args,
        boost::any&                    map_state,
        Value                          subvalue
    ) const
    {
        if (subvalue.type() != Value::STRING) {
            return Value();
        }

        return Value::create_number(
            mm,
            subvalue.name(), subvalue.name_length(),
            subvalue.as_string().size()
        );
    }
};

void load_string(CallFactory& to)
{
    to
        .add("stringReplaceRx", Functional::generate<StringReplaceRx>)
        .add("length", Functional::generate<Length>)
        ;
}

} // Standard
} // Predicate
} // IronBee
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2001  Internet Software Consortium.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* $Id: AccountInfo.cpp,v 1.3 2001/10/05 05:45:48 mayer Exp $ */

#ifndef UNICODE
#define UNICODE
#endif /* UNICODE */

#include "stdafx.h"

#include <windows.h>
#include <lm.h>
#include <ntsecapi.h>

#include <isc/ntgroups.h>
#include <isc/result.h>
#include "AccountInfo.h"

#define MAX_NAME_LENGTH 256

NTSTATUS
OpenPolicy(
    LPWSTR ServerName,		/* machine to open policy on (Unicode) */
    DWORD DesiredAccess,	/* desired access to policy */
    PLSA_HANDLE PolicyHandle	/* resultant policy handle */
    );

BOOL
GetAccountSid(
    LPTSTR SystemName,		/* where to lookup account */
    LPTSTR AccountName,		/* account of interest */
    PSID *Sid			/* resultant buffer containing SID */
    );

NTSTATUS
SetPrivilegeOnAccount(
    LSA_HANDLE PolicyHandle,	/* open policy handle */
    PSID AccountSid,		/* SID to grant privilege to */
    LPWSTR PrivilegeName,	/* privilege to grant (Unicode) */
    BOOL bEnable		/* enable or disable */
    );

NTSTATUS
GetPrivilegesOnAccount(
    LSA_HANDLE PolicyHandle,	/* open policy handle */
    PSID AccountSid,		/* SID to grant privilege to */
    wchar_t **PrivList,		/* Ptr to List of Privileges found */
    unsigned int *PrivCount	/* total number of Privileges in list */
    );

NTSTATUS
AddPrivilegeToAcccount(
    LPTSTR AccountName,		/* Name of the account */
    LPWSTR PrivilegeName	/* Privilege to Add */
    );

void
InitLsaString(
    PLSA_UNICODE_STRING LsaString,	/* destination */
    LPWSTR String			/* source (Unicode) */
    );

void
DisplayNtStatus(
    LPSTR szAPI,		/* pointer to function name (ANSI) */
    NTSTATUS Status		/* NTSTATUS error value */
    );

void
DisplayWinError(
    LPSTR szAPI,		/* pointer to function name (ANSI) */
    DWORD WinError		/* DWORD WinError */
    );

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
#endif

/*
 * Note that this code only retrieves the list of privileges of the
 * requested account or group. However, all accounts belong to the
 * Everyone group even though that group is not returned by the
 * calls to get the groups to which that account belongs.
 * The Everyone group has two privileges associated with it:
 * SeChangeNotifyPrivilege and SeNetworkLogonRight
 * It is not advisable to disable or remove these privileges
 * from the group nor can the account be removed from the Everyone
 * group
 * The None group has no privileges associated with it and is the group
 * to which an account belongs if it is associated with no group.
 */

int
GetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
		     char **Accounts, unsigned int *totalAccounts,
		     int maxAccounts)
{
	LSA_HANDLE PolicyHandle;
	TCHAR AccountName[256];		/* static account name buffer */
	PSID pSid;
	unsigned int i;
	NTSTATUS Status;
	isc_result_t istatus;
	int iRetVal=RTN_ERROR;		/* assume error from main */

	/*
	 * Open the policy on the target machine.
	 */
	if ((Status = OpenPolicy(NULL,
				 POLICY_LOOKUP_NAMES,
				 &PolicyHandle)) != STATUS_SUCCESS)
		return (RTN_ERROR);

	/*
	 * Let's see if the account exists. Return if not
	 */
	wsprintf(AccountName, TEXT("%hS"), name);
	if (!GetAccountSid(NULL, AccountName, &pSid))
		return (RTN_NOACCOUNT);
	/*
	 * Find out what groups the account belongs to
	 */
	istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
						  totalAccounts);
	if (istatus == ISC_R_NOMEMORY) {
		return (RTN_NOMEMORY);
	}
	else if (istatus != ISC_R_SUCCESS) {
		return (RTN_ERROR);
	}

	Accounts[*totalAccounts] = name; /* Add the account to the list */
	(*totalAccounts)++;

	/*
	 * Loop through each Account to get the list of privileges
	 */
	for (i = 0; i < *totalAccounts; i++) {
		wsprintf(AccountName, TEXT("%hS"), Accounts[i]);
		 /* Obtain the SID of the user/group. */
		if (!GetAccountSid(NULL, AccountName, &pSid))
			continue;	/* Try the next one */
		/* Get the Privileges allocated to this SID */
	        if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
			PrivList, PrivCount)) == STATUS_SUCCESS)
		{
			iRetVal=RTN_OK;
			if (pSid != NULL)
				HeapFree(GetProcessHeap(), 0, pSid);
		} else {
			if (pSid != NULL)
				HeapFree(GetProcessHeap(), 0, pSid);
			continue;	/* Try the next one */
		}
	}
	/*
	 * Close the policy handle.
	 */
	LsaClose(PolicyHandle);

	(*totalAccounts)--;	/* Correct for the number of groups */
	return iRetVal;
}

BOOL
CreateServiceAccount(char *name, char *password) {
	NTSTATUS retstat;
	USER_INFO_1 ui;
	DWORD dwLevel = 1;
	DWORD dwError = 0;
	NET_API_STATUS nStatus;

	unsigned int namelen = strlen(name);
	unsigned int passwdlen = strlen(password);
	wchar_t AccountName[MAX_NAME_LENGTH];
	wchar_t AccountPassword[MAX_NAME_LENGTH];

	mbstowcs(AccountName, name, namelen + 1);
	mbstowcs(AccountPassword, password, passwdlen + 1);

	/*
	 * Set up the USER_INFO_1 structure.
	 * USER_PRIV_USER: name is required here when creating an account
	 * rather than an administrator or a guest.
	 */

	ui.usri1_name = (LPWSTR) &AccountName;
	ui.usri1_password = (LPWSTR) &AccountPassword;
	ui.usri1_priv = USER_PRIV_USER;
	ui.usri1_home_dir = NULL;
	ui.usri1_comment = L"ISC BIND Service Account";
	ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
	ui.usri1_script_path = NULL;
	/*
	 * Call the NetUserAdd function, specifying level 1.
	 */
	nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);

	if (nStatus != NERR_Success)
		return (FALSE);

	retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
	return (TRUE);
}

NTSTATUS
AddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
	LSA_HANDLE PolicyHandle;
	TCHAR AccountName[256];		/* static account name buffer */
	PSID pSid;
	NTSTATUS Status;
	unsigned long err;

	/*
	 * Open the policy on the target machine.
	 */
	if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
		!= STATUS_SUCCESS)
		return (RTN_ERROR);

	/*
	 * Let's see if the account exists. Return if not
	 */
	wsprintf(AccountName, TEXT("%hS"), name);
	if (!GetAccountSid(NULL, AccountName, &pSid))
		return (RTN_NOACCOUNT);

        err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
		pSid, PrivilegeName, TRUE));

	LsaClose(PolicyHandle);
	if (err == ERROR_SUCCESS)
		return (RTN_OK);
	else
		return (err);
}

void
InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
	DWORD StringLength;

	if (String == NULL) {
		LsaString->Buffer = NULL;
		LsaString->Length = 0;
		LsaString->MaximumLength = 0;
		return;
	}

	StringLength = wcslen(String);
	LsaString->Buffer = String;
	LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
	LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
}

NTSTATUS
OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
	LSA_OBJECT_ATTRIBUTES ObjectAttributes;
	LSA_UNICODE_STRING ServerString;
	PLSA_UNICODE_STRING Server = NULL;

	/*
	 * Always initialize the object attributes to all zeroes.
	 */
	ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));

	if (ServerName != NULL) {
		/*
		 * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
		 */
		InitLsaString(&ServerString, ServerName);
		Server = &ServerString;
	}

	/*
	 * Attempt to open the policy.
	 */
	return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
		PolicyHandle));
}

BOOL
GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
	LPTSTR ReferencedDomain = NULL;
	DWORD cbSid = 128;    /* initial allocation attempt */
	DWORD cbReferencedDomain = 16; /* initial allocation size */
	SID_NAME_USE peUse;
	BOOL bSuccess = FALSE; /* assume this function will fail */

	__try {
		/*
		 * initial memory allocations
		 */
		if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
			__leave;

		if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
				       cbReferencedDomain)) == NULL) __leave;

		/*
		 * Obtain the SID of the specified account on the specified system.
		 */
		while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
					  ReferencedDomain, &cbReferencedDomain,
					  &peUse))
		{
			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
				/* reallocate memory */
				if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
					*Sid, cbSid)) == NULL) __leave;

				if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
					GetProcessHeap(), 0, ReferencedDomain,
					cbReferencedDomain)) == NULL)
				__leave;
			}
			else
				__leave;
		}
		bSuccess = TRUE;
	} /* finally */
	__finally {

		/* Cleanup and indicate failure, if appropriate. */

		HeapFree(GetProcessHeap(), 0, ReferencedDomain);

		if (!bSuccess) {
			if (*Sid != NULL) {
				HeapFree(GetProcessHeap(), 0, *Sid);
				*Sid = NULL;
			}
		}

	}

	return (bSuccess);
}

NTSTATUS
SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
		      LPWSTR PrivilegeName, BOOL bEnable)
{
	LSA_UNICODE_STRING PrivilegeString;

	/* Create a LSA_UNICODE_STRING for the privilege name. */
	InitLsaString(&PrivilegeString, PrivilegeName);

	/* grant or revoke the privilege, accordingly */
	if (bEnable)
		return (LsaAddAccountRights(PolicyHandle, AccountSid,
			&PrivilegeString, 1));
	else
		return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
			FALSE, &PrivilegeString, 1));
}

NTSTATUS
GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
		       wchar_t **PrivList, unsigned int *PrivCount)
{
	NTSTATUS Status;
	LSA_UNICODE_STRING *UserRights;
	ULONG CountOfRights;
	unsigned int retlen = 0;
	DWORD i, j;
	int found;

	Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
		&UserRights, &CountOfRights);
	/* Only continue if there is something */
	if (UserRights == NULL || Status != STATUS_SUCCESS)
		return (Status);

	for (i = 0; i < CountOfRights; i++) {
		found = -1;
		retlen = UserRights[i].Length/sizeof(wchar_t);
		for (j = 0; j < *PrivCount; j++) {
			found = wcsncmp(PrivList[j], UserRights[i].Buffer,
					retlen);
			if (found == 0)
				break;
		}
		if (found != 0) {
			PrivList[*PrivCount] =
			    (wchar_t *)malloc(UserRights[i].MaximumLength);
			if (PrivList[*PrivCount] == NULL)
				return (RTN_NOMEMORY);

			wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
				retlen);
			PrivList[*PrivCount][retlen] = L'\0';
			(*PrivCount)++;
		}

	}

	return (Status);
}

void
DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
	/* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
	DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
}

void
DisplayWinError(LPSTR szAPI, DWORD WinError) {
	LPSTR MessageBuffer;
	DWORD dwBufferLength;

	if (dwBufferLength=FormatMessageA(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL, WinError, GetUserDefaultLangID(),
		(LPSTR) &MessageBuffer, 0, NULL)){
		DWORD dwBytesWritten; /* unused */

		/* Output message string on stderr. */
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
			  dwBufferLength, &dwBytesWritten, NULL);

		/* Free the buffer allocated by the system. */
		LocalFree(MessageBuffer);
	}
}
<commit_msg>style<commit_after>/*
 * Copyright (C) 2001  Internet Software Consortium.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* $Id: AccountInfo.cpp,v 1.4 2001/10/05 17:08:09 gson Exp $ */

#ifndef UNICODE
#define UNICODE
#endif /* UNICODE */

#include "stdafx.h"

#include <windows.h>
#include <lm.h>
#include <ntsecapi.h>

#include <isc/ntgroups.h>
#include <isc/result.h>
#include "AccountInfo.h"

#define MAX_NAME_LENGTH 256

NTSTATUS
OpenPolicy(
    LPWSTR ServerName,		/* machine to open policy on (Unicode) */
    DWORD DesiredAccess,	/* desired access to policy */
    PLSA_HANDLE PolicyHandle	/* resultant policy handle */
    );

BOOL
GetAccountSid(
    LPTSTR SystemName,		/* where to lookup account */
    LPTSTR AccountName,		/* account of interest */
    PSID *Sid			/* resultant buffer containing SID */
    );

NTSTATUS
SetPrivilegeOnAccount(
    LSA_HANDLE PolicyHandle,	/* open policy handle */
    PSID AccountSid,		/* SID to grant privilege to */
    LPWSTR PrivilegeName,	/* privilege to grant (Unicode) */
    BOOL bEnable		/* enable or disable */
    );

NTSTATUS
GetPrivilegesOnAccount(
    LSA_HANDLE PolicyHandle,	/* open policy handle */
    PSID AccountSid,		/* SID to grant privilege to */
    wchar_t **PrivList,		/* Ptr to List of Privileges found */
    unsigned int *PrivCount	/* total number of Privileges in list */
    );

NTSTATUS
AddPrivilegeToAcccount(
    LPTSTR AccountName,		/* Name of the account */
    LPWSTR PrivilegeName	/* Privilege to Add */
    );

void
InitLsaString(
    PLSA_UNICODE_STRING LsaString,	/* destination */
    LPWSTR String			/* source (Unicode) */
    );

void
DisplayNtStatus(
    LPSTR szAPI,		/* pointer to function name (ANSI) */
    NTSTATUS Status		/* NTSTATUS error value */
    );

void
DisplayWinError(
    LPSTR szAPI,		/* pointer to function name (ANSI) */
    DWORD WinError		/* DWORD WinError */
    );

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
#endif

/*
 * Note that this code only retrieves the list of privileges of the
 * requested account or group. However, all accounts belong to the
 * Everyone group even though that group is not returned by the
 * calls to get the groups to which that account belongs.
 * The Everyone group has two privileges associated with it:
 * SeChangeNotifyPrivilege and SeNetworkLogonRight
 * It is not advisable to disable or remove these privileges
 * from the group nor can the account be removed from the Everyone
 * group
 * The None group has no privileges associated with it and is the group
 * to which an account belongs if it is associated with no group.
 */

int
GetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
		     char **Accounts, unsigned int *totalAccounts,
		     int maxAccounts)
{
	LSA_HANDLE PolicyHandle;
	TCHAR AccountName[256];		/* static account name buffer */
	PSID pSid;
	unsigned int i;
	NTSTATUS Status;
	isc_result_t istatus;
	int iRetVal = RTN_ERROR;	/* assume error from main */

	/*
	 * Open the policy on the target machine.
	 */
	if ((Status = OpenPolicy(NULL,
				 POLICY_LOOKUP_NAMES,
				 &PolicyHandle)) != STATUS_SUCCESS)
		return (RTN_ERROR);

	/*
	 * Let's see if the account exists. Return if not
	 */
	wsprintf(AccountName, TEXT("%hS"), name);
	if (!GetAccountSid(NULL, AccountName, &pSid))
		return (RTN_NOACCOUNT);
	/*
	 * Find out what groups the account belongs to
	 */
	istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
						  totalAccounts);
	if (istatus == ISC_R_NOMEMORY)
		return (RTN_NOMEMORY);
	else if (istatus != ISC_R_SUCCESS)
		return (RTN_ERROR);

	Accounts[*totalAccounts] = name; /* Add the account to the list */
	(*totalAccounts)++;

	/*
	 * Loop through each Account to get the list of privileges
	 */
	for (i = 0; i < *totalAccounts; i++) {
		wsprintf(AccountName, TEXT("%hS"), Accounts[i]);
		 /* Obtain the SID of the user/group. */
		if (!GetAccountSid(NULL, AccountName, &pSid))
			continue;	/* Try the next one */
		/* Get the Privileges allocated to this SID */
	        if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
			PrivList, PrivCount)) == STATUS_SUCCESS)
		{
			iRetVal=RTN_OK;
			if (pSid != NULL)
				HeapFree(GetProcessHeap(), 0, pSid);
		} else {
			if (pSid != NULL)
				HeapFree(GetProcessHeap(), 0, pSid);
			continue;	/* Try the next one */
		}
	}
	/*
	 * Close the policy handle.
	 */
	LsaClose(PolicyHandle);

	(*totalAccounts)--;	/* Correct for the number of groups */
	return iRetVal;
}

BOOL
CreateServiceAccount(char *name, char *password) {
	NTSTATUS retstat;
	USER_INFO_1 ui;
	DWORD dwLevel = 1;
	DWORD dwError = 0;
	NET_API_STATUS nStatus;

	unsigned int namelen = strlen(name);
	unsigned int passwdlen = strlen(password);
	wchar_t AccountName[MAX_NAME_LENGTH];
	wchar_t AccountPassword[MAX_NAME_LENGTH];

	mbstowcs(AccountName, name, namelen + 1);
	mbstowcs(AccountPassword, password, passwdlen + 1);

	/*
	 * Set up the USER_INFO_1 structure.
	 * USER_PRIV_USER: name is required here when creating an account
	 * rather than an administrator or a guest.
	 */

	ui.usri1_name = (LPWSTR) &AccountName;
	ui.usri1_password = (LPWSTR) &AccountPassword;
	ui.usri1_priv = USER_PRIV_USER;
	ui.usri1_home_dir = NULL;
	ui.usri1_comment = L"ISC BIND Service Account";
	ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
	ui.usri1_script_path = NULL;
	/*
	 * Call the NetUserAdd function, specifying level 1.
	 */
	nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);

	if (nStatus != NERR_Success)
		return (FALSE);

	retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
	return (TRUE);
}

NTSTATUS
AddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
	LSA_HANDLE PolicyHandle;
	TCHAR AccountName[256];		/* static account name buffer */
	PSID pSid;
	NTSTATUS Status;
	unsigned long err;

	/*
	 * Open the policy on the target machine.
	 */
	if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
		!= STATUS_SUCCESS)
		return (RTN_ERROR);

	/*
	 * Let's see if the account exists. Return if not
	 */
	wsprintf(AccountName, TEXT("%hS"), name);
	if (!GetAccountSid(NULL, AccountName, &pSid))
		return (RTN_NOACCOUNT);

        err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
		pSid, PrivilegeName, TRUE));

	LsaClose(PolicyHandle);
	if (err == ERROR_SUCCESS)
		return (RTN_OK);
	else
		return (err);
}

void
InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
	DWORD StringLength;

	if (String == NULL) {
		LsaString->Buffer = NULL;
		LsaString->Length = 0;
		LsaString->MaximumLength = 0;
		return;
	}

	StringLength = wcslen(String);
	LsaString->Buffer = String;
	LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
	LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
}

NTSTATUS
OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
	LSA_OBJECT_ATTRIBUTES ObjectAttributes;
	LSA_UNICODE_STRING ServerString;
	PLSA_UNICODE_STRING Server = NULL;

	/*
	 * Always initialize the object attributes to all zeroes.
	 */
	ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));

	if (ServerName != NULL) {
		/*
		 * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
		 */
		InitLsaString(&ServerString, ServerName);
		Server = &ServerString;
	}

	/*
	 * Attempt to open the policy.
	 */
	return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
		PolicyHandle));
}

BOOL
GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
	LPTSTR ReferencedDomain = NULL;
	DWORD cbSid = 128;    /* initial allocation attempt */
	DWORD cbReferencedDomain = 16; /* initial allocation size */
	SID_NAME_USE peUse;
	BOOL bSuccess = FALSE; /* assume this function will fail */

	__try {
		/*
		 * initial memory allocations
		 */
		if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
			__leave;

		if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
				       cbReferencedDomain)) == NULL) __leave;

		/*
		 * Obtain the SID of the specified account on the specified system.
		 */
		while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
					  ReferencedDomain, &cbReferencedDomain,
					  &peUse))
		{
			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
				/* reallocate memory */
				if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
					*Sid, cbSid)) == NULL) __leave;

				if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
					GetProcessHeap(), 0, ReferencedDomain,
					cbReferencedDomain)) == NULL)
				__leave;
			}
			else
				__leave;
		}
		bSuccess = TRUE;
	} /* finally */
	__finally {

		/* Cleanup and indicate failure, if appropriate. */

		HeapFree(GetProcessHeap(), 0, ReferencedDomain);

		if (!bSuccess) {
			if (*Sid != NULL) {
				HeapFree(GetProcessHeap(), 0, *Sid);
				*Sid = NULL;
			}
		}

	}

	return (bSuccess);
}

NTSTATUS
SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
		      LPWSTR PrivilegeName, BOOL bEnable)
{
	LSA_UNICODE_STRING PrivilegeString;

	/* Create a LSA_UNICODE_STRING for the privilege name. */
	InitLsaString(&PrivilegeString, PrivilegeName);

	/* grant or revoke the privilege, accordingly */
	if (bEnable)
		return (LsaAddAccountRights(PolicyHandle, AccountSid,
			&PrivilegeString, 1));
	else
		return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
			FALSE, &PrivilegeString, 1));
}

NTSTATUS
GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
		       wchar_t **PrivList, unsigned int *PrivCount)
{
	NTSTATUS Status;
	LSA_UNICODE_STRING *UserRights;
	ULONG CountOfRights;
	unsigned int retlen = 0;
	DWORD i, j;
	int found;

	Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
		&UserRights, &CountOfRights);
	/* Only continue if there is something */
	if (UserRights == NULL || Status != STATUS_SUCCESS)
		return (Status);

	for (i = 0; i < CountOfRights; i++) {
		found = -1;
		retlen = UserRights[i].Length/sizeof(wchar_t);
		for (j = 0; j < *PrivCount; j++) {
			found = wcsncmp(PrivList[j], UserRights[i].Buffer,
					retlen);
			if (found == 0)
				break;
		}
		if (found != 0) {
			PrivList[*PrivCount] =
			    (wchar_t *)malloc(UserRights[i].MaximumLength);
			if (PrivList[*PrivCount] == NULL)
				return (RTN_NOMEMORY);

			wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
				retlen);
			PrivList[*PrivCount][retlen] = L'\0';
			(*PrivCount)++;
		}

	}

	return (Status);
}

void
DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
	/* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
	DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
}

void
DisplayWinError(LPSTR szAPI, DWORD WinError) {
	LPSTR MessageBuffer;
	DWORD dwBufferLength;

	if (dwBufferLength=FormatMessageA(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL, WinError, GetUserDefaultLangID(),
		(LPSTR) &MessageBuffer, 0, NULL)){
		DWORD dwBytesWritten; /* unused */

		/* Output message string on stderr. */
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
			  dwBufferLength, &dwBytesWritten, NULL);

		/* Free the buffer allocated by the system. */
		LocalFree(MessageBuffer);
	}
}
<|endoftext|>


<commit_before><commit_msg>add programming/extern_c/main.cpp<commit_after><|endoftext|>


<commit_before>// $Header$

#include "Reve.h"
#include "RenderElement.h"

#include <TError.h>
#include <TPad.h>
#include <TGeoManager.h>
#include <TClass.h>

#include <TStyle.h>
#include <TColor.h>

#include <TROOT.h>
#include <TInterpreter.h>
#include <TSystem.h>

#include <TGClient.h>
#include <TGMimeTypes.h>

#include <list>
#include <algorithm>
#include <iostream>

//______________________________________________________________________
// Reve
//

/**************************************************************************/
/**************************************************************************/
namespace Reve {
/**************************************************************************/

// TString .vs. string

bool operator==(const TString& t, const std::string& s)
{ return (s == t.Data()); }

bool operator==(const std::string&  s, const TString& t)
{ return (s == t.Data()); }

// Exc

Exc_t::Exc_t(const std::string& s) : TString(s.c_str()) {}

// Exc + ops

Exc_t operator+(const Exc_t &s1, const std::string &s2)
{ return Exc_t((TString&)s1 + s2.c_str()); }

Exc_t operator+(const Exc_t &s1, const TString &s2)
{ return Exc_t((TString&)s1 + s2); }

Exc_t operator+(const Exc_t &s1,  const char *s2)
{ return Exc_t((TString&)s1 + s2); }

// ----------------------------------------------------------------

void WarnCaller(const TString& warning)
{
  std::cout << "WRN: " << warning << std::endl;
}

/**************************************************************************/
/**************************************************************************/

void SetupEnvironment()
{
  // Check if REVESYS exists, try fallback to $ALICE_ROOT/EVE.
  // Setup Include and Macro paths.

  static const Exc_t eH("Reve::SetupEnvironment");
  static Bool_t setupDone = kFALSE;

  if (setupDone) {
    Info(eH.Data(), "has already been run.");
    return;
  }

  if(gSystem->Getenv("REVESYS") == 0) {
    if(gSystem->Getenv("ALICE_ROOT") != 0) {
      Info(eH.Data(), "setting REVESYS from ALICE_ROOT.");
      gSystem->Setenv("REVESYS", Form("%s/EVE", gSystem->Getenv("ALICE_ROOT")));
    } else {
      Error(eH.Data(), "REVESYS not defined, neither is ALICE_ROOT.");
      gSystem->Exit(1);
    }
  }
  if(gSystem->AccessPathName(gSystem->Getenv("REVESYS")) == kTRUE) {
    Error(eH.Data(), "REVESYS '%s' does not exist.", gSystem->Getenv("REVESYS"));
    gSystem->Exit(1);
  }

  TString macPath(gROOT->GetMacroPath());
  macPath += Form(":%s/macros", gSystem->Getenv("REVESYS"));
  gInterpreter->AddIncludePath(gSystem->Getenv("REVESYS"));
  if(gSystem->Getenv("ALICE_ROOT") != 0) {
    macPath += Form(":%s/alice-macros", gSystem->Getenv("REVESYS"));
    gInterpreter->AddIncludePath(Form("%s/include", gSystem->Getenv("ALICE_ROOT")));
    gInterpreter->AddIncludePath(gSystem->Getenv("ALICE_ROOT"));
  }
  gROOT->SetMacroPath(macPath);
}

void SetupGUI()
{
  TString fld( Form("%s/icons/", gSystem->Getenv("REVESYS")) );
  // printf("foofoo %p %p %p %p\n",
  //	 RenderElement::fgRnrIcons[0],RenderElement::fgRnrIcons[1],
  //	 RenderElement::fgRnrIcons[2],RenderElement::fgRnrIcons[3]);
  RenderElement::fgRnrIcons[0] = gClient->GetPicture(fld + "rnr00_t.xpm");
  RenderElement::fgRnrIcons[1] = gClient->GetPicture(fld + "rnr01_t.xpm");
  RenderElement::fgRnrIcons[2] = gClient->GetPicture(fld + "rnr10_t.xpm");
  RenderElement::fgRnrIcons[3] = gClient->GetPicture(fld + "rnr11_t.xpm");

  RenderElement::fgListTreeIcons[0] = gClient->GetPicture("folder_t.xpm");
  RenderElement::fgListTreeIcons[1] = gClient->GetPicture(fld + "viewer.xpm");
  RenderElement::fgListTreeIcons[2] = gClient->GetPicture(fld + "scene.xpm");
  RenderElement::fgListTreeIcons[3] = gClient->GetPicture(fld + "pointset.xpm");
  RenderElement::fgListTreeIcons[4] = gClient->GetPicture(fld + "track.xpm");

  gClient->GetMimeTypeList()->AddType("root/tmacro", "Reve::RMacro",
                                      "tmacro_s.xpm", "tmacro_t.xpm", "");
}

/**************************************************************************/

namespace {
  void ChompTail(TString& s, char c='.') {
    Ssiz_t p = s.Last(c);
    if(p != kNPOS)
      s.Remove(p);
  }
}

Bool_t CheckMacro(const Text_t* mac)
{
  // Checks if macro 'mac' is loaded.

  // Axel's advice; now sth seems slow, using old method below for test.
  // return gROOT->GetInterpreter()->IsLoaded(mac);

  // Previous version expected function with same name and used ROOT's
  // list of global functions.

  TString foo(mac); ChompTail(foo);
  /*
  if(recreate) {
    TCollection* logf = gROOT->GetListOfGlobalFunctions(kFALSE);
    logf->SetOwner();
    logf->Clear();
  }
  */
  if (gROOT->GetGlobalFunction(foo.Data(), 0, kFALSE) != 0)
    return kTRUE;
  else
    return (gROOT->GetGlobalFunction(foo.Data(), 0, kTRUE) != 0);
}

void AssertMacro(const Text_t* mac)
{
  // Load and execute macro 'mac' if it has not been loaded yet.

  if(CheckMacro(mac) == kFALSE) {
    gROOT->Macro(mac);
  }
}

void Macro(const Text_t* mac)
{
  // Execute macro 'mac'. Do not reload the macro.

  if(CheckMacro(mac) == kFALSE) {
    gROOT->LoadMacro(mac);
  }
  TString foo(mac); ChompTail(foo); foo += "()";
  gROOT->ProcessLine(foo.Data());
}

void LoadMacro(const Text_t* mac)
{
  // Makes sure that macro 'mac' is loaded, but do not reload it.

  if(CheckMacro(mac) == kFALSE) {
    gROOT->LoadMacro(mac);
  }
}

/**************************************************************************/
/**************************************************************************/

// Pad stack for RINT/GUI thread.
std::list<TVirtualPad*> s_Pad_Stack;

TVirtualPad* PushPad(TVirtualPad* new_gpad, Int_t subpad)
{
  // printf("Reve::PushPad old=%p, new=%p\n", gPad, new_gpad);
  s_Pad_Stack.push_back(gPad);
  if(new_gpad != 0)
    new_gpad->cd(subpad);
  else
    gPad = 0;
  return gPad;
}

TVirtualPad* PopPad(Bool_t modify_update_p)
{
  // printf("Reve::PopPad old=%p, new=%p\n", gPad, s_Pad_Stack.empty() ? 0 : s_Pad_Stack.back());
  if(s_Pad_Stack.empty()) {
    Warning("Reve::PopTPad", "stack empty.");
  } else {
    if(modify_update_p && gPad != 0) {
      gPad->Modified();
      gPad->Update();
    }
    gPad = s_Pad_Stack.back();
    s_Pad_Stack.pop_back();
  }
  return gPad;
}

/**************************************************************************/
// GeoManagerHolder
/**************************************************************************/

GeoManagerHolder::GeoManagerHolder(TGeoManager* new_gmgr) :
  fManager(gGeoManager)
{
  gGeoManager = new_gmgr;
}

GeoManagerHolder::~GeoManagerHolder()
{
  gGeoManager = fManager;
}

/**************************************************************************/
// Color management
/**************************************************************************/

void ColorFromIdx(Color_t ci, UChar_t* col, Bool_t alpha)
{
  if (ci < 0) {
    col[0] = col[1] = col[2] = col[3] = 0;
    return;
  }
  TColor* c = gROOT->GetColor(ci);
  if(c) {
    col[0] = (UChar_t)(255*c->GetRed());
    col[1] = (UChar_t)(255*c->GetGreen());
    col[2] = (UChar_t)(255*c->GetBlue());
    if (alpha) col[3] = 255;
  }
}

void ColorFromIdx(Float_t f1, Color_t c1, Float_t f2, Color_t c2,
		  UChar_t* col, Bool_t alpha)
{
  TColor* t1 = gROOT->GetColor(c1);
  TColor* t2 = gROOT->GetColor(c2);
  if(t1 && t2) {
    col[0] = (UChar_t)(255*(f1*t1->GetRed()   + f2*t2->GetRed()));
    col[1] = (UChar_t)(255*(f1*t1->GetGreen() + f2*t2->GetGreen()));
    col[2] = (UChar_t)(255*(f1*t1->GetBlue()  + f2*t2->GetBlue()));
    if (alpha) col[3] = 255;
  }
}

Color_t* FindColorVar(TObject* obj, const Text_t* varname)
{
  static const Exc_t eH("Reve::FindColorVar");

  Int_t off = obj->IsA()->GetDataMemberOffset(varname);
  if(off == 0)
    throw(eH + "could not find member '" + varname + "' in class " + obj->IsA()->GetName() + ".");
  return (Color_t*) (((char*)obj) + off);
}

/**************************************************************************/
} // end namespace Reve
/**************************************************************************/
/**************************************************************************/

using namespace Reve;

/**************************************************************************/
// ReferenceBackPtr
/**************************************************************************/

ClassImp(ReferenceBackPtr)

ReferenceBackPtr::ReferenceBackPtr() :
  ReferenceCount(),
  fBackRefs()
{}

ReferenceBackPtr::~ReferenceBackPtr()
{
  // !!!! Complain if list not empty.
}

ReferenceBackPtr::ReferenceBackPtr(const ReferenceBackPtr&) :
  ReferenceCount(),
  fBackRefs()
{}

ReferenceBackPtr& ReferenceBackPtr::operator=(const ReferenceBackPtr&)
{
  return *this;
}

/**************************************************************************/

void ReferenceBackPtr::IncRefCount(RenderElement* re)
{
  ReferenceCount::IncRefCount();
  fBackRefs.push_back(re);
}

void ReferenceBackPtr::DecRefCount(RenderElement* re)
{
  static const Exc_t eH("ReferenceBackPtr::DecRefCount ");

  std::list<RenderElement*>::iterator i =
    std::find(fBackRefs.begin(), fBackRefs.end(), re);
  if (i != fBackRefs.end()) {
    fBackRefs.erase(i);
    ReferenceCount::DecRefCount();
  } else {
    Warning(eH, Form("render element '%s' not found in back-refs.",
		     re->GetObject()->GetName()));
  }
}

/**************************************************************************/

void ReferenceBackPtr::UpdateBackPtrItems()
{
  std::list<RenderElement*>::iterator i = fBackRefs.begin();
  while (i != fBackRefs.end())
  {
    (*i)->UpdateItems();
    ++i;
  }
}
<commit_msg>Rewrite Exc_t operator+ variants.<commit_after>// $Header$

#include "Reve.h"
#include "RenderElement.h"

#include <TError.h>
#include <TPad.h>
#include <TGeoManager.h>
#include <TClass.h>

#include <TStyle.h>
#include <TColor.h>

#include <TROOT.h>
#include <TInterpreter.h>
#include <TSystem.h>

#include <TGClient.h>
#include <TGMimeTypes.h>

#include <list>
#include <algorithm>
#include <iostream>

//______________________________________________________________________
// Reve
//

/**************************************************************************/
/**************************************************************************/
namespace Reve {
/**************************************************************************/

// TString .vs. string

bool operator==(const TString& t, const std::string& s)
{ return (s == t.Data()); }

bool operator==(const std::string&  s, const TString& t)
{ return (s == t.Data()); }

// Exc

Exc_t::Exc_t(const std::string& s) : TString(s.c_str()) {}

// Exc + ops

Exc_t operator+(const Exc_t &s1, const std::string &s2)
{ Exc_t r(s1); r += s2; return r; }

Exc_t operator+(const Exc_t &s1, const TString &s2)
{ Exc_t r(s1); r += s2; return r; }

Exc_t operator+(const Exc_t &s1,  const char *s2)
{ Exc_t r(s1); r += s2; return r; }

// ----------------------------------------------------------------

void WarnCaller(const TString& warning)
{
  std::cout << "WRN: " << warning << std::endl;
}

/**************************************************************************/
/**************************************************************************/

void SetupEnvironment()
{
  // Check if REVESYS exists, try fallback to $ALICE_ROOT/EVE.
  // Setup Include and Macro paths.

  static const Exc_t eH("Reve::SetupEnvironment");
  static Bool_t setupDone = kFALSE;

  if (setupDone) {
    Info(eH.Data(), "has already been run.");
    return;
  }

  if(gSystem->Getenv("REVESYS") == 0) {
    if(gSystem->Getenv("ALICE_ROOT") != 0) {
      Info(eH.Data(), "setting REVESYS from ALICE_ROOT.");
      gSystem->Setenv("REVESYS", Form("%s/EVE", gSystem->Getenv("ALICE_ROOT")));
    } else {
      Error(eH.Data(), "REVESYS not defined, neither is ALICE_ROOT.");
      gSystem->Exit(1);
    }
  }
  if(gSystem->AccessPathName(gSystem->Getenv("REVESYS")) == kTRUE) {
    Error(eH.Data(), "REVESYS '%s' does not exist.", gSystem->Getenv("REVESYS"));
    gSystem->Exit(1);
  }

  TString macPath(gROOT->GetMacroPath());
  macPath += Form(":%s/macros", gSystem->Getenv("REVESYS"));
  gInterpreter->AddIncludePath(gSystem->Getenv("REVESYS"));
  if(gSystem->Getenv("ALICE_ROOT") != 0) {
    macPath += Form(":%s/alice-macros", gSystem->Getenv("REVESYS"));
    gInterpreter->AddIncludePath(Form("%s/include", gSystem->Getenv("ALICE_ROOT")));
    gInterpreter->AddIncludePath(gSystem->Getenv("ALICE_ROOT"));
  }
  gROOT->SetMacroPath(macPath);
}

void SetupGUI()
{
  TString fld( Form("%s/icons/", gSystem->Getenv("REVESYS")) );
  // printf("foofoo %p %p %p %p\n",
  //	 RenderElement::fgRnrIcons[0],RenderElement::fgRnrIcons[1],
  //	 RenderElement::fgRnrIcons[2],RenderElement::fgRnrIcons[3]);
  RenderElement::fgRnrIcons[0] = gClient->GetPicture(fld + "rnr00_t.xpm");
  RenderElement::fgRnrIcons[1] = gClient->GetPicture(fld + "rnr01_t.xpm");
  RenderElement::fgRnrIcons[2] = gClient->GetPicture(fld + "rnr10_t.xpm");
  RenderElement::fgRnrIcons[3] = gClient->GetPicture(fld + "rnr11_t.xpm");

  RenderElement::fgListTreeIcons[0] = gClient->GetPicture("folder_t.xpm");
  RenderElement::fgListTreeIcons[1] = gClient->GetPicture(fld + "viewer.xpm");
  RenderElement::fgListTreeIcons[2] = gClient->GetPicture(fld + "scene.xpm");
  RenderElement::fgListTreeIcons[3] = gClient->GetPicture(fld + "pointset.xpm");
  RenderElement::fgListTreeIcons[4] = gClient->GetPicture(fld + "track.xpm");

  gClient->GetMimeTypeList()->AddType("root/tmacro", "Reve::RMacro",
                                      "tmacro_s.xpm", "tmacro_t.xpm", "");
}

/**************************************************************************/

namespace {
  void ChompTail(TString& s, char c='.') {
    Ssiz_t p = s.Last(c);
    if(p != kNPOS)
      s.Remove(p);
  }
}

Bool_t CheckMacro(const Text_t* mac)
{
  // Checks if macro 'mac' is loaded.

  // Axel's advice; now sth seems slow, using old method below for test.
  // return gROOT->GetInterpreter()->IsLoaded(mac);

  // Previous version expected function with same name and used ROOT's
  // list of global functions.

  TString foo(mac); ChompTail(foo);
  /*
  if(recreate) {
    TCollection* logf = gROOT->GetListOfGlobalFunctions(kFALSE);
    logf->SetOwner();
    logf->Clear();
  }
  */
  if (gROOT->GetGlobalFunction(foo.Data(), 0, kFALSE) != 0)
    return kTRUE;
  else
    return (gROOT->GetGlobalFunction(foo.Data(), 0, kTRUE) != 0);
}

void AssertMacro(const Text_t* mac)
{
  // Load and execute macro 'mac' if it has not been loaded yet.

  if(CheckMacro(mac) == kFALSE) {
    gROOT->Macro(mac);
  }
}

void Macro(const Text_t* mac)
{
  // Execute macro 'mac'. Do not reload the macro.

  if(CheckMacro(mac) == kFALSE) {
    gROOT->LoadMacro(mac);
  }
  TString foo(mac); ChompTail(foo); foo += "()";
  gROOT->ProcessLine(foo.Data());
}

void LoadMacro(const Text_t* mac)
{
  // Makes sure that macro 'mac' is loaded, but do not reload it.

  if(CheckMacro(mac) == kFALSE) {
    gROOT->LoadMacro(mac);
  }
}

/**************************************************************************/
/**************************************************************************/

// Pad stack for RINT/GUI thread.
std::list<TVirtualPad*> s_Pad_Stack;

TVirtualPad* PushPad(TVirtualPad* new_gpad, Int_t subpad)
{
  // printf("Reve::PushPad old=%p, new=%p\n", gPad, new_gpad);
  s_Pad_Stack.push_back(gPad);
  if(new_gpad != 0)
    new_gpad->cd(subpad);
  else
    gPad = 0;
  return gPad;
}

TVirtualPad* PopPad(Bool_t modify_update_p)
{
  // printf("Reve::PopPad old=%p, new=%p\n", gPad, s_Pad_Stack.empty() ? 0 : s_Pad_Stack.back());
  if(s_Pad_Stack.empty()) {
    Warning("Reve::PopTPad", "stack empty.");
  } else {
    if(modify_update_p && gPad != 0) {
      gPad->Modified();
      gPad->Update();
    }
    gPad = s_Pad_Stack.back();
    s_Pad_Stack.pop_back();
  }
  return gPad;
}

/**************************************************************************/
// GeoManagerHolder
/**************************************************************************/

GeoManagerHolder::GeoManagerHolder(TGeoManager* new_gmgr) :
  fManager(gGeoManager)
{
  gGeoManager = new_gmgr;
}

GeoManagerHolder::~GeoManagerHolder()
{
  gGeoManager = fManager;
}

/**************************************************************************/
// Color management
/**************************************************************************/

void ColorFromIdx(Color_t ci, UChar_t* col, Bool_t alpha)
{
  if (ci < 0) {
    col[0] = col[1] = col[2] = col[3] = 0;
    return;
  }
  TColor* c = gROOT->GetColor(ci);
  if(c) {
    col[0] = (UChar_t)(255*c->GetRed());
    col[1] = (UChar_t)(255*c->GetGreen());
    col[2] = (UChar_t)(255*c->GetBlue());
    if (alpha) col[3] = 255;
  }
}

void ColorFromIdx(Float_t f1, Color_t c1, Float_t f2, Color_t c2,
		  UChar_t* col, Bool_t alpha)
{
  TColor* t1 = gROOT->GetColor(c1);
  TColor* t2 = gROOT->GetColor(c2);
  if(t1 && t2) {
    col[0] = (UChar_t)(255*(f1*t1->GetRed()   + f2*t2->GetRed()));
    col[1] = (UChar_t)(255*(f1*t1->GetGreen() + f2*t2->GetGreen()));
    col[2] = (UChar_t)(255*(f1*t1->GetBlue()  + f2*t2->GetBlue()));
    if (alpha) col[3] = 255;
  }
}

Color_t* FindColorVar(TObject* obj, const Text_t* varname)
{
  static const Exc_t eH("Reve::FindColorVar");

  Int_t off = obj->IsA()->GetDataMemberOffset(varname);
  if(off == 0)
    throw(eH + "could not find member '" + varname + "' in class " + obj->IsA()->GetName() + ".");
  return (Color_t*) (((char*)obj) + off);
}

/**************************************************************************/
} // end namespace Reve
/**************************************************************************/
/**************************************************************************/

using namespace Reve;

/**************************************************************************/
// ReferenceBackPtr
/**************************************************************************/

ClassImp(ReferenceBackPtr)

ReferenceBackPtr::ReferenceBackPtr() :
  ReferenceCount(),
  fBackRefs()
{}

ReferenceBackPtr::~ReferenceBackPtr()
{
  // !!!! Complain if list not empty.
}

ReferenceBackPtr::ReferenceBackPtr(const ReferenceBackPtr&) :
  ReferenceCount(),
  fBackRefs()
{}

ReferenceBackPtr& ReferenceBackPtr::operator=(const ReferenceBackPtr&)
{
  return *this;
}

/**************************************************************************/

void ReferenceBackPtr::IncRefCount(RenderElement* re)
{
  ReferenceCount::IncRefCount();
  fBackRefs.push_back(re);
}

void ReferenceBackPtr::DecRefCount(RenderElement* re)
{
  static const Exc_t eH("ReferenceBackPtr::DecRefCount ");

  std::list<RenderElement*>::iterator i =
    std::find(fBackRefs.begin(), fBackRefs.end(), re);
  if (i != fBackRefs.end()) {
    fBackRefs.erase(i);
    ReferenceCount::DecRefCount();
  } else {
    Warning(eH, Form("render element '%s' not found in back-refs.",
		     re->GetObject()->GetName()));
  }
}

/**************************************************************************/

void ReferenceBackPtr::UpdateBackPtrItems()
{
  std::list<RenderElement*>::iterator i = fBackRefs.begin();
  while (i != fBackRefs.end())
  {
    (*i)->UpdateItems();
    ++i;
  }
}
<|endoftext|>


<commit_before><commit_msg>Prediction: fixed random failure in prediction_component_test (#1873)<commit_after><|endoftext|>