<commit_before>/**
 * \file
 * \brief ThreadSchedulingPolicyTestCase class implementation
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 *
 * \date 2014-11-17
 */

#include "ThreadSchedulingPolicyTestCase.hpp"

#include "SequenceAsserter.hpp"
#include "wasteTime.hpp"

#include "distortos/StaticThread.hpp"
#include "distortos/ThisThread.hpp"

#include "distortos/architecture/InterruptMaskingLock.hpp"

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// pair of sequence points
using SequencePoints = std::pair<unsigned int, unsigned int>;

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {192};

/// priority of test thread
constexpr uint8_t testThreadPriority {1};

/// number of test threads
constexpr size_t totalThreads {10};

/// duration of single test thread - significantly longer than single round-robin quantum
constexpr auto testThreadDuration = scheduler::RoundRobinQuantum::getInitial() * 2;

/*---------------------------------------------------------------------------------------------------------------------+
| local functions' declarations
+---------------------------------------------------------------------------------------------------------------------*/

void thread(SequenceAsserter& sequenceAsserter, SequencePoints sequencePoints);

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// type of test thread
using TestThread = decltype(makeStaticThread<testThreadStackSize>({}, thread,
		std::ref(std::declval<SequenceAsserter&>()), std::declval<SequencePoints>()));

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Test thread.
 *
 * Marks the first sequence point in SequenceAsserter, wastes some time and marks the second sequence point in
 * SequenceAsserter.
 *
 * \param [in] sequenceAsserter is a reference to SequenceAsserter shared object
 * \param [in] sequencePoints is a pair of sequence points for this instance
 */

void thread(SequenceAsserter& sequenceAsserter, const SequencePoints sequencePoints)
{
	sequenceAsserter.sequencePoint(sequencePoints.first);
	wasteTime(testThreadDuration);
	sequenceAsserter.sequencePoint(sequencePoints.second);
}

/**
 * \brief Builder of TestThread objects.
 *
 * \param [in] sequenceAsserter is a reference to SequenceAsserter shared object
 * \param [in] sequencePoints is a pair of sequence points for this instance
 *
 * \return constructed TestThread object
 */

TestThread makeTestThread(SequenceAsserter& sequenceAsserter, const SequencePoints sequencePoints)
{
	return makeStaticThread<testThreadStackSize>(testThreadPriority, thread, std::ref(sequenceAsserter),
			static_cast<SequencePoints>(sequencePoints));
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool ThreadSchedulingPolicyTestCase::run_() const
{
	SequenceAsserter sequenceAsserter;

	std::array<TestThread, totalThreads> threads
	{{
			makeTestThread(sequenceAsserter, {0, 0 + totalThreads}),
			makeTestThread(sequenceAsserter, {1, 1 + totalThreads}),
			makeTestThread(sequenceAsserter, {2, 2 + totalThreads}),
			makeTestThread(sequenceAsserter, {3, 3 + totalThreads}),
			makeTestThread(sequenceAsserter, {4, 4 + totalThreads}),
			makeTestThread(sequenceAsserter, {5, 5 + totalThreads}),
			makeTestThread(sequenceAsserter, {6, 6 + totalThreads}),
			makeTestThread(sequenceAsserter, {7, 7 + totalThreads}),
			makeTestThread(sequenceAsserter, {8, 8 + totalThreads}),
			makeTestThread(sequenceAsserter, {9, 9 + totalThreads}),
	}};

	decltype(TickClock::now()) testStart;

	{
		architecture::InterruptMaskingLock interruptMaskingLock;

		// wait for beginning of next tick - test threads should be started in the same tick
		ThisThread::sleepFor({});

		for (auto& thread : threads)
			thread.start();

		testStart = TickClock::now();
	}

	for (auto& thread : threads)
		thread.join();

	const auto testDuration = TickClock::now() - testStart;

	if (sequenceAsserter.assertSequence(totalThreads * 2) == false)
		return false;

	// exact time cannot be calculated, because wasteTime() is not precise when context switches occur during it
	if (testDuration < testThreadDuration * totalThreads)
		return false;

	return true;
}

}	// namespace test

}	// namespace distortos
<commit_msg>test: allow setting of scheduling policy of test thread in makeTestThread() from ThreadSchedulingPolicyTestCase<commit_after>/**
 * \file
 * \brief ThreadSchedulingPolicyTestCase class implementation
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 *
 * \date 2014-11-17
 */

#include "ThreadSchedulingPolicyTestCase.hpp"

#include "SequenceAsserter.hpp"
#include "wasteTime.hpp"

#include "distortos/StaticThread.hpp"
#include "distortos/ThisThread.hpp"

#include "distortos/architecture/InterruptMaskingLock.hpp"

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// pair of sequence points
using SequencePoints = std::pair<unsigned int, unsigned int>;

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {192};

/// priority of test thread
constexpr uint8_t testThreadPriority {1};

/// number of test threads
constexpr size_t totalThreads {10};

/// duration of single test thread - significantly longer than single round-robin quantum
constexpr auto testThreadDuration = scheduler::RoundRobinQuantum::getInitial() * 2;

/*---------------------------------------------------------------------------------------------------------------------+
| local functions' declarations
+---------------------------------------------------------------------------------------------------------------------*/

void thread(SequenceAsserter& sequenceAsserter, SequencePoints sequencePoints);

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// type of test thread
using TestThread = decltype(makeStaticThread<testThreadStackSize>({}, thread,
		std::ref(std::declval<SequenceAsserter&>()), std::declval<SequencePoints>()));

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Test thread.
 *
 * Marks the first sequence point in SequenceAsserter, wastes some time and marks the second sequence point in
 * SequenceAsserter.
 *
 * \param [in] sequenceAsserter is a reference to SequenceAsserter shared object
 * \param [in] sequencePoints is a pair of sequence points for this instance
 */

void thread(SequenceAsserter& sequenceAsserter, const SequencePoints sequencePoints)
{
	sequenceAsserter.sequencePoint(sequencePoints.first);
	wasteTime(testThreadDuration);
	sequenceAsserter.sequencePoint(sequencePoints.second);
}

/**
 * \brief Builder of TestThread objects.
 *
 * \param [in] schedulingPolicy is the scheduling policy of the test thread
 * \param [in] sequenceAsserter is a reference to SequenceAsserter shared object
 * \param [in] sequencePoints is a pair of sequence points for this instance
 *
 * \return constructed TestThread object
 */

TestThread makeTestThread(const SchedulingPolicy schedulingPolicy, SequenceAsserter& sequenceAsserter,
		const SequencePoints sequencePoints)
{
	return makeStaticThread<testThreadStackSize>(testThreadPriority, schedulingPolicy, thread,
			std::ref(sequenceAsserter), static_cast<SequencePoints>(sequencePoints));
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool ThreadSchedulingPolicyTestCase::run_() const
{
	SequenceAsserter sequenceAsserter;

	std::array<TestThread, totalThreads> threads
	{{
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {0, 0 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {1, 1 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {2, 2 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {3, 3 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {4, 4 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {5, 5 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {6, 6 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {7, 7 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {8, 8 + totalThreads}),
			makeTestThread(SchedulingPolicy::RoundRobin, sequenceAsserter, {9, 9 + totalThreads}),
	}};

	decltype(TickClock::now()) testStart;

	{
		architecture::InterruptMaskingLock interruptMaskingLock;

		// wait for beginning of next tick - test threads should be started in the same tick
		ThisThread::sleepFor({});

		for (auto& thread : threads)
			thread.start();

		testStart = TickClock::now();
	}

	for (auto& thread : threads)
		thread.join();

	const auto testDuration = TickClock::now() - testStart;

	if (sequenceAsserter.assertSequence(totalThreads * 2) == false)
		return false;

	// exact time cannot be calculated, because wasteTime() is not precise when context switches occur during it
	if (testDuration < testThreadDuration * totalThreads)
		return false;

	return true;
}

}	// namespace test

}	// namespace distortos
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "sandbox/src/restricted_token.h"

#include <vector>

#include "base/logging.h"
#include "sandbox/src/acl.h"
#include "sandbox/src/win_utils.h"

namespace sandbox {

unsigned RestrictedToken::Init(const HANDLE effective_token) {
  DCHECK(!init_);
  if (init_)
    return ERROR_ALREADY_INITIALIZED;

  if (effective_token) {
    // We duplicate the handle to be able to use it even if the original handle
    // is closed.
    HANDLE effective_token_dup;
    if (::DuplicateHandle(::GetCurrentProcess(),
                          effective_token,
                          ::GetCurrentProcess(),
                          &effective_token_dup,
                          DUPLICATE_SAME_ACCESS,
                          FALSE,
                          0)) {  // no special options
      effective_token_ = effective_token_dup;
    } else {
      return ::GetLastError();
    }
  } else {
    if (!::OpenProcessToken(::GetCurrentProcess(),
                            TOKEN_ALL_ACCESS,
                            &effective_token_))
      return ::GetLastError();
  }

  init_ = true;
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::GetRestrictedTokenHandle(HANDLE *token_handle) const {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  size_t deny_size = sids_for_deny_only_.size();
  size_t restrict_size = sids_to_restrict_.size();
  size_t privileges_size = privileges_to_disable_.size();

  SID_AND_ATTRIBUTES *deny_only_array = NULL;
  if (deny_size) {
    deny_only_array = new SID_AND_ATTRIBUTES[deny_size];

    for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) {
      deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
      deny_only_array[i].Sid =
          const_cast<SID*>(sids_for_deny_only_[i].GetPSID());
    }
  }

  SID_AND_ATTRIBUTES *sids_to_restrict_array = NULL;
  if (restrict_size) {
    sids_to_restrict_array = new SID_AND_ATTRIBUTES[restrict_size];

    for (unsigned int i = 0; i < restrict_size; ++i) {
      sids_to_restrict_array[i].Attributes = 0;
      sids_to_restrict_array[i].Sid =
          const_cast<SID*>(sids_to_restrict_[i].GetPSID());
    }
  }

  LUID_AND_ATTRIBUTES *privileges_to_disable_array = NULL;
  if (privileges_size) {
    privileges_to_disable_array = new LUID_AND_ATTRIBUTES[privileges_size];

    for (unsigned int i = 0; i < privileges_size; ++i) {
      privileges_to_disable_array[i].Attributes = 0;
      privileges_to_disable_array[i].Luid = privileges_to_disable_[i];
    }
  }

  BOOL result = TRUE;
  HANDLE new_token = NULL;
  if (deny_size || restrict_size || privileges_size) {
    result = ::CreateRestrictedToken(effective_token_,
                                     0,  // No flags.
                                     static_cast<DWORD>(deny_size),
                                     deny_only_array,
                                     static_cast<DWORD>(privileges_size),
                                     privileges_to_disable_array,
                                     static_cast<DWORD>(restrict_size),
                                     sids_to_restrict_array,
                                     &new_token);
  } else {
    // Duplicate the token even if it's not modified at this point
    // because any subsequent changes to this token would also affect the
    // current process.
    result = ::DuplicateTokenEx(effective_token_, TOKEN_ALL_ACCESS, NULL,
                                SecurityIdentification, TokenPrimary,
                                &new_token);
  }

  if (deny_only_array)
    delete[] deny_only_array;

  if (sids_to_restrict_array)
    delete[] sids_to_restrict_array;

  if (privileges_to_disable_array)
    delete[] privileges_to_disable_array;

  if (!result)
    return ::GetLastError();

  // Modify the default dacl on the token to contain Restricted and the user.
  if (!AddSidToDefaultDacl(new_token, WinRestrictedCodeSid, GENERIC_ALL))
    return ::GetLastError();

  if (!AddUserSidToDefaultDacl(new_token, GENERIC_ALL))
    return ::GetLastError();

  DWORD error = SetTokenIntegrityLevel(new_token, integrity_level_);
  if (ERROR_SUCCESS != error)
    return error;

  BOOL status = ::DuplicateHandle(::GetCurrentProcess(),
                                  new_token,
                                  ::GetCurrentProcess(),
                                  token_handle,
                                  TOKEN_ALL_ACCESS,
                                  TRUE,  // Inherit handle.
                                  0);  // No options.

  if (new_token != effective_token_)
    ::CloseHandle(new_token);

  if (!status)
    return ::GetLastError();

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::GetRestrictedTokenHandleForImpersonation(
    HANDLE *token_handle) const {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  HANDLE restricted_token_handle;
  unsigned err_code = GetRestrictedTokenHandle(&restricted_token_handle);
  if (ERROR_SUCCESS != err_code)
    return err_code;

  HANDLE impersonation_token;
  if (!::DuplicateToken(restricted_token_handle,
                        SecurityImpersonation,
                        &impersonation_token)) {
    ::CloseHandle(restricted_token_handle);
    return ::GetLastError();
  }

  ::CloseHandle(restricted_token_handle);

  BOOL status = ::DuplicateHandle(::GetCurrentProcess(),
                                  impersonation_token,
                                  ::GetCurrentProcess(),
                                  token_handle,
                                  TOKEN_ALL_ACCESS,
                                  TRUE,  // Inherit handle.
                                  0);  // No options.

  ::CloseHandle(impersonation_token);

  if (!status)
    return ::GetLastError();

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  TOKEN_GROUPS *token_groups = NULL;
  DWORD size = 0;

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenGroups,
                                      NULL,  // No buffer.
                                      0,  // Size is 0.
                                      &size);
  if (!size)
    return ::GetLastError();

  token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenGroups,
                                 token_groups,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE*>(token_groups);
    return ::GetLastError();
  }

  // Build the list of the deny only group SIDs
  for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
    if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 &&
        (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) {
      bool should_ignore = false;
      if (exceptions) {
        for (unsigned int j = 0; j < exceptions->size(); ++j) {
          if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()),
                          token_groups->Groups[i].Sid)) {
            should_ignore = true;
            break;
          }
        }
      }
      if (!should_ignore) {
        sids_for_deny_only_.push_back(
            reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
      }
    }
  }

  delete[] reinterpret_cast<BYTE*>(token_groups);

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddSidForDenyOnly(const Sid &sid) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  sids_for_deny_only_.push_back(sid);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddUserSidForDenyOnly() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
  TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]);

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenUser,
                                      token_user,
                                      size,
                                      &size);

  Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
  delete[] reinterpret_cast<BYTE*>(token_user);

  if (!result)
    return ::GetLastError();

  sids_for_deny_only_.push_back(user);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::DeleteAllPrivileges(
    const std::vector<std::wstring> *exceptions) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  // Get the list of privileges in the token
  TOKEN_PRIVILEGES *token_privileges = NULL;
  DWORD size = 0;

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenPrivileges,
                                      NULL,  // No buffer.
                                      0,  // Size is 0.
                                      &size);
  if (!size)
    return ::GetLastError();

  token_privileges = reinterpret_cast<TOKEN_PRIVILEGES*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenPrivileges,
                                 token_privileges,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE *>(token_privileges);
    return ::GetLastError();
  }

  // Build the list of privileges to disable
  for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) {
    bool should_ignore = false;
    if (exceptions) {
      for (unsigned int j = 0; j < exceptions->size(); ++j) {
        LUID luid = {0};
        ::LookupPrivilegeValue(NULL, (*exceptions)[j].c_str(), &luid);
        if (token_privileges->Privileges[i].Luid.HighPart == luid.HighPart &&
            token_privileges->Privileges[i].Luid.LowPart == luid.LowPart) {
          should_ignore = true;
          break;
        }
      }
    }
    if (!should_ignore) {
        privileges_to_disable_.push_back(token_privileges->Privileges[i].Luid);
    }
  }

  delete[] reinterpret_cast<BYTE *>(token_privileges);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::DeletePrivilege(const wchar_t *privilege) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  LUID luid = {0};
  if (LookupPrivilegeValue(NULL, privilege, &luid))
    privileges_to_disable_.push_back(luid);
  else
    return ::GetLastError();

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSid(const Sid &sid) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  sids_to_restrict_.push_back(sid);  // No attributes
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSidLogonSession() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  TOKEN_GROUPS *token_groups = NULL;
  DWORD size = 0;

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenGroups,
                                      NULL,  // No buffer.
                                      0,  // Size is 0.
                                      &size);
  if (!size)
    return ::GetLastError();

  token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenGroups,
                                 token_groups,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE*>(token_groups);
    return ::GetLastError();
  }

  SID *logon_sid = NULL;
  for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
    if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) {
        logon_sid = static_cast<SID*>(token_groups->Groups[i].Sid);
        break;
    }
  }

  if (logon_sid)
    sids_to_restrict_.push_back(logon_sid);

  delete[] reinterpret_cast<BYTE*>(token_groups);

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSidCurrentUser() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
  TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]);

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenUser,
                                      token_user,
                                      size,
                                      &size);

  Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
  delete[] reinterpret_cast<BYTE*>(token_user);

  if (!result)
    return ::GetLastError();

  sids_to_restrict_.push_back(user);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSidAllSids() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  // Add the current user to the list.
  unsigned error = AddRestrictingSidCurrentUser();
  if (ERROR_SUCCESS != error)
    return error;

  TOKEN_GROUPS *token_groups = NULL;
  DWORD size = 0;

  // Get the buffer size required.
  BOOL result = ::GetTokenInformation(effective_token_, TokenGroups, NULL, 0,
                                      &size);
  if (!size)
    return ::GetLastError();

  token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenGroups,
                                 token_groups,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE*>(token_groups);
    return ::GetLastError();
  }

  // Build the list of restricting sids from all groups.
  for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
    if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0)
      AddRestrictingSid(reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
  }

  delete[] reinterpret_cast<BYTE*>(token_groups);

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) {
  integrity_level_ = integrity_level;
  return ERROR_SUCCESS;
}

}  // namespace sandbox
<commit_msg>Try the SANDOX_INERT flag in CreateRestrictedToken - It might help with the AppLocker problem. See bug below.<commit_after>// Copyright (c) 2006-2008 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 "sandbox/src/restricted_token.h"

#include <vector>

#include "base/logging.h"
#include "sandbox/src/acl.h"
#include "sandbox/src/win_utils.h"

namespace sandbox {

unsigned RestrictedToken::Init(const HANDLE effective_token) {
  DCHECK(!init_);
  if (init_)
    return ERROR_ALREADY_INITIALIZED;

  if (effective_token) {
    // We duplicate the handle to be able to use it even if the original handle
    // is closed.
    HANDLE effective_token_dup;
    if (::DuplicateHandle(::GetCurrentProcess(),
                          effective_token,
                          ::GetCurrentProcess(),
                          &effective_token_dup,
                          DUPLICATE_SAME_ACCESS,
                          FALSE,
                          0)) {  // no special options
      effective_token_ = effective_token_dup;
    } else {
      return ::GetLastError();
    }
  } else {
    if (!::OpenProcessToken(::GetCurrentProcess(),
                            TOKEN_ALL_ACCESS,
                            &effective_token_))
      return ::GetLastError();
  }

  init_ = true;
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::GetRestrictedTokenHandle(HANDLE *token_handle) const {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  size_t deny_size = sids_for_deny_only_.size();
  size_t restrict_size = sids_to_restrict_.size();
  size_t privileges_size = privileges_to_disable_.size();

  SID_AND_ATTRIBUTES *deny_only_array = NULL;
  if (deny_size) {
    deny_only_array = new SID_AND_ATTRIBUTES[deny_size];

    for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) {
      deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
      deny_only_array[i].Sid =
          const_cast<SID*>(sids_for_deny_only_[i].GetPSID());
    }
  }

  SID_AND_ATTRIBUTES *sids_to_restrict_array = NULL;
  if (restrict_size) {
    sids_to_restrict_array = new SID_AND_ATTRIBUTES[restrict_size];

    for (unsigned int i = 0; i < restrict_size; ++i) {
      sids_to_restrict_array[i].Attributes = 0;
      sids_to_restrict_array[i].Sid =
          const_cast<SID*>(sids_to_restrict_[i].GetPSID());
    }
  }

  LUID_AND_ATTRIBUTES *privileges_to_disable_array = NULL;
  if (privileges_size) {
    privileges_to_disable_array = new LUID_AND_ATTRIBUTES[privileges_size];

    for (unsigned int i = 0; i < privileges_size; ++i) {
      privileges_to_disable_array[i].Attributes = 0;
      privileges_to_disable_array[i].Luid = privileges_to_disable_[i];
    }
  }

  BOOL result = TRUE;
  HANDLE new_token = NULL;
  // The SANDBOX_INERT flag did nothing in XP and it was just a way to tell
  // if a token has ben restricted given the limiations of IsTokenRestricted()
  // but it appears that in Windows 7 it hints the AppLocker subsystem to
  // leave us alone.
  if (deny_size || restrict_size || privileges_size) {
    result = ::CreateRestrictedToken(effective_token_,
                                     SANDBOX_INERT,
                                     static_cast<DWORD>(deny_size),
                                     deny_only_array,
                                     static_cast<DWORD>(privileges_size),
                                     privileges_to_disable_array,
                                     static_cast<DWORD>(restrict_size),
                                     sids_to_restrict_array,
                                     &new_token);
  } else {
    // Duplicate the token even if it's not modified at this point
    // because any subsequent changes to this token would also affect the
    // current process.
    result = ::DuplicateTokenEx(effective_token_, TOKEN_ALL_ACCESS, NULL,
                                SecurityIdentification, TokenPrimary,
                                &new_token);
  }

  if (deny_only_array)
    delete[] deny_only_array;

  if (sids_to_restrict_array)
    delete[] sids_to_restrict_array;

  if (privileges_to_disable_array)
    delete[] privileges_to_disable_array;

  if (!result)
    return ::GetLastError();

  // Modify the default dacl on the token to contain Restricted and the user.
  if (!AddSidToDefaultDacl(new_token, WinRestrictedCodeSid, GENERIC_ALL))
    return ::GetLastError();

  if (!AddUserSidToDefaultDacl(new_token, GENERIC_ALL))
    return ::GetLastError();

  DWORD error = SetTokenIntegrityLevel(new_token, integrity_level_);
  if (ERROR_SUCCESS != error)
    return error;

  BOOL status = ::DuplicateHandle(::GetCurrentProcess(),
                                  new_token,
                                  ::GetCurrentProcess(),
                                  token_handle,
                                  TOKEN_ALL_ACCESS,
                                  TRUE,  // Inherit handle.
                                  0);  // No options.

  if (new_token != effective_token_)
    ::CloseHandle(new_token);

  if (!status)
    return ::GetLastError();

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::GetRestrictedTokenHandleForImpersonation(
    HANDLE *token_handle) const {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  HANDLE restricted_token_handle;
  unsigned err_code = GetRestrictedTokenHandle(&restricted_token_handle);
  if (ERROR_SUCCESS != err_code)
    return err_code;

  HANDLE impersonation_token;
  if (!::DuplicateToken(restricted_token_handle,
                        SecurityImpersonation,
                        &impersonation_token)) {
    ::CloseHandle(restricted_token_handle);
    return ::GetLastError();
  }

  ::CloseHandle(restricted_token_handle);

  BOOL status = ::DuplicateHandle(::GetCurrentProcess(),
                                  impersonation_token,
                                  ::GetCurrentProcess(),
                                  token_handle,
                                  TOKEN_ALL_ACCESS,
                                  TRUE,  // Inherit handle.
                                  0);  // No options.

  ::CloseHandle(impersonation_token);

  if (!status)
    return ::GetLastError();

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  TOKEN_GROUPS *token_groups = NULL;
  DWORD size = 0;

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenGroups,
                                      NULL,  // No buffer.
                                      0,  // Size is 0.
                                      &size);
  if (!size)
    return ::GetLastError();

  token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenGroups,
                                 token_groups,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE*>(token_groups);
    return ::GetLastError();
  }

  // Build the list of the deny only group SIDs
  for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
    if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 &&
        (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) {
      bool should_ignore = false;
      if (exceptions) {
        for (unsigned int j = 0; j < exceptions->size(); ++j) {
          if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()),
                          token_groups->Groups[i].Sid)) {
            should_ignore = true;
            break;
          }
        }
      }
      if (!should_ignore) {
        sids_for_deny_only_.push_back(
            reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
      }
    }
  }

  delete[] reinterpret_cast<BYTE*>(token_groups);

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddSidForDenyOnly(const Sid &sid) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  sids_for_deny_only_.push_back(sid);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddUserSidForDenyOnly() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
  TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]);

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenUser,
                                      token_user,
                                      size,
                                      &size);

  Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
  delete[] reinterpret_cast<BYTE*>(token_user);

  if (!result)
    return ::GetLastError();

  sids_for_deny_only_.push_back(user);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::DeleteAllPrivileges(
    const std::vector<std::wstring> *exceptions) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  // Get the list of privileges in the token
  TOKEN_PRIVILEGES *token_privileges = NULL;
  DWORD size = 0;

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenPrivileges,
                                      NULL,  // No buffer.
                                      0,  // Size is 0.
                                      &size);
  if (!size)
    return ::GetLastError();

  token_privileges = reinterpret_cast<TOKEN_PRIVILEGES*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenPrivileges,
                                 token_privileges,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE *>(token_privileges);
    return ::GetLastError();
  }

  // Build the list of privileges to disable
  for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) {
    bool should_ignore = false;
    if (exceptions) {
      for (unsigned int j = 0; j < exceptions->size(); ++j) {
        LUID luid = {0};
        ::LookupPrivilegeValue(NULL, (*exceptions)[j].c_str(), &luid);
        if (token_privileges->Privileges[i].Luid.HighPart == luid.HighPart &&
            token_privileges->Privileges[i].Luid.LowPart == luid.LowPart) {
          should_ignore = true;
          break;
        }
      }
    }
    if (!should_ignore) {
        privileges_to_disable_.push_back(token_privileges->Privileges[i].Luid);
    }
  }

  delete[] reinterpret_cast<BYTE *>(token_privileges);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::DeletePrivilege(const wchar_t *privilege) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  LUID luid = {0};
  if (LookupPrivilegeValue(NULL, privilege, &luid))
    privileges_to_disable_.push_back(luid);
  else
    return ::GetLastError();

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSid(const Sid &sid) {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  sids_to_restrict_.push_back(sid);  // No attributes
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSidLogonSession() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  TOKEN_GROUPS *token_groups = NULL;
  DWORD size = 0;

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenGroups,
                                      NULL,  // No buffer.
                                      0,  // Size is 0.
                                      &size);
  if (!size)
    return ::GetLastError();

  token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenGroups,
                                 token_groups,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE*>(token_groups);
    return ::GetLastError();
  }

  SID *logon_sid = NULL;
  for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
    if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) {
        logon_sid = static_cast<SID*>(token_groups->Groups[i].Sid);
        break;
    }
  }

  if (logon_sid)
    sids_to_restrict_.push_back(logon_sid);

  delete[] reinterpret_cast<BYTE*>(token_groups);

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSidCurrentUser() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
  TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(new BYTE[size]);

  BOOL result = ::GetTokenInformation(effective_token_,
                                      TokenUser,
                                      token_user,
                                      size,
                                      &size);

  Sid user = reinterpret_cast<SID*>(token_user->User.Sid);
  delete[] reinterpret_cast<BYTE*>(token_user);

  if (!result)
    return ::GetLastError();

  sids_to_restrict_.push_back(user);
  return ERROR_SUCCESS;
}

unsigned RestrictedToken::AddRestrictingSidAllSids() {
  DCHECK(init_);
  if (!init_)
    return ERROR_NO_TOKEN;

  // Add the current user to the list.
  unsigned error = AddRestrictingSidCurrentUser();
  if (ERROR_SUCCESS != error)
    return error;

  TOKEN_GROUPS *token_groups = NULL;
  DWORD size = 0;

  // Get the buffer size required.
  BOOL result = ::GetTokenInformation(effective_token_, TokenGroups, NULL, 0,
                                      &size);
  if (!size)
    return ::GetLastError();

  token_groups = reinterpret_cast<TOKEN_GROUPS*>(new BYTE[size]);
  result = ::GetTokenInformation(effective_token_,
                                 TokenGroups,
                                 token_groups,
                                 size,
                                 &size);
  if (!result) {
    delete[] reinterpret_cast<BYTE*>(token_groups);
    return ::GetLastError();
  }

  // Build the list of restricting sids from all groups.
  for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) {
    if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0)
      AddRestrictingSid(reinterpret_cast<SID*>(token_groups->Groups[i].Sid));
  }

  delete[] reinterpret_cast<BYTE*>(token_groups);

  return ERROR_SUCCESS;
}

unsigned RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) {
  integrity_level_ = integrity_level;
  return ERROR_SUCCESS;
}

}  // namespace sandbox
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#include <iostream>
#include <list>
#include <sstream>
#include <string>

#include "base/cprintf.hh"
#include "base/misc.hh"

using namespace std;

int
main()
{
    char foo[] = "foo";
    cprintf("%s\n", foo);

    string _bar = "asdfkhasdlkfjhasdlkfhjalksdjfhalksdjhfalksdjfhalksdjhf";
    int length = 11;
    char bar[length + 1];
    bar[length] = 0;

    memcpy(bar, _bar.c_str(), length);
    warn("%s\n", bar);

    cprintf("%d\n", 'A');
    cprintf("%shits%%s + %smisses%%s\n", "test", "test");
    cprintf("%%s%-10s %c he went home \'\"%d %#o %#x %1.5f %1.2E\n",
            "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.141592653589, 1.1e10);

    cprintf("another test\n");

    stringstream buffer;
    ccprintf(buffer, "%-10s %c he home \'\"%d %#o %#x %1.5f %1.2E\n",
             "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.14159265, 1.1e10);

    double f = 314159.26535897932384;

    #define ctest(x, y) printf(x, y); cprintf(x, y); cprintf("\n");
    ctest("%1.8f\n", f);
    ctest("%2.8f\n", f);
    ctest("%3.8f\n", f);
    ctest("%4.8f\n", f);
    ctest("%5.8f\n", f);
    ctest("%6.8f\n", f);
    ctest("%12.8f\n", f);
    ctest("%1000.8f\n", f);
    ctest("%1.0f\n", f);
    ctest("%1.1f\n", f);
    ctest("%1.2f\n", f);
    ctest("%1.3f\n", f);
    ctest("%1.4f\n", f);
    ctest("%1.5f\n", f);
    ctest("%1.6f\n", f);
    ctest("%1.7f\n", f);
    ctest("%1.8f\n", f);
    ctest("%1.9f\n", f);
    ctest("%1.10f\n", f);
    ctest("%1.11f\n", f);
    ctest("%1.12f\n", f);
    ctest("%1.13f\n", f);
    ctest("%1.14f\n", f);
    ctest("%1.15f\n", f);
    ctest("%1.16f\n", f);
    ctest("%1.17f\n", f);
    ctest("%1.18f\n", f);

    cout << "foo\n";

    f = 0.00000026535897932384;
    ctest("%1.8f\n", f);
    ctest("%2.8f\n", f);
    ctest("%3.8f\n", f);
    ctest("%4.8f\n", f);
    ctest("%5.8f\n", f);
    ctest("%6.8f\n", f);
    ctest("%12.8f\n", f);
    ctest("%1.0f\n", f);
    ctest("%1.1f\n", f);
    ctest("%1.2f\n", f);
    ctest("%1.3f\n", f);
    ctest("%1.4f\n", f);
    ctest("%1.5f\n", f);
    ctest("%1.6f\n", f);
    ctest("%1.7f\n", f);
    ctest("%1.8f\n", f);
    ctest("%1.9f\n", f);
    ctest("%1.10f\n", f);
    ctest("%1.11f\n", f);
    ctest("%1.12f\n", f);
    ctest("%1.13f\n", f);
    ctest("%1.14f\n", f);
    ctest("%1.15f\n", f);
    ctest("%1.16f\n", f);
    ctest("%1.17f\n", f);
    ctest("%1.18f\n", f);

    f = 0.00000026535897932384;
    ctest("%1.8e\n", f);
    ctest("%2.8e\n", f);
    ctest("%3.8e\n", f);
    ctest("%4.8e\n", f);
    ctest("%5.8e\n", f);
    ctest("%6.8e\n", f);
    ctest("%12.8e\n", f);
    ctest("%1.0e\n", f);
    ctest("%1.1e\n", f);
    ctest("%1.2e\n", f);
    ctest("%1.3e\n", f);
    ctest("%1.4e\n", f);
    ctest("%1.5e\n", f);
    ctest("%1.6e\n", f);
    ctest("%1.7e\n", f);
    ctest("%1.8e\n", f);
    ctest("%1.9e\n", f);
    ctest("%1.10e\n", f);
    ctest("%1.11e\n", f);
    ctest("%1.12e\n", f);
    ctest("%1.13e\n", f);
    ctest("%1.14e\n", f);
    ctest("%1.15e\n", f);
    ctest("%1.16e\n", f);
    ctest("%1.17e\n", f);
    ctest("%1.18e\n", f);

    cout << buffer.str();

    cout.width(0);
    cout.precision(1);
    cout << f << "\n";

    string foo1 = "string test";
    cprintf("%s\n", foo1);

    stringstream foo2;
    foo2 << "stringstream test";
    cprintf("%s\n", foo2);

    cprintf("%c  %c\n", 'c', 65);

    cout << '9' << endl;

    cout << endl;

    cprintf("%08.4f\n", 99.99);
    cprintf("%0*.*f\n", 8, 4, 99.99);
    cprintf("%07.*f\n", 4, 1.234);
    cprintf("%#0*x\n", 9, 123412);
    return 0;
}
<commit_msg>tests: Fix compilation of cprinftest.<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#include <iostream>
#include <list>
#include <sstream>
#include <string>

#include "base/cprintf.hh"
#include "base/misc.hh"

using namespace std;

int
main()
{
    char foo[] = "foo";
    cprintf("%s\n", foo);

    string _bar = "asdfkhasdlkfjhasdlkfhjalksdjfhalksdjhfalksdjfhalksdjhf";
    const int length = 11;
    char bar[length + 1];
    bar[length] = 0;

    memcpy(bar, _bar.c_str(), length);
    warn("%s\n", bar);

    cprintf("%d\n", 'A');
    cprintf("%shits%%s + %smisses%%s\n", "test", "test");
    cprintf("%%s%-10s %c he went home \'\"%d %#o %#x %1.5f %1.2E\n",
            "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.141592653589, 1.1e10);

    cprintf("another test\n");

    stringstream buffer;
    ccprintf(buffer, "%-10s %c he home \'\"%d %#o %#x %1.5f %1.2E\n",
             "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.14159265, 1.1e10);

    double f = 314159.26535897932384;

    #define ctest(x, y) printf(x, y); cprintf(x, y); cprintf("\n");
    ctest("%1.8f\n", f);
    ctest("%2.8f\n", f);
    ctest("%3.8f\n", f);
    ctest("%4.8f\n", f);
    ctest("%5.8f\n", f);
    ctest("%6.8f\n", f);
    ctest("%12.8f\n", f);
    ctest("%1000.8f\n", f);
    ctest("%1.0f\n", f);
    ctest("%1.1f\n", f);
    ctest("%1.2f\n", f);
    ctest("%1.3f\n", f);
    ctest("%1.4f\n", f);
    ctest("%1.5f\n", f);
    ctest("%1.6f\n", f);
    ctest("%1.7f\n", f);
    ctest("%1.8f\n", f);
    ctest("%1.9f\n", f);
    ctest("%1.10f\n", f);
    ctest("%1.11f\n", f);
    ctest("%1.12f\n", f);
    ctest("%1.13f\n", f);
    ctest("%1.14f\n", f);
    ctest("%1.15f\n", f);
    ctest("%1.16f\n", f);
    ctest("%1.17f\n", f);
    ctest("%1.18f\n", f);

    cout << "foo\n";

    f = 0.00000026535897932384;
    ctest("%1.8f\n", f);
    ctest("%2.8f\n", f);
    ctest("%3.8f\n", f);
    ctest("%4.8f\n", f);
    ctest("%5.8f\n", f);
    ctest("%6.8f\n", f);
    ctest("%12.8f\n", f);
    ctest("%1.0f\n", f);
    ctest("%1.1f\n", f);
    ctest("%1.2f\n", f);
    ctest("%1.3f\n", f);
    ctest("%1.4f\n", f);
    ctest("%1.5f\n", f);
    ctest("%1.6f\n", f);
    ctest("%1.7f\n", f);
    ctest("%1.8f\n", f);
    ctest("%1.9f\n", f);
    ctest("%1.10f\n", f);
    ctest("%1.11f\n", f);
    ctest("%1.12f\n", f);
    ctest("%1.13f\n", f);
    ctest("%1.14f\n", f);
    ctest("%1.15f\n", f);
    ctest("%1.16f\n", f);
    ctest("%1.17f\n", f);
    ctest("%1.18f\n", f);

    f = 0.00000026535897932384;
    ctest("%1.8e\n", f);
    ctest("%2.8e\n", f);
    ctest("%3.8e\n", f);
    ctest("%4.8e\n", f);
    ctest("%5.8e\n", f);
    ctest("%6.8e\n", f);
    ctest("%12.8e\n", f);
    ctest("%1.0e\n", f);
    ctest("%1.1e\n", f);
    ctest("%1.2e\n", f);
    ctest("%1.3e\n", f);
    ctest("%1.4e\n", f);
    ctest("%1.5e\n", f);
    ctest("%1.6e\n", f);
    ctest("%1.7e\n", f);
    ctest("%1.8e\n", f);
    ctest("%1.9e\n", f);
    ctest("%1.10e\n", f);
    ctest("%1.11e\n", f);
    ctest("%1.12e\n", f);
    ctest("%1.13e\n", f);
    ctest("%1.14e\n", f);
    ctest("%1.15e\n", f);
    ctest("%1.16e\n", f);
    ctest("%1.17e\n", f);
    ctest("%1.18e\n", f);

    cout << buffer.str();

    cout.width(0);
    cout.precision(1);
    cout << f << "\n";

    string foo1 = "string test";
    cprintf("%s\n", foo1);

    stringstream foo2;
    foo2 << "stringstream test";
    cprintf("%s\n", foo2);

    cprintf("%c  %c\n", 'c', 65);

    cout << '9' << endl;

    cout << endl;

    cprintf("%08.4f\n", 99.99);
    cprintf("%0*.*f\n", 8, 4, 99.99);
    cprintf("%07.*f\n", 4, 1.234);
    cprintf("%#0*x\n", 9, 123412);
    return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "test/fuzzers/audio_processing_fuzzer_helper.h"

#include <algorithm>
#include <array>
#include <cmath>
#include <limits>

#include "api/audio/audio_frame.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "rtc_base/checks.h"

namespace webrtc {
namespace {
void GenerateFloatFrame(test::FuzzDataHelper* fuzz_data,
                        size_t input_rate,
                        size_t num_channels,
                        float* const* float_frames) {
  const size_t samples_per_input_channel =
      rtc::CheckedDivExact(input_rate, 100ul);
  RTC_DCHECK_LE(samples_per_input_channel, 480);
  for (size_t i = 0; i < num_channels; ++i) {
    for (size_t j = 0; j < samples_per_input_channel; ++j) {
      float_frames[i][j] =
          static_cast<float>(fuzz_data->ReadOrDefaultValue<int16_t>(0)) /
          static_cast<float>(std::numeric_limits<int16_t>::max());
    }
  }
}

void GenerateFixedFrame(test::FuzzDataHelper* fuzz_data,
                        size_t input_rate,
                        size_t num_channels,
                        AudioFrame* fixed_frame) {
  const size_t samples_per_input_channel =
      rtc::CheckedDivExact(input_rate, 100ul);
  fixed_frame->samples_per_channel_ = samples_per_input_channel;
  fixed_frame->sample_rate_hz_ = input_rate;
  fixed_frame->num_channels_ = num_channels;

  RTC_DCHECK_LE(samples_per_input_channel * num_channels,
                AudioFrame::kMaxDataSizeSamples);
  for (size_t i = 0; i < samples_per_input_channel * num_channels; ++i) {
    fixed_frame->mutable_data()[i] = fuzz_data->ReadOrDefaultValue<int16_t>(0);
  }
}
}  // namespace

void FuzzAudioProcessing(test::FuzzDataHelper* fuzz_data,
                         std::unique_ptr<AudioProcessing> apm) {
  AudioFrame fixed_frame;
  std::array<float, 480> float_frame1;
  std::array<float, 480> float_frame2;
  std::array<float* const, 2> float_frame_ptrs = {
      &float_frame1[0], &float_frame2[0],
  };
  float* const* ptr_to_float_frames = &float_frame_ptrs[0];

  using Rate = AudioProcessing::NativeRate;
  const Rate rate_kinds[] = {Rate::kSampleRate8kHz, Rate::kSampleRate16kHz,
                             Rate::kSampleRate32kHz, Rate::kSampleRate48kHz};

  // We may run out of fuzz data in the middle of a loop iteration. In
  // that case, default values will be used for the rest of that
  // iteration.
  while (fuzz_data->CanReadBytes(1)) {
    const bool is_float = fuzz_data->ReadOrDefaultValue(true);
    // Decide input/output rate for this iteration.
    const auto input_rate =
        static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
    const auto output_rate =
        static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));

    const int num_channels = fuzz_data->ReadOrDefaultValue(true) ? 2 : 1;
    const uint8_t stream_delay = fuzz_data->ReadOrDefaultValue<uint8_t>(0);

    // API call needed for AEC-2 and AEC-m to run.
    apm->set_stream_delay_ms(stream_delay);

    const bool key_pressed = fuzz_data->ReadOrDefaultValue(true);
    apm->set_stream_key_pressed(key_pressed);

    // Make the APM call depending on capture/render mode and float /
    // fix interface.
    const bool is_capture = fuzz_data->ReadOrDefaultValue(true);

    // Fill the arrays with audio samples from the data.
    int apm_return_code = AudioProcessing::Error::kNoError;
    if (is_float) {
      GenerateFloatFrame(fuzz_data, input_rate, num_channels,
                         ptr_to_float_frames);
      if (is_capture) {
        apm_return_code = apm->ProcessStream(
            ptr_to_float_frames, StreamConfig(input_rate, num_channels),
            StreamConfig(output_rate, num_channels), ptr_to_float_frames);
      } else {
        apm_return_code = apm->ProcessReverseStream(
            ptr_to_float_frames, StreamConfig(input_rate, 1),
            StreamConfig(output_rate, 1), ptr_to_float_frames);
      }
    } else {
      GenerateFixedFrame(fuzz_data, input_rate, num_channels, &fixed_frame);

      if (is_capture) {
        apm_return_code = apm->ProcessStream(&fixed_frame);
      } else {
        apm_return_code = apm->ProcessReverseStream(&fixed_frame);
      }
    }

    // Make calls to stats gathering functions to cover these
    // codeways.
    static_cast<void>(apm->GetStatistics());
    static_cast<void>(apm->GetStatistics(true));
    static_cast<void>(apm->UpdateHistogramsOnCallEnd());

    RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
  }
}
}  // namespace webrtc
<commit_msg>Fuzz more kinds of floats in the APM fuzzer.<commit_after>/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "test/fuzzers/audio_processing_fuzzer_helper.h"

#include <algorithm>
#include <array>
#include <cmath>
#include <limits>

#include "api/audio/audio_frame.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "rtc_base/checks.h"

namespace webrtc {
namespace {
bool ValidForApm(float x) {
  return std::isfinite(x) && -1.0f <= x && x <= 1.0f;
}

void GenerateFloatFrame(test::FuzzDataHelper* fuzz_data,
                        size_t input_rate,
                        size_t num_channels,
                        float* const* float_frames) {
  const size_t samples_per_input_channel =
      rtc::CheckedDivExact(input_rate, 100ul);
  RTC_DCHECK_LE(samples_per_input_channel, 480);
  for (size_t i = 0; i < num_channels; ++i) {
    std::fill(float_frames[i], float_frames[i] + samples_per_input_channel, 0);
    const size_t read_bytes = sizeof(float) * samples_per_input_channel;
    if (fuzz_data->CanReadBytes(read_bytes)) {
      rtc::ArrayView<const uint8_t> byte_array =
          fuzz_data->ReadByteArray(read_bytes);
      memmove(float_frames[i], byte_array.begin(), read_bytes);
    }

    // Sanitize input.
    for (size_t j = 0; j < samples_per_input_channel; ++j) {
      if (!ValidForApm(float_frames[i][j])) {
        float_frames[i][j] = 0.f;
      }
    }
  }
}

void GenerateFixedFrame(test::FuzzDataHelper* fuzz_data,
                        size_t input_rate,
                        size_t num_channels,
                        AudioFrame* fixed_frame) {
  const size_t samples_per_input_channel =
      rtc::CheckedDivExact(input_rate, 100ul);
  fixed_frame->samples_per_channel_ = samples_per_input_channel;
  fixed_frame->sample_rate_hz_ = input_rate;
  fixed_frame->num_channels_ = num_channels;

  RTC_DCHECK_LE(samples_per_input_channel * num_channels,
                AudioFrame::kMaxDataSizeSamples);
  for (size_t i = 0; i < samples_per_input_channel * num_channels; ++i) {
    fixed_frame->mutable_data()[i] = fuzz_data->ReadOrDefaultValue<int16_t>(0);
  }
}
}  // namespace

void FuzzAudioProcessing(test::FuzzDataHelper* fuzz_data,
                         std::unique_ptr<AudioProcessing> apm) {
  AudioFrame fixed_frame;
  std::array<float, 480> float_frame1;
  std::array<float, 480> float_frame2;
  std::array<float* const, 2> float_frame_ptrs = {
      &float_frame1[0], &float_frame2[0],
  };
  float* const* ptr_to_float_frames = &float_frame_ptrs[0];

  using Rate = AudioProcessing::NativeRate;
  const Rate rate_kinds[] = {Rate::kSampleRate8kHz, Rate::kSampleRate16kHz,
                             Rate::kSampleRate32kHz, Rate::kSampleRate48kHz};

  // We may run out of fuzz data in the middle of a loop iteration. In
  // that case, default values will be used for the rest of that
  // iteration.
  while (fuzz_data->CanReadBytes(1)) {
    const bool is_float = fuzz_data->ReadOrDefaultValue(true);
    // Decide input/output rate for this iteration.
    const auto input_rate =
        static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
    const auto output_rate =
        static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));

    const int num_channels = fuzz_data->ReadOrDefaultValue(true) ? 2 : 1;
    const uint8_t stream_delay = fuzz_data->ReadOrDefaultValue<uint8_t>(0);

    // API call needed for AEC-2 and AEC-m to run.
    apm->set_stream_delay_ms(stream_delay);

    const bool key_pressed = fuzz_data->ReadOrDefaultValue(true);
    apm->set_stream_key_pressed(key_pressed);

    // Make the APM call depending on capture/render mode and float /
    // fix interface.
    const bool is_capture = fuzz_data->ReadOrDefaultValue(true);

    // Fill the arrays with audio samples from the data.
    int apm_return_code = AudioProcessing::Error::kNoError;
    if (is_float) {
      GenerateFloatFrame(fuzz_data, input_rate, num_channels,
                         ptr_to_float_frames);
      if (is_capture) {
        apm_return_code = apm->ProcessStream(
            ptr_to_float_frames, StreamConfig(input_rate, num_channels),
            StreamConfig(output_rate, num_channels), ptr_to_float_frames);
      } else {
        apm_return_code = apm->ProcessReverseStream(
            ptr_to_float_frames, StreamConfig(input_rate, 1),
            StreamConfig(output_rate, 1), ptr_to_float_frames);
      }
    } else {
      GenerateFixedFrame(fuzz_data, input_rate, num_channels, &fixed_frame);

      if (is_capture) {
        apm_return_code = apm->ProcessStream(&fixed_frame);
      } else {
        apm_return_code = apm->ProcessReverseStream(&fixed_frame);
      }
    }

    // Make calls to stats gathering functions to cover these
    // codeways.
    static_cast<void>(apm->GetStatistics());
    static_cast<void>(apm->GetStatistics(true));
    static_cast<void>(apm->UpdateHistogramsOnCallEnd());

    RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
  }
}
}  // namespace webrtc
<|endoftext|>


<commit_before>// compilation
// $ g++ -std=c++11 main.cpp -o main

#include <iostream>
#include <fstream>
#include <array>
#include <vector>
#include <string>
#include <chrono>

typedef std::array<int, 4> Vector;
typedef std::array<std::array<int, 4>, 4> Matrix;

typedef std::vector<Vector> Vectors;
typedef std::vector<Matrix> Matrices;

Matrices readMatrices(const std::string& filename)
{
  Matrices M;
  std::ifstream input(filename);
  unsigned int linTransCount;

  input >> linTransCount;

  for (size_t i = 0; i < linTransCount; i++)
  {
    Matrix m;

    for (size_t i = 0; i < 4; i++) {
      input >> m[i][0] >> m[i][1] >> m[i][2] >> m[i][3];
    }

    M.push_back(m);
  }

  input.close();
  return M;
}

Vectors readVectors(const std::string& filename)
{
  Vectors V;
  std::ifstream input(filename);
  unsigned int vectorCount;

  input >> vectorCount;

  for (size_t i = 0; i < vectorCount; i++)
  {
    Vector v;

    input >> v[0] >> v[1] >> v[2];

    v[3] = 1;

    V.push_back(v);
  }

  input.close();
  return V;
}

void writeFile(const std::string& filename, Vectors& V)
{
  std::ofstream output(filename);

  for (auto const& v : V)
  {
    for (size_t i = 0; i < v.size(); i++) {
      output << v[i] << " ";
    }

    output << std::endl;
  }

  output.close();
}

void multiplication(const Matrix& m, Vector& v)
{
  const int length = v.size();

  Vector result;

  for (size_t i = 0; i < length; i++) {
    int item = 0;

    for (size_t j = 0; j < length; j++) {
      item += m[i][j] * v[j];
    }

    v[i] = item;
  }
}

void linTransforms(Vectors& V, Matrices& M)
{
  for (auto& v : V)
  {
    for (auto const& m : M)
    {
      multiplication(m, v);
    }
  }
}

int main()
{
  using namespace std::chrono;

  Matrices M = readMatrices("tests/0/input_matrices.txt");
  Vectors V = readVectors("tests/0/input_points.txt");

  time_point<system_clock> t0, t1;
  t0 = system_clock::now();

  linTransforms(V, M);

  t1 = system_clock::now();
  std::cout << duration_cast<milliseconds>(t1 - t0).count() << "ms\n";

  writeFile("output.txt", V);

  return 0;
}
<commit_msg>bead3 working with 1 thread<commit_after>// compilation
// $ g++ -std=c++11 main.cpp -o main

#include <iostream>
#include <fstream>
#include <array>
#include <vector>
#include <string>
#include <chrono>

typedef std::array<int, 4> Vector;
typedef std::array<std::array<int, 4>, 4> Matrix;

typedef std::vector<Vector> Vectors;
typedef std::vector<Matrix> Matrices;

Matrices readMatrices(const std::string& filename)
{
  Matrices M;
  std::ifstream input(filename);
  unsigned int linTransCount;

  input >> linTransCount;

  for (size_t i = 0; i < linTransCount; i++)
  {
    Matrix m;

    for (size_t i = 0; i < 4; i++) {
      input >> m[i][0] >> m[i][1] >> m[i][2] >> m[i][3];
    }

    M.push_back(m);
  }

  input.close();
  return M;
}

Vectors readVectors(const std::string& filename)
{
  Vectors V;
  std::ifstream input(filename);
  unsigned int vectorCount;

  input >> vectorCount;

  for (size_t i = 0; i < vectorCount; i++)
  {
    Vector v;

    input >> v[0] >> v[1] >> v[2];

    v[3] = 1;

    V.push_back(v);
  }

  input.close();
  return V;
}

void writeVectors(const std::string& filename, Vectors& V)
{
  std::ofstream output(filename);

  for (auto const& v : V)
  {
    for (size_t i = 0; i < v.size() - 1; i++) {
      output << v[i] << " ";
    }

    output << std::endl;
  }

  output.close();
}

Vector linTransform(const Matrix& m, const Vector& v)
{
  Vector result;

  for (size_t i = 0; i < v.size(); i++) {
    result[i] = 0;

    for (size_t j = 0; j < v.size(); j++) {
      result[i] += m[i][j] * v[j];
    }
  }

  return result;
}

void linTransforms(Vectors& V, Matrices& M)
{
  for (auto& v : V)
  {
    for (auto const& m : M)
    {
      v = linTransform(m, v);
    }
  }
}

int main()
{
  using namespace std::chrono;

  Matrices M = readMatrices("tests/0/input_matrices.txt");
  Vectors V = readVectors("tests/0/input_points.txt");

  time_point<system_clock> t0, t1;
  t0 = system_clock::now();

  linTransforms(V, M);

  t1 = system_clock::now();
  std::cout << duration_cast<milliseconds>(t1 - t0).count() << "ms\n";

  writeVectors("output.txt", V);

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ddelink.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 18:42:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifdef PCH
#include "core_pch.hxx"
#endif

#pragma hdrstop

// INCLUDE ---------------------------------------------------------------

#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif
#include <svx/linkmgr.hxx>
#include <sfx2/bindings.hxx>
#include <svtools/zforlist.hxx>

#include "ddelink.hxx"
#include "brdcst.hxx"
#include "document.hxx"
#include "scmatrix.hxx"
#include "patattr.hxx"
#include "rechead.hxx"
#include "rangeseq.hxx"
#include "sc.hrc"
#include "hints.hxx"

TYPEINIT2(ScDdeLink,::sfx2::SvBaseLink,SfxBroadcaster);

#ifdef PM2
#define DDE_TXT_ENCODING    RTL_TEXTENCODING_IBM_850
#else
#define DDE_TXT_ENCODING    RTL_TEXTENCODING_MS_1252
#endif

BOOL ScDdeLink::bIsInUpdate = FALSE;

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

ScDdeLink::ScDdeLink( ScDocument* pD, const String& rA, const String& rT, const String& rI,
                        BYTE nM ) :
    ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
    pDoc( pD ),
    aAppl( rA ),
    aTopic( rT ),
    aItem( rI ),
    nMode( nM ),
    pResult( NULL ),
    bNeedUpdate( FALSE )
{
}

__EXPORT ScDdeLink::~ScDdeLink()
{
    // Verbindung aufheben

    // pResult is refcounted
}

ScDdeLink::ScDdeLink( ScDocument* pD, const ScDdeLink& rOther ) :
    ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
    pDoc    ( pD ),
    aAppl   ( rOther.aAppl ),
    aTopic  ( rOther.aTopic ),
    aItem   ( rOther.aItem ),
    nMode   ( rOther.nMode ),
    pResult ( NULL ),
    bNeedUpdate( FALSE )
{
    if (rOther.pResult)
        pResult = rOther.pResult->Clone();
}

ScDdeLink::ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& rHdr ) :
    ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
    pDoc( pD ),
    pResult( NULL ),
    bNeedUpdate( FALSE )
{
    rHdr.StartEntry();

    rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
    rStream.ReadByteString( aAppl, eCharSet );
    rStream.ReadByteString( aTopic, eCharSet );
    rStream.ReadByteString( aItem, eCharSet );

    BOOL bHasValue;
    rStream >> bHasValue;
    if ( bHasValue )
        pResult = new ScMatrix( rStream );

    if (rHdr.BytesLeft())       // neu in 388b und der 364w (RealTime-Client) Version
        rStream >> nMode;
    else
        nMode = SC_DDE_DEFAULT;

    rHdr.EndEntry();
}

void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
{
    rHdr.StartEntry();

    rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
    rStream.WriteByteString( aAppl, eCharSet );
    rStream.WriteByteString( aTopic, eCharSet );
    rStream.WriteByteString( aItem, eCharSet );

    BOOL bHasValue = ( pResult != NULL );
    rStream << bHasValue;
    if (bHasValue)
        pResult->Store( rStream );

    if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 )      // nicht bei 4.0 Export
        rStream << nMode;                                   // seit 388b

    //  Links mit Mode != SC_DDE_DEFAULT werden bei 4.0 Export komplett weggelassen
    //  (aus ScDocument::SaveDdeLinks)

    rHdr.EndEntry();
}

void __EXPORT ScDdeLink::DataChanged( const String& rMimeType,
                                const ::com::sun::star::uno::Any & rValue )
{
    //  wir koennen nur Strings...
    if ( FORMAT_STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
        return;

    String aLinkStr;
    ScByteSequenceToString::GetString( aLinkStr, rValue, DDE_TXT_ENCODING );
    aLinkStr.ConvertLineEnd(LINEEND_LF);

    //  wenn String mit Zeilenende aufhoert, streichen:

    xub_StrLen nLen = aLinkStr.Len();
    if (nLen && aLinkStr.GetChar(nLen-1) == '\n')
        aLinkStr.Erase(nLen-1);

    String aLine;
    SCSIZE nCols = 1;       // Leerstring -> eine leere Zelle
    SCSIZE nRows = 1;
    if (aLinkStr.Len())
    {
        nRows = static_cast<SCSIZE>(aLinkStr.GetTokenCount( '\n' ));
        aLine = aLinkStr.GetToken( 0, '\n' );
        if (aLine.Len())
            nCols = static_cast<SCSIZE>(aLine.GetTokenCount( '\t' ));
    }

    if (!nRows || !nCols)               // keine Daten
    {
        pResult.Clear();
    }
    else                                // Daten aufteilen
    {
        //  Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
        pResult = new ScMatrix( nCols, nRows );

        SvNumberFormatter* pFormatter = pDoc->GetFormatTable();

        //  nMode bestimmt, wie der Text interpretiert wird (#44455#/#49783#):
        //  SC_DDE_DEFAULT - Zahlformat aus Zellvorlage "Standard"
        //  SC_DDE_ENGLISH - Standard-Zahlformat fuer English/US
        //  SC_DDE_TEXT    - ohne NumberFormatter direkt als String
        ULONG nStdFormat = 0;
        if ( nMode == SC_DDE_DEFAULT )
        {
            ScPatternAttr* pDefPattern = pDoc->GetDefPattern();     // enthaelt Standard-Vorlage
            if ( pDefPattern )
                nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
        }
        else if ( nMode == SC_DDE_ENGLISH )
            nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);

        String aEntry;
        for (SCSIZE nR=0; nR<nRows; nR++)
        {
            aLine = aLinkStr.GetToken( (xub_StrLen) nR, '\n' );
            for (SCSIZE nC=0; nC<nCols; nC++)
            {
                aEntry = aLine.GetToken( (xub_StrLen) nC, '\t' );
                ULONG nIndex = nStdFormat;
                double fVal;
                if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
                    pResult->PutDouble( fVal, nC, nR );
                else
                    pResult->PutString( aEntry, nC, nR );
            }
        }
    }

    //  Es hat sich was getan...

    if (HasListeners())
    {
        Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
        pDoc->TrackFormulas();      // muss sofort passieren
        pDoc->StartTrackTimer();

        //  StartTrackTimer ruft asynchron TrackFormulas, Broadcast(FID_DATACHANGED),
        //  ResetChanged, SetModified und Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
        //  TrackFormulas zusaetzlich nochmal sofort, damit nicht z.B. durch IdleCalc
        //  eine Formel berechnet wird, die noch im FormulaTrack steht (#61676#)

        //  notify Uno objects (for XRefreshListener)
        //  must be after TrackFormulas
        //! do this asynchronously?
        ScLinkRefreshedHint aHint;
        aHint.SetDdeLink( aAppl, aTopic, aItem, nMode );
        pDoc->BroadcastUno( aHint );
    }
}

void ScDdeLink::NewData(SCSIZE nCols, SCSIZE nRows)
{
    pResult = new ScMatrix( nCols, nRows );
}

void ScDdeLink::ResetValue()
{
    pResult.Clear();

    //  Es hat sich was getan...
    //  Tracking, FID_DATACHANGED etc. passiert von aussen

    if (HasListeners())
        Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
}

void __EXPORT ScDdeLink::ListenersGone()
{
    BOOL bWas = bIsInUpdate;
    bIsInUpdate = TRUE;             // Remove() kann Reschedule ausloesen??!?

    ScDocument* pStackDoc = pDoc;   // member pDoc can't be used after removing the link

    SvxLinkManager* pLinkMgr = pDoc->GetLinkManager();
    pLinkMgr->Remove( this);        // deletes this

    if ( !pLinkMgr->GetLinks().Count() )            // letzten geloescht ?
    {
        SfxBindings* pBindings = pStackDoc->GetViewBindings();      // don't use member pDoc!
        if (pBindings)
            pBindings->Invalidate( SID_LINKS );
    }

    bIsInUpdate = bWas;
}

void ScDdeLink::TryUpdate()
{
    if (bIsInUpdate)
        bNeedUpdate = TRUE;         // kann jetzt nicht ausgefuehrt werden
    else
    {
        bIsInUpdate = TRUE;
        //Application::Reschedule();    //! OS/2-Simulation
        pDoc->IncInDdeLinkUpdate();
        Update();
        pDoc->DecInDdeLinkUpdate();
        bIsInUpdate = FALSE;
        bNeedUpdate = FALSE;
    }
}

<commit_msg>INTEGRATION: CWS numberformat (1.12.42); FILE MERGED 2005/10/26 17:51:50 kendy 1.12.42.1: #i55546# The ULONG -> sal_uInt32 patches related to NumberFormat extracted from ooo64bit02 CWS.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ddelink.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: rt $ $Date: 2005-12-14 15:06:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifdef PCH
#include "core_pch.hxx"
#endif

#pragma hdrstop

// INCLUDE ---------------------------------------------------------------

#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif
#include <svx/linkmgr.hxx>
#include <sfx2/bindings.hxx>
#include <svtools/zforlist.hxx>

#include "ddelink.hxx"
#include "brdcst.hxx"
#include "document.hxx"
#include "scmatrix.hxx"
#include "patattr.hxx"
#include "rechead.hxx"
#include "rangeseq.hxx"
#include "sc.hrc"
#include "hints.hxx"

TYPEINIT2(ScDdeLink,::sfx2::SvBaseLink,SfxBroadcaster);

#ifdef PM2
#define DDE_TXT_ENCODING    RTL_TEXTENCODING_IBM_850
#else
#define DDE_TXT_ENCODING    RTL_TEXTENCODING_MS_1252
#endif

BOOL ScDdeLink::bIsInUpdate = FALSE;

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

ScDdeLink::ScDdeLink( ScDocument* pD, const String& rA, const String& rT, const String& rI,
                        BYTE nM ) :
    ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
    pDoc( pD ),
    aAppl( rA ),
    aTopic( rT ),
    aItem( rI ),
    nMode( nM ),
    pResult( NULL ),
    bNeedUpdate( FALSE )
{
}

__EXPORT ScDdeLink::~ScDdeLink()
{
    // Verbindung aufheben

    // pResult is refcounted
}

ScDdeLink::ScDdeLink( ScDocument* pD, const ScDdeLink& rOther ) :
    ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
    pDoc    ( pD ),
    aAppl   ( rOther.aAppl ),
    aTopic  ( rOther.aTopic ),
    aItem   ( rOther.aItem ),
    nMode   ( rOther.nMode ),
    pResult ( NULL ),
    bNeedUpdate( FALSE )
{
    if (rOther.pResult)
        pResult = rOther.pResult->Clone();
}

ScDdeLink::ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& rHdr ) :
    ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
    pDoc( pD ),
    pResult( NULL ),
    bNeedUpdate( FALSE )
{
    rHdr.StartEntry();

    rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
    rStream.ReadByteString( aAppl, eCharSet );
    rStream.ReadByteString( aTopic, eCharSet );
    rStream.ReadByteString( aItem, eCharSet );

    BOOL bHasValue;
    rStream >> bHasValue;
    if ( bHasValue )
        pResult = new ScMatrix( rStream );

    if (rHdr.BytesLeft())       // neu in 388b und der 364w (RealTime-Client) Version
        rStream >> nMode;
    else
        nMode = SC_DDE_DEFAULT;

    rHdr.EndEntry();
}

void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
{
    rHdr.StartEntry();

    rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
    rStream.WriteByteString( aAppl, eCharSet );
    rStream.WriteByteString( aTopic, eCharSet );
    rStream.WriteByteString( aItem, eCharSet );

    BOOL bHasValue = ( pResult != NULL );
    rStream << bHasValue;
    if (bHasValue)
        pResult->Store( rStream );

    if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 )      // nicht bei 4.0 Export
        rStream << nMode;                                   // seit 388b

    //  Links mit Mode != SC_DDE_DEFAULT werden bei 4.0 Export komplett weggelassen
    //  (aus ScDocument::SaveDdeLinks)

    rHdr.EndEntry();
}

void __EXPORT ScDdeLink::DataChanged( const String& rMimeType,
                                const ::com::sun::star::uno::Any & rValue )
{
    //  wir koennen nur Strings...
    if ( FORMAT_STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
        return;

    String aLinkStr;
    ScByteSequenceToString::GetString( aLinkStr, rValue, DDE_TXT_ENCODING );
    aLinkStr.ConvertLineEnd(LINEEND_LF);

    //  wenn String mit Zeilenende aufhoert, streichen:

    xub_StrLen nLen = aLinkStr.Len();
    if (nLen && aLinkStr.GetChar(nLen-1) == '\n')
        aLinkStr.Erase(nLen-1);

    String aLine;
    SCSIZE nCols = 1;       // Leerstring -> eine leere Zelle
    SCSIZE nRows = 1;
    if (aLinkStr.Len())
    {
        nRows = static_cast<SCSIZE>(aLinkStr.GetTokenCount( '\n' ));
        aLine = aLinkStr.GetToken( 0, '\n' );
        if (aLine.Len())
            nCols = static_cast<SCSIZE>(aLine.GetTokenCount( '\t' ));
    }

    if (!nRows || !nCols)               // keine Daten
    {
        pResult.Clear();
    }
    else                                // Daten aufteilen
    {
        //  Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
        pResult = new ScMatrix( nCols, nRows );

        SvNumberFormatter* pFormatter = pDoc->GetFormatTable();

        //  nMode bestimmt, wie der Text interpretiert wird (#44455#/#49783#):
        //  SC_DDE_DEFAULT - Zahlformat aus Zellvorlage "Standard"
        //  SC_DDE_ENGLISH - Standard-Zahlformat fuer English/US
        //  SC_DDE_TEXT    - ohne NumberFormatter direkt als String
        ULONG nStdFormat = 0;
        if ( nMode == SC_DDE_DEFAULT )
        {
            ScPatternAttr* pDefPattern = pDoc->GetDefPattern();     // enthaelt Standard-Vorlage
            if ( pDefPattern )
                nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
        }
        else if ( nMode == SC_DDE_ENGLISH )
            nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);

        String aEntry;
        for (SCSIZE nR=0; nR<nRows; nR++)
        {
            aLine = aLinkStr.GetToken( (xub_StrLen) nR, '\n' );
            for (SCSIZE nC=0; nC<nCols; nC++)
            {
                aEntry = aLine.GetToken( (xub_StrLen) nC, '\t' );
                sal_uInt32 nIndex = nStdFormat;
                double fVal;
                if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
                    pResult->PutDouble( fVal, nC, nR );
                else
                    pResult->PutString( aEntry, nC, nR );
            }
        }
    }

    //  Es hat sich was getan...

    if (HasListeners())
    {
        Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
        pDoc->TrackFormulas();      // muss sofort passieren
        pDoc->StartTrackTimer();

        //  StartTrackTimer ruft asynchron TrackFormulas, Broadcast(FID_DATACHANGED),
        //  ResetChanged, SetModified und Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
        //  TrackFormulas zusaetzlich nochmal sofort, damit nicht z.B. durch IdleCalc
        //  eine Formel berechnet wird, die noch im FormulaTrack steht (#61676#)

        //  notify Uno objects (for XRefreshListener)
        //  must be after TrackFormulas
        //! do this asynchronously?
        ScLinkRefreshedHint aHint;
        aHint.SetDdeLink( aAppl, aTopic, aItem, nMode );
        pDoc->BroadcastUno( aHint );
    }
}

void ScDdeLink::NewData(SCSIZE nCols, SCSIZE nRows)
{
    pResult = new ScMatrix( nCols, nRows );
}

void ScDdeLink::ResetValue()
{
    pResult.Clear();

    //  Es hat sich was getan...
    //  Tracking, FID_DATACHANGED etc. passiert von aussen

    if (HasListeners())
        Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
}

void __EXPORT ScDdeLink::ListenersGone()
{
    BOOL bWas = bIsInUpdate;
    bIsInUpdate = TRUE;             // Remove() kann Reschedule ausloesen??!?

    ScDocument* pStackDoc = pDoc;   // member pDoc can't be used after removing the link

    SvxLinkManager* pLinkMgr = pDoc->GetLinkManager();
    pLinkMgr->Remove( this);        // deletes this

    if ( !pLinkMgr->GetLinks().Count() )            // letzten geloescht ?
    {
        SfxBindings* pBindings = pStackDoc->GetViewBindings();      // don't use member pDoc!
        if (pBindings)
            pBindings->Invalidate( SID_LINKS );
    }

    bIsInUpdate = bWas;
}

void ScDdeLink::TryUpdate()
{
    if (bIsInUpdate)
        bNeedUpdate = TRUE;         // kann jetzt nicht ausgefuehrt werden
    else
    {
        bIsInUpdate = TRUE;
        //Application::Reschedule();    //! OS/2-Simulation
        pDoc->IncInDdeLinkUpdate();
        Update();
        pDoc->DecInDdeLinkUpdate();
        bIsInUpdate = FALSE;
        bNeedUpdate = FALSE;
    }
}

<|endoftext|>