159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Use of this source code is governed by a BSD-style license that can be
359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// found in the LICENSE file.
459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#ifndef SANDBOX_SRC_CROSSCALL_PARAMS_H__
659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#define SANDBOX_SRC_CROSSCALL_PARAMS_H__
759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#include <windows.h>
959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#include <lmaccess.h>
10cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <stddef.h>
11cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <stdint.h>
1259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
1359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#include <memory>
1459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
15cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "base/macros.h"
1659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#include "sandbox/win/src/internal_types.h"
1759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#include "sandbox/win/src/sandbox_types.h"
1859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
19cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko// Increases |value| until there is no need for padding given an int64_t
2059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// alignment. Returns the increased value.
21cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkoinline uint32_t Align(uint32_t value) {
22cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t alignment = sizeof(int64_t);
2359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  return ((value + alignment - 1) / alignment) * alignment;
2459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat}
2559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
2659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// This header is part of CrossCall: the sandbox inter-process communication.
2759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// This header defines the basic types used both in the client IPC and in the
2859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// server IPC code. CrossCallParams and ActualCallParams model the input
2959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// parameters of an IPC call and CrossCallReturn models the output params and
3059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// the return value.
3159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
32cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko// An IPC call is defined by its 'tag' which is a (uint32_t) unique identifier
3359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// that is used to route the IPC call to the proper server. Every tag implies
3459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// a complete call signature including the order and type of each parameter.
3559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
3659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Like most IPC systems. CrossCall is designed to take as inputs 'simple'
3759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// types such as integers and strings. Classes, generic arrays or pointers to
3859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// them are not supported.
3959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
4059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Another limitation of CrossCall is that the return value and output
41cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko// parameters can only be uint32_t integers. Returning complex structures or
4259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// strings is not supported.
4359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
4459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratnamespace sandbox {
4559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
4659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// max number of extended return parameters. See CrossCallReturn
4759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratconst size_t kExtendedReturnCount = 8;
4859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
4959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Union of multiple types to be used as extended results
5059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// in the CrossCallReturn.
5159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratunion MultiType {
52cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t unsigned_int;
5359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  void* pointer;
5459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  HANDLE handle;
5559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  ULONG_PTR ulong_ptr;
5659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat};
5759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
5859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Maximum number of IPC parameters currently supported.
5959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// To increase this value, we have to:
6059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//  - Add another Callback typedef to Dispatcher.
6159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//  - Add another case to the switch on SharedMemIPCServer::InvokeCallback.
6259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//  - Add another case to the switch in GetActualAndMaxBufferSize
6359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratconst int kMaxIpcParams = 9;
6459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
6559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Contains the information about a parameter in the ipc buffer.
6659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratstruct ParamInfo {
6759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  ArgType type_;
68cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t offset_;
69cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t size_;
7059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat};
7159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
7259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Models the return value and the return parameters of an IPC call
7359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// currently limited to one status code and eight generic return values
7459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// which cannot be pointers to other data. For x64 ports this structure
7559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// might have to use other integer types.
7659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratstruct CrossCallReturn {
7759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // the IPC tag. It should match the original IPC tag.
78cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t tag;
7959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // The result of the IPC operation itself.
8059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  ResultCode call_outcome;
8159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // the result of the IPC call as executed in the server. The interpretation
8259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // of this value depends on the specific service.
8359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  union {
8459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    NTSTATUS nt_status;
8559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    DWORD    win32_result;
8659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  };
8759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Number of extended return values.
88cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t extended_count;
8959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // for calls that should return a windows handle. It is found here.
9059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  HANDLE handle;
9159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // The array of extended values.
9259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  MultiType extended[kExtendedReturnCount];
9359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat};
9459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
9559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// CrossCallParams base class that models the input params all packed in a
9659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// single compact memory blob. The representation can vary but in general a
9759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// given child of this class is meant to represent all input parameters
9859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// necessary to make a IPC call.
9959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
10059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// This class cannot have virtual members because its assumed the IPC
10159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// parameters start from the 'this' pointer to the end, which is defined by
10259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// one of the subclasses
10359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
10459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Objects of this class cannot be constructed directly. Only derived
10559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// classes have the proper knowledge to construct it.
10659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratclass CrossCallParams {
10759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat public:
10859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Returns the tag (ipc unique id) associated with this IPC.
109cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t GetTag() const { return tag_; }
11059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
11159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Returns the beggining of the buffer where the IPC params can be stored.
11259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // prior to an IPC call
11359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  const void* GetBuffer() const {
11459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    return this;
11559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
11659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
11759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Returns how many parameter this IPC call should have.
118cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t GetParamsCount() const { return params_count_; }
11959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
12059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Returns a pointer to the CrossCallReturn structure.
12159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  CrossCallReturn* GetCallReturn() {
12259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    return &call_return;
12359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
12459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
12559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Returns TRUE if this call contains InOut parameters.
126cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  bool IsInOut() const { return (1 == is_in_out_); }
12759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
12859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Tells the CrossCall object if it contains InOut parameters.
12959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  void SetIsInOut(bool value) {
13059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    if (value)
13159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      is_in_out_ = 1;
13259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    else
13359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      is_in_out_ = 0;
13459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
13559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
13659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat protected:
13759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // constructs the IPC call params. Called only from the derived classes
138cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  CrossCallParams(uint32_t tag, uint32_t params_count)
139cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko      : tag_(tag), is_in_out_(0), params_count_(params_count) {}
14059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
14159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat private:
142cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t tag_;
143cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t is_in_out_;
14459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  CrossCallReturn call_return;
145cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  const uint32_t params_count_;
14659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  DISALLOW_COPY_AND_ASSIGN(CrossCallParams);
14759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat};
14859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
14959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// ActualCallParams models an specific IPC call parameters with respect to the
15059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// storage allocation that the packed parameters should need.
15159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// NUMBER_PARAMS: the number of parameters, valid from 1 to N
15259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// BLOCK_SIZE: the total storage that the NUMBER_PARAMS parameters can take,
15359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// typically the block size is defined by the channel size of the underlying
15459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// ipc mechanism.
15559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// In practice this class is used to levergage C++ capacity to properly
15659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// calculate sizes and displacements given the possibility of the packed params
15759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// blob to be complex.
15859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
15959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// As is, this class assumes that the layout of the blob is as follows. Assume
16059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// that NUMBER_PARAMS = 2 and a 32-bit build:
16159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
16259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ tag                4 bytes]
16359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ IsOnOut            4 bytes]
16459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ call return       52 bytes]
16559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ params count       4 bytes]
16659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 0 type   4 bytes]
16759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 0 offset 4 bytes] ---delta to ---\
16859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 0 size   4 bytes]                |
16959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 1 type   4 bytes]                |
17059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 1 offset 4 bytes] ---------------|--\
17159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 1 size   4 bytes]                |  |
17259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 2 type   4 bytes]                |  |
17359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 2 offset 4 bytes] ----------------------\
17459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// [ parameter 2 size   4 bytes]                |  |   |
17559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// |---------------------------|                |  |   |
17659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// | value 0     (x bytes)     | <--------------/  |   |
17759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// | value 1     (y bytes)     | <-----------------/   |
17859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// |                           |                       |
17959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// | end of buffer             | <---------------------/
18059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// |---------------------------|
18159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
18259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// Note that the actual number of params is NUMBER_PARAMS + 1
18359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// so that the size of each actual param can be computed from the difference
18459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// between one parameter and the next down. The offset of the last param
18559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat// points to the end of the buffer and the type and size are undefined.
18659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat//
18759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erattemplate <size_t NUMBER_PARAMS, size_t BLOCK_SIZE>
18859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratclass ActualCallParams : public CrossCallParams {
18959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat public:
19059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // constructor. Pass the ipc unique tag as input
191cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  explicit ActualCallParams(uint32_t tag)
19259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      : CrossCallParams(tag, NUMBER_PARAMS) {
19359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    param_info_[0].offset_ =
194cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko        static_cast<uint32_t>(parameters_ - reinterpret_cast<char*>(this));
19559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
19659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
19759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Testing-only constructor. Allows setting the |number_params| to a
19859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // wrong value.
199cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  ActualCallParams(uint32_t tag, uint32_t number_params)
20059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      : CrossCallParams(tag, number_params) {
20159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    param_info_[0].offset_ =
202cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko        static_cast<uint32_t>(parameters_ - reinterpret_cast<char*>(this));
20359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
20459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
20559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Testing-only method. Allows setting the apparent size to a wrong value.
20659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // returns the previous size.
207cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t OverrideSize(uint32_t new_size) {
208cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko    uint32_t previous_size = param_info_[NUMBER_PARAMS].offset_;
20959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    param_info_[NUMBER_PARAMS].offset_ = new_size;
21059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    return previous_size;
21159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
21259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
21359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Copies each paramter into the internal buffer. For each you must supply:
21459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // index: 0 for the first param, 1 for the next an so on
215cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  bool CopyParamIn(uint32_t index,
216cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko                   const void* parameter_address,
217cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko                   uint32_t size,
218cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko                   bool is_in_out,
219cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko                   ArgType type) {
22059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    if (index >= NUMBER_PARAMS) {
22159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      return false;
22259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    }
22359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
224cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko    if (UINT32_MAX == size) {
22559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      // Memory error while getting the size.
22659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      return false;
22759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    }
22859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
22959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    if (size && !parameter_address) {
23059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      return false;
23159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    }
23259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
23359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    if ((size > sizeof(*this)) ||
23459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat        (param_info_[index].offset_ > (sizeof(*this) - size))) {
23559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      // It does not fit, abort copy.
23659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      return false;
23759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    }
23859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
23959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    char* dest = reinterpret_cast<char*>(this) +  param_info_[index].offset_;
24059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
24159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    // We might be touching user memory, this has to be done from inside a try
24259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    // except.
24359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    __try {
24459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      memcpy(dest, parameter_address, size);
24559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    }
24659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    __except(EXCEPTION_EXECUTE_HANDLER) {
24759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      return false;
24859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    }
24959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
25059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    // Set the flag to tell the broker to update the buffer once the call is
25159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    // made.
25259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    if (is_in_out)
25359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat      SetIsInOut(true);
25459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
25559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    param_info_[index + 1].offset_ = Align(param_info_[index].offset_ +
25659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat                                                size);
25759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    param_info_[index].size_ = size;
25859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    param_info_[index].type_ = type;
25959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    return true;
26059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
26159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
26259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Returns a pointer to a parameter in the memory section.
26359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  void* GetParamPtr(size_t index) {
26459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat    return reinterpret_cast<char*>(this) + param_info_[index].offset_;
26559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  }
26659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
26759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // Returns the total size of the buffer. Only valid once all the paramters
26859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  // have been copied in with CopyParamIn.
269cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko  uint32_t GetSize() const { return param_info_[NUMBER_PARAMS].offset_; }
27059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
27159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat protected:
27259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  ActualCallParams() : CrossCallParams(0, NUMBER_PARAMS) { }
27359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
27459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat private:
27559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  ParamInfo param_info_[NUMBER_PARAMS + 1];
27659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  char parameters_[BLOCK_SIZE - sizeof(CrossCallParams)
27759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat                   - sizeof(ParamInfo) * (NUMBER_PARAMS + 1)];
27859c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat  DISALLOW_COPY_AND_ASSIGN(ActualCallParams);
27959c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat};
28059c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
28159c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratstatic_assert(sizeof(ActualCallParams<1, 1024>) == 1024, "bad size buffer");
28259c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratstatic_assert(sizeof(ActualCallParams<2, 1024>) == 1024, "bad size buffer");
28359c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Eratstatic_assert(sizeof(ActualCallParams<3, 1024>) == 1024, "bad size buffer");
28459c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
28559c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat}  // namespace sandbox
28659c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat
28759c5f4b0fb104e8e4806e4934a3d5d112ad695abDaniel Erat#endif  // SANDBOX_SRC_CROSSCALL_PARAMS_H__
288