<commit_before>//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to the MSP430 assembly language.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "MSP430.h"
#include "MSP430InstrInfo.h"
#include "MSP430InstPrinter.h"
#include "MSP430MCAsmInfo.h"
#include "MSP430MCInstLower.h"
#include "MSP430TargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;

STATISTIC(EmittedInsts, "Number of machine instrs printed");

static cl::opt<bool>
EnableMCInst("enable-msp430-mcinst-printer", cl::Hidden,
             cl::desc("enable experimental mcinst gunk in the msp430 backend"));

namespace {
  class MSP430AsmPrinter : public AsmPrinter {
  public:
    MSP430AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
                     const MCAsmInfo *MAI, bool V)
      : AsmPrinter(O, TM, MAI, V) {}

    virtual const char *getPassName() const {
      return "MSP430 Assembly Printer";
    }

    void printMCInst(const MCInst *MI) {
      MSP430InstPrinter(O, *MAI).printInstruction(MI);
    }
    void printOperand(const MachineInstr *MI, int OpNum,
                      const char* Modifier = 0);
    void printPCRelImmOperand(const MachineInstr *MI, int OpNum) {
      printOperand(MI, OpNum);
    }
    void printSrcMemOperand(const MachineInstr *MI, int OpNum,
                            const char* Modifier = 0);
    void printCCOperand(const MachineInstr *MI, int OpNum);
    void printMachineInstruction(const MachineInstr * MI);
    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                         unsigned AsmVariant,
                         const char *ExtraCode);
    bool PrintAsmMemoryOperand(const MachineInstr *MI,
                               unsigned OpNo, unsigned AsmVariant,
                               const char *ExtraCode);
    void printInstructionThroughMCStreamer(const MachineInstr *MI);

    bool runOnMachineFunction(MachineFunction &F);

    void getAnalysisUsage(AnalysisUsage &AU) const {
      AsmPrinter::getAnalysisUsage(AU);
      AU.setPreservesAll();
    }
  };
} // end of anonymous namespace

bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);
  O << "\n\n";

  EmitFunctionHeader();

  // Print out code for the function.
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    // Print a label for the basic block.
    EmitBasicBlockStart(I);

    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
         II != E; ++II)
      // Print the assembly for the instruction.
      printMachineInstruction(II);
  }

  if (MAI->hasDotTypeDotSizeDirective())
    O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';

  // Print out constants referenced by the function
  EmitConstantPool(MF.getConstantPool());
  EmitJumpTableInfo(MF);

  // We didn't modify anything
  return false;
}

void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
  ++EmittedInsts;

  processDebugLoc(MI, true);

  printInstructionThroughMCStreamer(MI);

  if (VerboseAsm)
    EmitComments(*MI);
  O << '\n';

  processDebugLoc(MI, false);
}

void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
                                    const char* Modifier) {
  const MachineOperand &MO = MI->getOperand(OpNum);
  switch (MO.getType()) {
  case MachineOperand::MO_Register:
    O << MSP430InstPrinter::getRegisterName(MO.getReg());
    return;
  case MachineOperand::MO_Immediate:
    if (!Modifier || strcmp(Modifier, "nohash"))
      O << '#';
    O << MO.getImm();
    return;
  case MachineOperand::MO_MachineBasicBlock:
    O << *MO.getMBB()->getSymbol(OutContext);
    return;
  case MachineOperand::MO_GlobalAddress: {
    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
    uint64_t Offset = MO.getOffset();

    O << (isMemOp ? '&' : '#');
    if (Offset)
      O << '(' << Offset << '+';

    O << *GetGlobalValueSymbol(MO.getGlobal());

    if (Offset)
      O << ')';

    return;
  }
  case MachineOperand::MO_ExternalSymbol: {
    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
    O << (isMemOp ? '&' : '#');
    O << MAI->getGlobalPrefix() << MO.getSymbolName();
    return;
  }
  default:
    llvm_unreachable("Not implemented yet!");
  }
}

void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
                                          const char* Modifier) {
  const MachineOperand &Base = MI->getOperand(OpNum);
  const MachineOperand &Disp = MI->getOperand(OpNum+1);

  // Print displacement first
  if (!Disp.isImm()) {
    printOperand(MI, OpNum+1, "mem");
  } else {
    if (!Base.getReg())
      O << '&';

    printOperand(MI, OpNum+1, "nohash");
  }

  // Print register base field
  if (Base.getReg()) {
    O << '(';
    printOperand(MI, OpNum);
    O << ')';
  }
}

void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
  unsigned CC = MI->getOperand(OpNum).getImm();

  switch (CC) {
  default:
   llvm_unreachable("Unsupported CC code");
   break;
  case MSP430CC::COND_E:
   O << "eq";
   break;
  case MSP430CC::COND_NE:
   O << "ne";
   break;
  case MSP430CC::COND_HS:
   O << "hs";
   break;
  case MSP430CC::COND_LO:
   O << "lo";
   break;
  case MSP430CC::COND_GE:
   O << "ge";
   break;
  case MSP430CC::COND_L:
   O << 'l';
   break;
  }
}

/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                       unsigned AsmVariant,
                                       const char *ExtraCode) {
  // Does this asm operand have a single letter operand modifier?
  if (ExtraCode && ExtraCode[0])
    return true; // Unknown modifier.

  printOperand(MI, OpNo);
  return false;
}

bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
                                             unsigned OpNo, unsigned AsmVariant,
                                             const char *ExtraCode) {
  if (ExtraCode && ExtraCode[0]) {
    return true; // Unknown modifier.
  }
  printSrcMemOperand(MI, OpNo);
  return false;
}

//===----------------------------------------------------------------------===//
void MSP430AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI){

  MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this);

  switch (MI->getOpcode()) {
  case TargetInstrInfo::DBG_LABEL:
  case TargetInstrInfo::EH_LABEL:
  case TargetInstrInfo::GC_LABEL:
    printLabel(MI);
    return;
  case TargetInstrInfo::KILL:
    printKill(MI);
    return;
  case TargetInstrInfo::INLINEASM:
    printInlineAsm(MI);
    return;
  case TargetInstrInfo::IMPLICIT_DEF:
    printImplicitDef(MI);
    return;
  default: break;
  }

  MCInst TmpInst;
  MCInstLowering.Lower(MI, TmpInst);

  printMCInst(&TmpInst);
}

static MCInstPrinter *createMSP430MCInstPrinter(const Target &T,
                                                unsigned SyntaxVariant,
                                                const MCAsmInfo &MAI,
                                                raw_ostream &O) {
  if (SyntaxVariant == 0)
    return new MSP430InstPrinter(O, MAI);
  return 0;
}

// Force static initialization.
extern "C" void LLVMInitializeMSP430AsmPrinter() {
  RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
  TargetRegistry::RegisterMCInstPrinter(TheMSP430Target,
                                        createMSP430MCInstPrinter);
}
<commit_msg>don't emit constant pools twice.<commit_after>//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to the MSP430 assembly language.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "MSP430.h"
#include "MSP430InstrInfo.h"
#include "MSP430InstPrinter.h"
#include "MSP430MCAsmInfo.h"
#include "MSP430MCInstLower.h"
#include "MSP430TargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;

STATISTIC(EmittedInsts, "Number of machine instrs printed");

static cl::opt<bool>
EnableMCInst("enable-msp430-mcinst-printer", cl::Hidden,
             cl::desc("enable experimental mcinst gunk in the msp430 backend"));

namespace {
  class MSP430AsmPrinter : public AsmPrinter {
  public:
    MSP430AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
                     const MCAsmInfo *MAI, bool V)
      : AsmPrinter(O, TM, MAI, V) {}

    virtual const char *getPassName() const {
      return "MSP430 Assembly Printer";
    }

    void printMCInst(const MCInst *MI) {
      MSP430InstPrinter(O, *MAI).printInstruction(MI);
    }
    void printOperand(const MachineInstr *MI, int OpNum,
                      const char* Modifier = 0);
    void printPCRelImmOperand(const MachineInstr *MI, int OpNum) {
      printOperand(MI, OpNum);
    }
    void printSrcMemOperand(const MachineInstr *MI, int OpNum,
                            const char* Modifier = 0);
    void printCCOperand(const MachineInstr *MI, int OpNum);
    void printMachineInstruction(const MachineInstr * MI);
    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                         unsigned AsmVariant,
                         const char *ExtraCode);
    bool PrintAsmMemoryOperand(const MachineInstr *MI,
                               unsigned OpNo, unsigned AsmVariant,
                               const char *ExtraCode);
    void printInstructionThroughMCStreamer(const MachineInstr *MI);

    bool runOnMachineFunction(MachineFunction &F);

    void getAnalysisUsage(AnalysisUsage &AU) const {
      AsmPrinter::getAnalysisUsage(AU);
      AU.setPreservesAll();
    }
  };
} // end of anonymous namespace

bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);
  O << "\n\n";

  EmitFunctionHeader();

  // Print out code for the function.
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    // Print a label for the basic block.
    EmitBasicBlockStart(I);

    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
         II != E; ++II)
      // Print the assembly for the instruction.
      printMachineInstruction(II);
  }

  if (MAI->hasDotTypeDotSizeDirective())
    O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';

  // Print out constants referenced by the function
  EmitJumpTableInfo(MF);

  // We didn't modify anything
  return false;
}

void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
  ++EmittedInsts;

  processDebugLoc(MI, true);

  printInstructionThroughMCStreamer(MI);

  if (VerboseAsm)
    EmitComments(*MI);
  O << '\n';

  processDebugLoc(MI, false);
}

void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
                                    const char* Modifier) {
  const MachineOperand &MO = MI->getOperand(OpNum);
  switch (MO.getType()) {
  case MachineOperand::MO_Register:
    O << MSP430InstPrinter::getRegisterName(MO.getReg());
    return;
  case MachineOperand::MO_Immediate:
    if (!Modifier || strcmp(Modifier, "nohash"))
      O << '#';
    O << MO.getImm();
    return;
  case MachineOperand::MO_MachineBasicBlock:
    O << *MO.getMBB()->getSymbol(OutContext);
    return;
  case MachineOperand::MO_GlobalAddress: {
    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
    uint64_t Offset = MO.getOffset();

    O << (isMemOp ? '&' : '#');
    if (Offset)
      O << '(' << Offset << '+';

    O << *GetGlobalValueSymbol(MO.getGlobal());

    if (Offset)
      O << ')';

    return;
  }
  case MachineOperand::MO_ExternalSymbol: {
    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
    O << (isMemOp ? '&' : '#');
    O << MAI->getGlobalPrefix() << MO.getSymbolName();
    return;
  }
  default:
    llvm_unreachable("Not implemented yet!");
  }
}

void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
                                          const char* Modifier) {
  const MachineOperand &Base = MI->getOperand(OpNum);
  const MachineOperand &Disp = MI->getOperand(OpNum+1);

  // Print displacement first
  if (!Disp.isImm()) {
    printOperand(MI, OpNum+1, "mem");
  } else {
    if (!Base.getReg())
      O << '&';

    printOperand(MI, OpNum+1, "nohash");
  }

  // Print register base field
  if (Base.getReg()) {
    O << '(';
    printOperand(MI, OpNum);
    O << ')';
  }
}

void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
  unsigned CC = MI->getOperand(OpNum).getImm();

  switch (CC) {
  default:
   llvm_unreachable("Unsupported CC code");
   break;
  case MSP430CC::COND_E:
   O << "eq";
   break;
  case MSP430CC::COND_NE:
   O << "ne";
   break;
  case MSP430CC::COND_HS:
   O << "hs";
   break;
  case MSP430CC::COND_LO:
   O << "lo";
   break;
  case MSP430CC::COND_GE:
   O << "ge";
   break;
  case MSP430CC::COND_L:
   O << 'l';
   break;
  }
}

/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                       unsigned AsmVariant,
                                       const char *ExtraCode) {
  // Does this asm operand have a single letter operand modifier?
  if (ExtraCode && ExtraCode[0])
    return true; // Unknown modifier.

  printOperand(MI, OpNo);
  return false;
}

bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
                                             unsigned OpNo, unsigned AsmVariant,
                                             const char *ExtraCode) {
  if (ExtraCode && ExtraCode[0]) {
    return true; // Unknown modifier.
  }
  printSrcMemOperand(MI, OpNo);
  return false;
}

//===----------------------------------------------------------------------===//
void MSP430AsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI){

  MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this);

  switch (MI->getOpcode()) {
  case TargetInstrInfo::DBG_LABEL:
  case TargetInstrInfo::EH_LABEL:
  case TargetInstrInfo::GC_LABEL:
    printLabel(MI);
    return;
  case TargetInstrInfo::KILL:
    printKill(MI);
    return;
  case TargetInstrInfo::INLINEASM:
    printInlineAsm(MI);
    return;
  case TargetInstrInfo::IMPLICIT_DEF:
    printImplicitDef(MI);
    return;
  default: break;
  }

  MCInst TmpInst;
  MCInstLowering.Lower(MI, TmpInst);

  printMCInst(&TmpInst);
}

static MCInstPrinter *createMSP430MCInstPrinter(const Target &T,
                                                unsigned SyntaxVariant,
                                                const MCAsmInfo &MAI,
                                                raw_ostream &O) {
  if (SyntaxVariant == 0)
    return new MSP430InstPrinter(O, MAI);
  return 0;
}

// Force static initialization.
extern "C" void LLVMInitializeMSP430AsmPrinter() {
  RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
  TargetRegistry::RegisterMCInstPrinter(TheMSP430Target,
                                        createMSP430MCInstPrinter);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

#pragma once
#ifndef _____COMMS__INCLUDE__OPFLEX__RPC__SEND_HANDLER_HPP
#define _____COMMS__INCLUDE__OPFLEX__RPC__SEND_HANDLER_HPP

#include <rapidjson/rapidjson.h>

#include <deque>
#include <opflex/logging/internal/logging.hpp>

namespace yajr {
    namespace internal {

bool __checkInvariants(void const *);
bool isLegitPunct(int c);

template <typename Encoding = rapidjson::UTF8<> >
struct GenericStringQueue {

    typedef typename Encoding::Ch Ch;

    void Put(Ch c) {
        deque_.push_back(c);
        assert(::yajr::internal::isLegitPunct(c));
#ifdef PERFORM_CRAZY_BYTE_BY_BYTE_INVARIANT_CHECK
        assert(__checkInvariants(cP_));
#endif
        if(deque_.back()!=c){
            LOG(ERROR)
                << "inserted char already changed: \""
                << c
                << "\"->\""
                << deque_.back()
                << "\""
            ;
        }
    }

    void Flush() {}

    void Clear() {
        deque_.clear();
    }

    void ShrinkToFit() {
        deque_.shrink_to_fit();
    }

    size_t GetSize() const {
        return deque_.size();
    }

    std::deque<Ch> deque_;
#ifndef NDEBUG
    void const * cP_;
#endif
};

//! String buffer with UTF8 encoding
typedef GenericStringQueue<rapidjson::UTF8<> > StringQueue;

} /* yajr::internal namespace */
} /* yajr namespace */

#endif /* _____COMMS__INCLUDE__OPFLEX__RPC__SEND_HANDLER_HPP */

<commit_msg>avoid logging from send handler<commit_after>/*
 * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

#pragma once
#ifndef _____COMMS__INCLUDE__OPFLEX__RPC__SEND_HANDLER_HPP
#define _____COMMS__INCLUDE__OPFLEX__RPC__SEND_HANDLER_HPP

#include <rapidjson/rapidjson.h>

#include <deque>

#ifdef PERFORM_CRAZY_BYTE_BY_BYTE_INVARIANT_CHECK
#include <opflex/logging/internal/logging.hpp>
#endif
namespace yajr {
    namespace internal {

bool __checkInvariants(void const *);
bool isLegitPunct(int c);

template <typename Encoding = rapidjson::UTF8<> >
struct GenericStringQueue {

    typedef typename Encoding::Ch Ch;

    void Put(Ch c) {
        deque_.push_back(c);
        assert(::yajr::internal::isLegitPunct(c));
#ifdef PERFORM_CRAZY_BYTE_BY_BYTE_INVARIANT_CHECK
        assert(__checkInvariants(cP_));
        if(deque_.back()!=c){
            LOG(ERROR)
                << "inserted char already changed: \""
                << c
                << "\"->\""
                << deque_.back()
                << "\""
            ;
        }
#endif
    }

    void Flush() {}

    void Clear() {
        deque_.clear();
    }

    void ShrinkToFit() {
        deque_.shrink_to_fit();
    }

    size_t GetSize() const {
        return deque_.size();
    }

    std::deque<Ch> deque_;
#ifndef NDEBUG
    void const * cP_;
#endif
};

//! String buffer with UTF8 encoding
typedef GenericStringQueue<rapidjson::UTF8<> > StringQueue;

} /* yajr::internal namespace */
} /* yajr namespace */

#endif /* _____COMMS__INCLUDE__OPFLEX__RPC__SEND_HANDLER_HPP */

<|endoftext|>


<commit_before>#include "browser/inspectable_web_contents.h"

#include "browser/inspectable_web_contents_impl.h"

namespace brightray {

InspectableWebContents* InspectableWebContents::Create(const content::WebContents::CreateParams& create_params) {
  return Create(content::WebContents::Create(create_params));
}

InspectableWebContents* InspectableWebContents::Create(content::WebContents* web_contents) {
  return new InspectableWebContentsImpl(web_contents);
}

}
<commit_msg>Fix flashing in WebContents we create<commit_after>#include "browser/inspectable_web_contents.h"

#include "browser/inspectable_web_contents_impl.h"

#include "content/public/browser/web_contents_view.h"

namespace brightray {

InspectableWebContents* InspectableWebContents::Create(const content::WebContents::CreateParams& create_params) {
  auto contents = content::WebContents::Create(create_params);
#if defined(OS_MACOSX)
  // Work around http://crbug.com/279472.
  contents->GetView()->SetAllowOverlappingViews(true);
#endif

  return Create(contents);
}

InspectableWebContents* InspectableWebContents::Create(content::WebContents* web_contents) {
  return new InspectableWebContentsImpl(web_contents);
}

}
<|endoftext|>


<commit_before><commit_msg>Minor edit<commit_after><|endoftext|>


<commit_before><commit_msg>Tidy<commit_after><|endoftext|>


<commit_before>#pragma once

#include <iostream>

#include "binary.hxx"
#include "bitnode.hxx"

namespace despairagus {
	namespace bitwisetrieNS {
		using std::cout;
		using std::ostream;

		using namespace bitnodeNS;
		using namespace binaryNS;

		template <typename A, typename B>
		class bitwisetrie final {
			template<typename C>
			using conref = const C&;

			using bitA = std::bitset<sizeof(A) << 3>;
			using byte = unsigned char;
			using bit = bool;

			constexpr static const size_t limit{sizeof(A) << 3};

			static inline bitnode<B>* navigate(bitnode<B>* currNode, conref<A> data) {
				return bitwisetrie<A,B>::navigate(currNode, data, 0);
			}

			static inline bitnode<B>* navigate(bitnode<B>* currNode, conref<A> data, conref<size_t> idx) {
				binary<A> bitHolder{data};

				return bitwisetrie<A,B>::navigate(currNode, bitHolder, idx);
			}

			static bitnode<B>* navigate(bitnode<B>* currNode, conref<binary<A>> bits, conref<size_t> idx) {
				if (idx < limit) {
					if (bits.getBit(idx)) {
						if (currNode->getOne() == nullptr) {
							currNode->setOne(new bitnode<B>);
						}

						return bitwisetrie<A,B>::navigate(currNode->getOne(), bits, idx + 1);
					} else {
						if (currNode->getZero() == nullptr) {
							currNode->setZero(new bitnode<B>);
						}

						return bitwisetrie<A,B>::navigate(currNode->getZero(), bits, idx + 1);
					}
				}

				return currNode;
			}

		public:
			explicit bitwisetrie(void) : root{new bitnode<B>} {}

			template <typename... C>
			explicit bitwisetrie(C...) = delete;

			inline explicit operator bool (void) {
				return this->root->isBarren();
			}

			template <typename C>
			explicit operator C (void) = delete;

			inline bool insertOnEmpty(conref<A> a, conref<B> b) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				if (leafNode->isEmpty()) {
					leafNode->setData(b);

					return true;
				}

				return false;
			}

			inline bool insertOnNotEmpty(conref<A> a, conref<B> b) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				if (leafNode->isNotEmpty()) {
					leafNode->setData(b);

					return true;
				}

				return false;
			}

			inline void insert(conref<A> a, conref<B> b) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				leafNode->setData(a);
			}

			inline bool remove(conref<A> a) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				if (leafNode->isNotEmpty()) {
					leafNode->dump();

					return true;
				}

				return false;
			}

			inline bool contains(conref<A> a) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				return leafNode->isNotEmpty();
			}

			inline bool notContains(conref<A> a) noexcept {
				return !this->contains(a);
			}

		private:
			bitnode<B>* root;
		};
	}
}
<commit_msg>should be using isNotBarren<commit_after>#pragma once

#include <iostream>

#include "binary.hxx"
#include "bitnode.hxx"

namespace despairagus {
	namespace bitwisetrieNS {
		using std::cout;
		using std::ostream;

		using namespace bitnodeNS;
		using namespace binaryNS;

		template <typename A, typename B>
		class bitwisetrie final {
			template<typename C>
			using conref = const C&;

			using bitA = std::bitset<sizeof(A) << 3>;
			using byte = unsigned char;
			using bit = bool;

			constexpr static const size_t limit{sizeof(A) << 3};

			static inline bitnode<B>* navigate(bitnode<B>* currNode, conref<A> data) {
				return bitwisetrie<A,B>::navigate(currNode, data, 0);
			}

			static inline bitnode<B>* navigate(bitnode<B>* currNode, conref<A> data, conref<size_t> idx) {
				binary<A> bitHolder{data};

				return bitwisetrie<A,B>::navigate(currNode, bitHolder, idx);
			}

			static bitnode<B>* navigate(bitnode<B>* currNode, conref<binary<A>> bits, conref<size_t> idx) {
				if (idx < limit) {
					if (bits.getBit(idx)) {
						if (currNode->getOne() == nullptr) {
							currNode->setOne(new bitnode<B>);
						}

						return bitwisetrie<A,B>::navigate(currNode->getOne(), bits, idx + 1);
					} else {
						if (currNode->getZero() == nullptr) {
							currNode->setZero(new bitnode<B>);
						}

						return bitwisetrie<A,B>::navigate(currNode->getZero(), bits, idx + 1);
					}
				}

				return currNode;
			}

		public:
			explicit bitwisetrie(void) : root{new bitnode<B>} {}

			template <typename... C>
			explicit bitwisetrie(C...) = delete;

			inline explicit operator bool (void) {
				return this->root->isNotBarren();
			}

			template <typename C>
			explicit operator C (void) = delete;

			inline bool insertOnEmpty(conref<A> a, conref<B> b) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				if (leafNode->isEmpty()) {
					leafNode->setData(b);

					return true;
				}

				return false;
			}

			inline bool insertOnNotEmpty(conref<A> a, conref<B> b) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				if (leafNode->isNotEmpty()) {
					leafNode->setData(b);

					return true;
				}

				return false;
			}

			inline void insert(conref<A> a, conref<B> b) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				leafNode->setData(a);
			}

			inline bool remove(conref<A> a) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				if (leafNode->isNotEmpty()) {
					leafNode->dump();

					return true;
				}

				return false;
			}

			inline bool contains(conref<A> a) noexcept {
				bitnode<B>* leafNode = bitwisetrie<A,B>::navigate(root, a);

				return leafNode->isNotEmpty();
			}

			inline bool notContains(conref<A> a) noexcept {
				return !this->contains(a);
			}

		private:
			bitnode<B>* root;
		};
	}
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2011-2014 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include "listen.h"
#include "log.h"
#define CLASS_MODULE "listen"

#define dprintf(fmt, arg...) __dprintf(DBG_SERVE, fmt, ##arg)

socket_listen::socket_listen()
  : h_thread((pthread_t)NULL)
  , f_kill_thread(false)
  , sock_fd(-1)
  , port(0)
  , m_socket_listen_iface(NULL)
{
	dprintf("()");
}

socket_listen::~socket_listen()
{
	dprintf("()");

	close_socket();
}

socket_listen::socket_listen(const socket_listen&)
{
	dprintf("(copy)");
	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	sock_fd = -1;
	port = 0;
	m_socket_listen_iface = NULL;
}

socket_listen& socket_listen::operator= (const socket_listen& cSource)
{
	dprintf("(operator=)");

	if (this == &cSource)
		return *this;

	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	sock_fd = -1;
	port = 0;
	m_socket_listen_iface = NULL;

	return *this;
}

void socket_listen::close_socket()
{
	dprintf("()");

	if (sock_fd >= 0) {
		close(sock_fd);
		sock_fd = -1;
	}
	port = 0;
}

void socket_listen::stop()
{
	dprintf("()");

	stop_without_wait();

	while (-1 != sock_fd) {
		usleep(20*1000);
	}
	return;
}

int socket_listen::start(uint16_t port_requested)
{
	struct sockaddr_in tcp_sock;

	dprintf("()");

	memset(&tcp_sock, 0, sizeof(tcp_sock));

	f_kill_thread = false;

	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (sock_fd < 0) {
		perror("open socket failed");
		return sock_fd;
	}

	int reuse = 1;
	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
		perror("setting reuse failed");
		return -1;
	}

	tcp_sock.sin_family = AF_INET;
	tcp_sock.sin_port = htons(port_requested);
	tcp_sock.sin_addr.s_addr = INADDR_ANY;

	if (bind(sock_fd, (struct sockaddr*)&tcp_sock, sizeof(tcp_sock)) < 0) {
		perror("bind to local interface failed");
		return -1;
	}
	port = port_requested;

	int fl = fcntl(sock_fd, F_GETFL, 0);
	if (fcntl(sock_fd, F_SETFL, fl | O_NONBLOCK) < 0) {
		perror("set non-blocking failed");
		return -1;
	}
#define MAX_SOCKETS 4
	listen(sock_fd, MAX_SOCKETS);

	int ret = pthread_create(&h_thread, NULL, listen_thread, this);

	if (0 != ret)
		perror("pthread_create() failed");

	return ret;
}

int socket_listen::start_udp(uint16_t port_requested)
{
	struct sockaddr_in udp_sock;

	dprintf("()");

	memset(&udp_sock, 0, sizeof(udp_sock));

	f_kill_thread = false;

	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock_fd < 0) {
		perror("open socket failed");
		return sock_fd;
	}

	int reuse = 1;
	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
		perror("setting reuse failed");
		return -1;
	}

	udp_sock.sin_family = AF_INET;
	udp_sock.sin_port = htons(port_requested);
	udp_sock.sin_addr.s_addr = INADDR_ANY;

	if (bind(sock_fd, (struct sockaddr*)&udp_sock, sizeof(udp_sock)) < 0) {
		perror("bind to local interface failed");
		return -1;
	}

	int fl = fcntl(sock_fd, F_GETFL, 0);
	if (fcntl(sock_fd, F_SETFL, fl | O_NONBLOCK) < 0) {
		perror("set non-blocking failed");
		return -1;
	}

	int ret = pthread_create(&h_thread, NULL, udp_listen_thread, this);

	if (0 != ret)
		perror("pthread_create() failed");

	return ret;
}

void* socket_listen::listen_thread(void *p_this)
{
	return static_cast<socket_listen*>(p_this)->listen_thread();
}

void* socket_listen::listen_thread()
{
	struct sockaddr_in tcpsa;
	socklen_t salen = sizeof(tcpsa);

	dprintf("(%d)", sock_fd);

	while (!f_kill_thread) {
		int accepted_sock_fd = accept(sock_fd, (struct sockaddr*)&tcpsa, &salen);
		if (accepted_sock_fd >= 0) {
			if (m_socket_listen_iface) {
				m_socket_listen_iface->accept_socket(accepted_sock_fd);
			} else {
				dprintf("(accept_socket callback not defined!)");
				close(accepted_sock_fd);
			}
		}
		usleep(20*1000);
	}

	close_socket();
	pthread_exit(NULL);
}

void* socket_listen::udp_listen_thread(void *p_this)
{
	return static_cast<socket_listen*>(p_this)->udp_listen_thread();
}

void* socket_listen::udp_listen_thread()
{
	dprintf("(%d)", sock_fd);

	while (!f_kill_thread) {
		if (sock_fd != -1) {
			if (m_socket_listen_iface)
				m_socket_listen_iface->accept_socket(sock_fd);
			else
				dprintf("(accept_socket callback not defined!)");
		}
		usleep(20*1000);
	}

	close_socket();
	pthread_exit(NULL);
}
<commit_msg>listen: set accepted_sock_fd to -1 after close()<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2014 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include "listen.h"
#include "log.h"
#define CLASS_MODULE "listen"

#define dprintf(fmt, arg...) __dprintf(DBG_SERVE, fmt, ##arg)

socket_listen::socket_listen()
  : h_thread((pthread_t)NULL)
  , f_kill_thread(false)
  , sock_fd(-1)
  , port(0)
  , m_socket_listen_iface(NULL)
{
	dprintf("()");
}

socket_listen::~socket_listen()
{
	dprintf("()");

	close_socket();
}

socket_listen::socket_listen(const socket_listen&)
{
	dprintf("(copy)");
	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	sock_fd = -1;
	port = 0;
	m_socket_listen_iface = NULL;
}

socket_listen& socket_listen::operator= (const socket_listen& cSource)
{
	dprintf("(operator=)");

	if (this == &cSource)
		return *this;

	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	sock_fd = -1;
	port = 0;
	m_socket_listen_iface = NULL;

	return *this;
}

void socket_listen::close_socket()
{
	dprintf("()");

	if (sock_fd >= 0) {
		close(sock_fd);
		sock_fd = -1;
	}
	port = 0;
}

void socket_listen::stop()
{
	dprintf("()");

	stop_without_wait();

	while (-1 != sock_fd) {
		usleep(20*1000);
	}
	return;
}

int socket_listen::start(uint16_t port_requested)
{
	struct sockaddr_in tcp_sock;

	dprintf("()");

	memset(&tcp_sock, 0, sizeof(tcp_sock));

	f_kill_thread = false;

	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (sock_fd < 0) {
		perror("open socket failed");
		return sock_fd;
	}

	int reuse = 1;
	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
		perror("setting reuse failed");
		return -1;
	}

	tcp_sock.sin_family = AF_INET;
	tcp_sock.sin_port = htons(port_requested);
	tcp_sock.sin_addr.s_addr = INADDR_ANY;

	if (bind(sock_fd, (struct sockaddr*)&tcp_sock, sizeof(tcp_sock)) < 0) {
		perror("bind to local interface failed");
		return -1;
	}
	port = port_requested;

	int fl = fcntl(sock_fd, F_GETFL, 0);
	if (fcntl(sock_fd, F_SETFL, fl | O_NONBLOCK) < 0) {
		perror("set non-blocking failed");
		return -1;
	}
#define MAX_SOCKETS 4
	listen(sock_fd, MAX_SOCKETS);

	int ret = pthread_create(&h_thread, NULL, listen_thread, this);

	if (0 != ret)
		perror("pthread_create() failed");

	return ret;
}

int socket_listen::start_udp(uint16_t port_requested)
{
	struct sockaddr_in udp_sock;

	dprintf("()");

	memset(&udp_sock, 0, sizeof(udp_sock));

	f_kill_thread = false;

	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock_fd < 0) {
		perror("open socket failed");
		return sock_fd;
	}

	int reuse = 1;
	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
		perror("setting reuse failed");
		return -1;
	}

	udp_sock.sin_family = AF_INET;
	udp_sock.sin_port = htons(port_requested);
	udp_sock.sin_addr.s_addr = INADDR_ANY;

	if (bind(sock_fd, (struct sockaddr*)&udp_sock, sizeof(udp_sock)) < 0) {
		perror("bind to local interface failed");
		return -1;
	}

	int fl = fcntl(sock_fd, F_GETFL, 0);
	if (fcntl(sock_fd, F_SETFL, fl | O_NONBLOCK) < 0) {
		perror("set non-blocking failed");
		return -1;
	}

	int ret = pthread_create(&h_thread, NULL, udp_listen_thread, this);

	if (0 != ret)
		perror("pthread_create() failed");

	return ret;
}

void* socket_listen::listen_thread(void *p_this)
{
	return static_cast<socket_listen*>(p_this)->listen_thread();
}

void* socket_listen::listen_thread()
{
	struct sockaddr_in tcpsa;
	socklen_t salen = sizeof(tcpsa);

	dprintf("(%d)", sock_fd);

	while (!f_kill_thread) {
		int accepted_sock_fd = accept(sock_fd, (struct sockaddr*)&tcpsa, &salen);
		if (accepted_sock_fd >= 0) {
			if (m_socket_listen_iface) {
				m_socket_listen_iface->accept_socket(accepted_sock_fd);
			} else {
				dprintf("(accept_socket callback not defined!)");
				close(accepted_sock_fd);
				accepted_sock_fd = -1;
			}
		}
		usleep(20*1000);
	}

	close_socket();
	pthread_exit(NULL);
}

void* socket_listen::udp_listen_thread(void *p_this)
{
	return static_cast<socket_listen*>(p_this)->udp_listen_thread();
}

void* socket_listen::udp_listen_thread()
{
	dprintf("(%d)", sock_fd);

	while (!f_kill_thread) {
		if (sock_fd != -1) {
			if (m_socket_listen_iface)
				m_socket_listen_iface->accept_socket(sock_fd);
			else
				dprintf("(accept_socket callback not defined!)");
		}
		usleep(20*1000);
	}

	close_socket();
	pthread_exit(NULL);
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
**
** $QT_END_LICENSE$
**
**************************************************************************/

#include "adminauthorization.h"
#include <QSettings>
#include <QVariant>
#include <QDir>
#include <qt_windows.h>
using namespace QtAutoUpdater;

static QString qt_create_commandline(const QStringList &arguments);

struct DeCoInitializer
{
    DeCoInitializer()
        : neededCoInit(CoInitialize(NULL) == S_OK)
    {
    }
    ~DeCoInitializer()
    {
        if (neededCoInit)
            CoUninitialize();
    }
    bool neededCoInit;
};

bool AdminAuthorization::hasAdminRights()
{
    SID_IDENTIFIER_AUTHORITY authority = { SECURITY_NT_AUTHORITY };
    PSID adminGroup;
    // Initialize SID.
    if (!AllocateAndInitializeSid(&authority,
                                  2,
                                  SECURITY_BUILTIN_DOMAIN_RID,
                                  DOMAIN_ALIAS_RID_ADMINS,
                                  0, 0, 0, 0, 0, 0,
                                  &adminGroup))
        return false;

    BOOL isInAdminGroup = FALSE;
    if (!CheckTokenMembership(0, adminGroup, &isInAdminGroup))
        isInAdminGroup = FALSE;

    FreeSid(adminGroup);
    return isInAdminGroup;
}

bool AdminAuthorization::executeAsAdmin(const QString &program, const QStringList &arguments)
{
    DeCoInitializer _;

    // AdminAuthorization::execute uses UAC to ask for admin privileges. If the user is no
    // administrator yet and the computer's policies are set to not use UAC (which is the case
    // in some corporate networks), the call to execute() will simply succeed and not at all
    // launch the child process. To avoid this, we detect this situation here and return early.
	if (!this->hasAdminRights()) {
		QLatin1String key("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
        QSettings registry(key, QSettings::NativeFormat);
        const QVariant enableLUA = registry.value(QLatin1String("EnableLUA"));
        if ((enableLUA.type() == QVariant::Int) && (enableLUA.toInt() == 0))
            return false;
    }

    const QString file = QDir::toNativeSeparators(program);
	const QString args = qt_create_commandline(arguments);

	SHELLEXECUTEINFOW shellExecuteInfo = { 0 };
	shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
    shellExecuteInfo.lpVerb = L"runas";
	shellExecuteInfo.lpFile = (wchar_t *)file.utf16();
	shellExecuteInfo.lpParameters = (wchar_t *)args.utf16();
	shellExecuteInfo.nShow = SW_SHOW;

	if (ShellExecuteExW(&shellExecuteInfo))
        return true;
	else
		return false;
}

QString qt_create_commandline(const QStringList &arguments)
{
    QString args;
    for (int i = 0; i < arguments.size(); ++i) {
        QString tmp = arguments.at(i);
        // in the case of \" already being in the string the \ must also be escaped
        tmp.replace(QLatin1String("\\\""), QLatin1String("\\\\\""));
        // escape a single " because the arguments will be parsed
        tmp.replace(QLatin1Char('\"'), QLatin1String("\\\""));
        if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
            // The argument must not end with a \ since this would be interpreted
            // as escaping the quote -- rather put the \ behind the quote: e.g.
            // rather use "foo"\ than "foo\"
            QString endQuote(QLatin1Char('\"'));
            int i = tmp.length();
            while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) {
                --i;
                endQuote += QLatin1Char('\\');
            }
            args += QLatin1String(" \"") + tmp.left(i) + endQuote;
        } else {
            args += QLatin1Char(' ') + tmp;
        }
    }
    return args;
}
<commit_msg>fixed mingw warning windows<commit_after>/**************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
**
** $QT_END_LICENSE$
**
**************************************************************************/

#include "adminauthorization.h"
#include <QSettings>
#include <QVariant>
#include <QDir>
#include <qt_windows.h>
using namespace QtAutoUpdater;

static QString qt_create_commandline(const QStringList &arguments);

struct DeCoInitializer
{
    DeCoInitializer()
        : neededCoInit(CoInitialize(NULL) == S_OK)
    {
    }
    ~DeCoInitializer()
    {
        if (neededCoInit)
            CoUninitialize();
    }
    bool neededCoInit;
};

bool AdminAuthorization::hasAdminRights()
{
    SID_IDENTIFIER_AUTHORITY authority = { SECURITY_NT_AUTHORITY };
    PSID adminGroup;
    // Initialize SID.
    if (!AllocateAndInitializeSid(&authority,
                                  2,
                                  SECURITY_BUILTIN_DOMAIN_RID,
                                  DOMAIN_ALIAS_RID_ADMINS,
                                  0, 0, 0, 0, 0, 0,
                                  &adminGroup))
        return false;

    BOOL isInAdminGroup = FALSE;
    if (!CheckTokenMembership(0, adminGroup, &isInAdminGroup))
        isInAdminGroup = FALSE;

    FreeSid(adminGroup);
    return isInAdminGroup;
}

bool AdminAuthorization::executeAsAdmin(const QString &program, const QStringList &arguments)
{
    DeCoInitializer _;

    // AdminAuthorization::execute uses UAC to ask for admin privileges. If the user is no
    // administrator yet and the computer's policies are set to not use UAC (which is the case
    // in some corporate networks), the call to execute() will simply succeed and not at all
    // launch the child process. To avoid this, we detect this situation here and return early.
	if (!this->hasAdminRights()) {
		QLatin1String key("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
        QSettings registry(key, QSettings::NativeFormat);
        const QVariant enableLUA = registry.value(QLatin1String("EnableLUA"));
        if ((enableLUA.type() == QVariant::Int) && (enableLUA.toInt() == 0))
            return false;
    }

    const QString file = QDir::toNativeSeparators(program);
	const QString args = qt_create_commandline(arguments);

	SHELLEXECUTEINFOW shellExecuteInfo;
	ZeroMemory(&shellExecuteInfo, sizeof(SHELLEXECUTEINFOW));
	shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
    shellExecuteInfo.lpVerb = L"runas";
	shellExecuteInfo.lpFile = (wchar_t *)file.utf16();
	shellExecuteInfo.lpParameters = (wchar_t *)args.utf16();
	shellExecuteInfo.nShow = SW_SHOW;

	if (ShellExecuteExW(&shellExecuteInfo))
        return true;
	else
		return false;
}

QString qt_create_commandline(const QStringList &arguments)
{
    QString args;
    for (int i = 0; i < arguments.size(); ++i) {
        QString tmp = arguments.at(i);
        // in the case of \" already being in the string the \ must also be escaped
        tmp.replace(QLatin1String("\\\""), QLatin1String("\\\\\""));
        // escape a single " because the arguments will be parsed
        tmp.replace(QLatin1Char('\"'), QLatin1String("\\\""));
        if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
            // The argument must not end with a \ since this would be interpreted
            // as escaping the quote -- rather put the \ behind the quote: e.g.
            // rather use "foo"\ than "foo\"
            QString endQuote(QLatin1Char('\"'));
            int i = tmp.length();
            while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) {
                --i;
                endQuote += QLatin1Char('\\');
            }
            args += QLatin1String(" \"") + tmp.left(i) + endQuote;
        } else {
            args += QLatin1Char(' ') + tmp;
        }
    }
    return args;
}
<|endoftext|>


<commit_before>#include "tokentransactionview.h"

#include "walletmodel.h"
#include "platformstyle.h"
#include "tokentransactiontablemodel.h"
#include "tokentransactionrecord.h"
#include "tokenfilterproxy.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "tokenitemmodel.h"
#include "tokendescdialog.h"

#include <QComboBox>
#include <QDateTimeEdit>
#include <QDoubleValidator>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QPoint>
#include <QScrollBar>
#include <QTableView>
#include <QVBoxLayout>
#include <QRegularExpressionValidator>

#define paternTokenAmount "^[0-9]{1,59}\\.{1,1}[0-9]{0,18}"

TokenTransactionView::TokenTransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
    QWidget(parent),
    model(0),
    tokenProxyModel(0),
    tokenView(0),
    columnResizingFixer(0)
{
    // Build filter row
    setContentsMargins(0,0,0,0);

    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(0,0,0,0);

    if (platformStyle->getUseExtraSpacing()) {
        hlayout->setSpacing(5);
        hlayout->addSpacing(STATUS_COLUMN_WIDTH + 3);
    } else {
        hlayout->setSpacing(0);
        hlayout->addSpacing(STATUS_COLUMN_WIDTH);
    }

    dateWidget = new QComboBox(this);
    if (platformStyle->getUseExtraSpacing()) {
        dateWidget->setFixedWidth(DATE_COLUMN_WIDTH + 1);
    } else {
        dateWidget->setFixedWidth(DATE_COLUMN_WIDTH);
    }
    dateWidget->addItem(tr("All"), All);
    dateWidget->addItem(tr("Today"), Today);
    dateWidget->addItem(tr("This week"), ThisWeek);
    dateWidget->addItem(tr("This month"), ThisMonth);
    dateWidget->addItem(tr("Last month"), LastMonth);
    dateWidget->addItem(tr("This year"), ThisYear);
    dateWidget->addItem(tr("Range..."), Range);
    hlayout->addWidget(dateWidget);

    typeWidget = new QComboBox(this);
    if (platformStyle->getUseExtraSpacing()) {
        typeWidget->setFixedWidth(TYPE_COLUMN_WIDTH + 1);
    } else {
        typeWidget->setFixedWidth(TYPE_COLUMN_WIDTH);
    }

    typeWidget->addItem(tr("All"), TokenFilterProxy::ALL_TYPES);
    typeWidget->addItem(tr("Received with"), TokenFilterProxy::TYPE(TokenTransactionRecord::RecvWithAddress));
    typeWidget->addItem(tr("Sent to"), TokenFilterProxy::TYPE(TokenTransactionRecord::SendToAddress));
    typeWidget->addItem(tr("To yourself"), TokenFilterProxy::TYPE(TokenTransactionRecord::SendToSelf));
    hlayout->addWidget(typeWidget);

    addressWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    addressWidget->setPlaceholderText(tr("Enter address to search"));
#endif
    hlayout->addWidget(addressWidget);

    nameWidget = new QComboBox(this);
    if (platformStyle->getUseExtraSpacing()) {
        nameWidget->setFixedWidth(NAME_COLUMN_WIDTH + 1);
    } else {
        nameWidget->setFixedWidth(NAME_COLUMN_WIDTH);
    }
    nameWidget->addItem(tr("All"), "");

    hlayout->addWidget(nameWidget);

    amountWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    amountWidget->setPlaceholderText(tr("Min amount"));
#endif
    if (platformStyle->getUseExtraSpacing()) {
        amountWidget->setFixedWidth(AMOUNT_MINIMUM_COLUMN_WIDTH - 3);
    } else {
        amountWidget->setFixedWidth(AMOUNT_MINIMUM_COLUMN_WIDTH);
    }
    QRegularExpression regEx;
    regEx.setPattern(paternTokenAmount);
    QRegularExpressionValidator *validator = new QRegularExpressionValidator(amountWidget);
    validator->setRegularExpression(regEx);
    amountWidget->setValidator(validator);
    hlayout->addWidget(amountWidget);

    QVBoxLayout *vlayout = new QVBoxLayout(this);
    vlayout->setContentsMargins(0,0,0,0);
    vlayout->setSpacing(0);

    QTableView *view = new QTableView(this);
    vlayout->addLayout(hlayout);
    vlayout->addWidget(createDateRangeWidget());
    vlayout->addWidget(view);
    vlayout->setSpacing(0);
    int width = view->verticalScrollBar()->sizeHint().width();
    // Cover scroll bar width with spacing
    if (platformStyle->getUseExtraSpacing()) {
        hlayout->addSpacing(width+2);
    } else {
        hlayout->addSpacing(width);
    }
    // Always show scroll bar
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    view->setTabKeyNavigation(false);
    view->setContextMenuPolicy(Qt::CustomContextMenu);

    view->installEventFilter(this);
    tokenView = view;

    // Actions
    QAction *copyAddressAction = new QAction(tr("Copy address"), this);
    QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
    QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this);
    QAction *copyTxPlainText = new QAction(tr("Copy full transaction details"), this);
    QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);

    contextMenu = new QMenu(tokenView);
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyAmountAction);
    contextMenu->addAction(copyTxIDAction);
    contextMenu->addAction(copyTxPlainText);
    contextMenu->addAction(showDetailsAction);

    connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
    connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
    connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString)));
    connect(amountWidget, SIGNAL(textChanged(QString)), this, SLOT(changedAmount(QString)));
    connect(nameWidget, SIGNAL(activated(int)), this, SLOT(chooseName(int)));

    connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
    connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
    connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID()));
    connect(copyTxPlainText, SIGNAL(triggered()), this, SLOT(copyTxPlainText()));
    connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
    connect(tokenView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(showDetails()));
}

void TokenTransactionView::setModel(WalletModel *_model)
{
    this->model = _model;
    if(_model)
    {
        refreshNameWidget();
        connect(model->getTokenItemModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),this, SLOT(addToNameWidget(QModelIndex,int,int)));

        tokenProxyModel = new TokenFilterProxy(this);
        tokenProxyModel->setSourceModel(_model->getTokenTransactionTableModel());
        tokenProxyModel->setDynamicSortFilter(true);
        tokenProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
        tokenProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

        tokenProxyModel->setSortRole(Qt::EditRole);

        tokenView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        tokenView->setModel(tokenProxyModel);
        tokenView->setAlternatingRowColors(true);
        tokenView->setSelectionBehavior(QAbstractItemView::SelectRows);
        tokenView->setSelectionMode(QAbstractItemView::ExtendedSelection);
        tokenView->setSortingEnabled(true);
        tokenView->sortByColumn(TokenTransactionTableModel::Date, Qt::DescendingOrder);
        tokenView->verticalHeader()->hide();

        tokenView->setColumnWidth(TokenTransactionTableModel::Status, STATUS_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Date, DATE_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Type, TYPE_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Name, NAME_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);

        columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tokenView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH, this, 3);
    }
}

QWidget *TokenTransactionView::createDateRangeWidget()
{
    dateRangeWidget = new QFrame();
    dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
    dateRangeWidget->setContentsMargins(1,1,1,1);
    QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
    layout->setContentsMargins(0,0,0,0);
    layout->addSpacing(23);
    layout->addWidget(new QLabel(tr("Range:")));

    dateFrom = new QDateTimeEdit(this);
    dateFrom->setDisplayFormat("dd/MM/yy");
    dateFrom->setCalendarPopup(true);
    dateFrom->setMinimumWidth(100);
    dateFrom->setDate(QDate::currentDate().addDays(-7));
    layout->addWidget(dateFrom);
    layout->addWidget(new QLabel(tr("to")));

    dateTo = new QDateTimeEdit(this);
    dateTo->setDisplayFormat("dd/MM/yy");
    dateTo->setCalendarPopup(true);
    dateTo->setMinimumWidth(100);
    dateTo->setDate(QDate::currentDate());
    layout->addWidget(dateTo);
    layout->addStretch();

    // Hide by default
    dateRangeWidget->setVisible(false);

    // Notify on change
    connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
    connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));

    return dateRangeWidget;
}

void TokenTransactionView::refreshNameWidget()
{
    if(model)
    {
        TokenItemModel *tim = model->getTokenItemModel();
        for(int i = 0; i < tim->rowCount(); i++)
        {
            QString name = tim->data(tim->index(i, 0), TokenItemModel::SymbolRole).toString();
            nameWidget->addItem(name, name);
        }
        nameWidget->setCurrentIndex(0);
    }
}

void TokenTransactionView::addToNameWidget(const QModelIndex &parent, int start, int /*end*/)
{
    if(model)
    {
        TokenItemModel *tim = model->getTokenItemModel();
        QString name = tim->index(start, TokenItemModel::Symbol, parent).data().toString();
        nameWidget->addItem(name, name);
        nameWidget->setCurrentIndex(0);
    }
}

void TokenTransactionView::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    columnResizingFixer->stretchColumnWidth(TokenTransactionTableModel::ToAddress);
}

bool TokenTransactionView::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        if (ke->key() == Qt::Key_C && ke->modifiers().testFlag(Qt::ControlModifier))
        {
            GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::TxPlainTextRole);
            return true;
        }
    }
    return QWidget::eventFilter(obj, event);
}

void TokenTransactionView::contextualMenu(const QPoint &point)
{
    QModelIndex index = tokenView->indexAt(point);
    QModelIndexList selection = tokenView->selectionModel()->selectedRows(0);
    if (selection.empty())
        return;

    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void TokenTransactionView::dateRangeChanged()
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setDateRange(
                QDateTime(dateFrom->date()),
                QDateTime(dateTo->date()).addDays(1));
}

void TokenTransactionView::showDetails()
{
    if(!tokenView->selectionModel())
        return;
    QModelIndexList selection = tokenView->selectionModel()->selectedRows();
    if(!selection.isEmpty())
    {
        TokenDescDialog *dlg = new TokenDescDialog(selection.at(0));
        dlg->setAttribute(Qt::WA_DeleteOnClose);
        dlg->show();
    }
}

void TokenTransactionView::copyAddress()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::AddressRole);
}

void TokenTransactionView::copyAmount()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::AmountRole);
}

void TokenTransactionView::copyTxID()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::TxHashRole);
}

void TokenTransactionView::copyTxPlainText()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::TxPlainTextRole);
}

void TokenTransactionView::chooseDate(int idx)
{
    if(!tokenProxyModel)
        return;
    QDate current = QDate::currentDate();
    dateRangeWidget->setVisible(false);
    switch(dateWidget->itemData(idx).toInt())
    {
    case All:
        tokenProxyModel->setDateRange(
                    TokenFilterProxy::MIN_DATE,
                    TokenFilterProxy::MAX_DATE);
        break;
    case Today:
        tokenProxyModel->setDateRange(
                    QDateTime(current),
                    TokenFilterProxy::MAX_DATE);
        break;
    case ThisWeek: {
        // Find last Monday
        QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
        tokenProxyModel->setDateRange(
                    QDateTime(startOfWeek),
                    TokenFilterProxy::MAX_DATE);

    } break;
    case ThisMonth:
        tokenProxyModel->setDateRange(
                    QDateTime(QDate(current.year(), current.month(), 1)),
                    TokenFilterProxy::MAX_DATE);
        break;
    case LastMonth:
        tokenProxyModel->setDateRange(
                    QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)),
                    QDateTime(QDate(current.year(), current.month(), 1)));
        break;
    case ThisYear:
        tokenProxyModel->setDateRange(
                    QDateTime(QDate(current.year(), 1, 1)),
                    TokenFilterProxy::MAX_DATE);
        break;
    case Range:
        dateRangeWidget->setVisible(true);
        dateRangeChanged();
        break;
    }
}

void TokenTransactionView::chooseType(int idx)
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setTypeFilter(
                typeWidget->itemData(idx).toInt());
}

void TokenTransactionView::chooseName(int idx)
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setName(
                nameWidget->itemData(idx).toString());
}

void TokenTransactionView::changedPrefix(const QString &prefix)
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setAddressPrefix(prefix);
}

void TokenTransactionView::changedAmount(const QString &amount)
{
    if(!tokenProxyModel)
        return;
    int256_t amount_parsed = 0;
    if(BitcoinUnits::parseToken(18, amount, &amount_parsed))
    {
        tokenProxyModel->setMinAmount(amount_parsed);
    }
    else
    {
        tokenProxyModel->setMinAmount(0);
    }
}
<commit_msg>Keep the current token selected when add new<commit_after>#include "tokentransactionview.h"

#include "walletmodel.h"
#include "platformstyle.h"
#include "tokentransactiontablemodel.h"
#include "tokentransactionrecord.h"
#include "tokenfilterproxy.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "tokenitemmodel.h"
#include "tokendescdialog.h"

#include <QComboBox>
#include <QDateTimeEdit>
#include <QDoubleValidator>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QPoint>
#include <QScrollBar>
#include <QTableView>
#include <QVBoxLayout>
#include <QRegularExpressionValidator>

#define paternTokenAmount "^[0-9]{1,59}\\.{1,1}[0-9]{0,18}"

TokenTransactionView::TokenTransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
    QWidget(parent),
    model(0),
    tokenProxyModel(0),
    tokenView(0),
    columnResizingFixer(0)
{
    // Build filter row
    setContentsMargins(0,0,0,0);

    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(0,0,0,0);

    if (platformStyle->getUseExtraSpacing()) {
        hlayout->setSpacing(5);
        hlayout->addSpacing(STATUS_COLUMN_WIDTH + 3);
    } else {
        hlayout->setSpacing(0);
        hlayout->addSpacing(STATUS_COLUMN_WIDTH);
    }

    dateWidget = new QComboBox(this);
    if (platformStyle->getUseExtraSpacing()) {
        dateWidget->setFixedWidth(DATE_COLUMN_WIDTH + 1);
    } else {
        dateWidget->setFixedWidth(DATE_COLUMN_WIDTH);
    }
    dateWidget->addItem(tr("All"), All);
    dateWidget->addItem(tr("Today"), Today);
    dateWidget->addItem(tr("This week"), ThisWeek);
    dateWidget->addItem(tr("This month"), ThisMonth);
    dateWidget->addItem(tr("Last month"), LastMonth);
    dateWidget->addItem(tr("This year"), ThisYear);
    dateWidget->addItem(tr("Range..."), Range);
    hlayout->addWidget(dateWidget);

    typeWidget = new QComboBox(this);
    if (platformStyle->getUseExtraSpacing()) {
        typeWidget->setFixedWidth(TYPE_COLUMN_WIDTH + 1);
    } else {
        typeWidget->setFixedWidth(TYPE_COLUMN_WIDTH);
    }

    typeWidget->addItem(tr("All"), TokenFilterProxy::ALL_TYPES);
    typeWidget->addItem(tr("Received with"), TokenFilterProxy::TYPE(TokenTransactionRecord::RecvWithAddress));
    typeWidget->addItem(tr("Sent to"), TokenFilterProxy::TYPE(TokenTransactionRecord::SendToAddress));
    typeWidget->addItem(tr("To yourself"), TokenFilterProxy::TYPE(TokenTransactionRecord::SendToSelf));
    hlayout->addWidget(typeWidget);

    addressWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    addressWidget->setPlaceholderText(tr("Enter address to search"));
#endif
    hlayout->addWidget(addressWidget);

    nameWidget = new QComboBox(this);
    if (platformStyle->getUseExtraSpacing()) {
        nameWidget->setFixedWidth(NAME_COLUMN_WIDTH + 1);
    } else {
        nameWidget->setFixedWidth(NAME_COLUMN_WIDTH);
    }
    nameWidget->addItem(tr("All"), "");

    hlayout->addWidget(nameWidget);

    amountWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    amountWidget->setPlaceholderText(tr("Min amount"));
#endif
    if (platformStyle->getUseExtraSpacing()) {
        amountWidget->setFixedWidth(AMOUNT_MINIMUM_COLUMN_WIDTH - 3);
    } else {
        amountWidget->setFixedWidth(AMOUNT_MINIMUM_COLUMN_WIDTH);
    }
    QRegularExpression regEx;
    regEx.setPattern(paternTokenAmount);
    QRegularExpressionValidator *validator = new QRegularExpressionValidator(amountWidget);
    validator->setRegularExpression(regEx);
    amountWidget->setValidator(validator);
    hlayout->addWidget(amountWidget);

    QVBoxLayout *vlayout = new QVBoxLayout(this);
    vlayout->setContentsMargins(0,0,0,0);
    vlayout->setSpacing(0);

    QTableView *view = new QTableView(this);
    vlayout->addLayout(hlayout);
    vlayout->addWidget(createDateRangeWidget());
    vlayout->addWidget(view);
    vlayout->setSpacing(0);
    int width = view->verticalScrollBar()->sizeHint().width();
    // Cover scroll bar width with spacing
    if (platformStyle->getUseExtraSpacing()) {
        hlayout->addSpacing(width+2);
    } else {
        hlayout->addSpacing(width);
    }
    // Always show scroll bar
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    view->setTabKeyNavigation(false);
    view->setContextMenuPolicy(Qt::CustomContextMenu);

    view->installEventFilter(this);
    tokenView = view;

    // Actions
    QAction *copyAddressAction = new QAction(tr("Copy address"), this);
    QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
    QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this);
    QAction *copyTxPlainText = new QAction(tr("Copy full transaction details"), this);
    QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);

    contextMenu = new QMenu(tokenView);
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyAmountAction);
    contextMenu->addAction(copyTxIDAction);
    contextMenu->addAction(copyTxPlainText);
    contextMenu->addAction(showDetailsAction);

    connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
    connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
    connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString)));
    connect(amountWidget, SIGNAL(textChanged(QString)), this, SLOT(changedAmount(QString)));
    connect(nameWidget, SIGNAL(activated(int)), this, SLOT(chooseName(int)));

    connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
    connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
    connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID()));
    connect(copyTxPlainText, SIGNAL(triggered()), this, SLOT(copyTxPlainText()));
    connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
    connect(tokenView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(showDetails()));
}

void TokenTransactionView::setModel(WalletModel *_model)
{
    this->model = _model;
    if(_model)
    {
        refreshNameWidget();
        connect(model->getTokenItemModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),this, SLOT(addToNameWidget(QModelIndex,int,int)));

        tokenProxyModel = new TokenFilterProxy(this);
        tokenProxyModel->setSourceModel(_model->getTokenTransactionTableModel());
        tokenProxyModel->setDynamicSortFilter(true);
        tokenProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
        tokenProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

        tokenProxyModel->setSortRole(Qt::EditRole);

        tokenView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        tokenView->setModel(tokenProxyModel);
        tokenView->setAlternatingRowColors(true);
        tokenView->setSelectionBehavior(QAbstractItemView::SelectRows);
        tokenView->setSelectionMode(QAbstractItemView::ExtendedSelection);
        tokenView->setSortingEnabled(true);
        tokenView->sortByColumn(TokenTransactionTableModel::Date, Qt::DescendingOrder);
        tokenView->verticalHeader()->hide();

        tokenView->setColumnWidth(TokenTransactionTableModel::Status, STATUS_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Date, DATE_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Type, TYPE_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Name, NAME_COLUMN_WIDTH);
        tokenView->setColumnWidth(TokenTransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);

        columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tokenView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH, this, 3);
    }
}

QWidget *TokenTransactionView::createDateRangeWidget()
{
    dateRangeWidget = new QFrame();
    dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
    dateRangeWidget->setContentsMargins(1,1,1,1);
    QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
    layout->setContentsMargins(0,0,0,0);
    layout->addSpacing(23);
    layout->addWidget(new QLabel(tr("Range:")));

    dateFrom = new QDateTimeEdit(this);
    dateFrom->setDisplayFormat("dd/MM/yy");
    dateFrom->setCalendarPopup(true);
    dateFrom->setMinimumWidth(100);
    dateFrom->setDate(QDate::currentDate().addDays(-7));
    layout->addWidget(dateFrom);
    layout->addWidget(new QLabel(tr("to")));

    dateTo = new QDateTimeEdit(this);
    dateTo->setDisplayFormat("dd/MM/yy");
    dateTo->setCalendarPopup(true);
    dateTo->setMinimumWidth(100);
    dateTo->setDate(QDate::currentDate());
    layout->addWidget(dateTo);
    layout->addStretch();

    // Hide by default
    dateRangeWidget->setVisible(false);

    // Notify on change
    connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
    connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));

    return dateRangeWidget;
}

void TokenTransactionView::refreshNameWidget()
{
    if(model)
    {
        TokenItemModel *tim = model->getTokenItemModel();
        for(int i = 0; i < tim->rowCount(); i++)
        {
            QString name = tim->data(tim->index(i, 0), TokenItemModel::SymbolRole).toString();
            nameWidget->addItem(name, name);
        }
    }
}

void TokenTransactionView::addToNameWidget(const QModelIndex &parent, int start, int /*end*/)
{
    if(model)
    {
        TokenItemModel *tim = model->getTokenItemModel();
        QString name = tim->index(start, TokenItemModel::Symbol, parent).data().toString();
        nameWidget->addItem(name, name);
    }
}

void TokenTransactionView::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    columnResizingFixer->stretchColumnWidth(TokenTransactionTableModel::ToAddress);
}

bool TokenTransactionView::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        if (ke->key() == Qt::Key_C && ke->modifiers().testFlag(Qt::ControlModifier))
        {
            GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::TxPlainTextRole);
            return true;
        }
    }
    return QWidget::eventFilter(obj, event);
}

void TokenTransactionView::contextualMenu(const QPoint &point)
{
    QModelIndex index = tokenView->indexAt(point);
    QModelIndexList selection = tokenView->selectionModel()->selectedRows(0);
    if (selection.empty())
        return;

    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void TokenTransactionView::dateRangeChanged()
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setDateRange(
                QDateTime(dateFrom->date()),
                QDateTime(dateTo->date()).addDays(1));
}

void TokenTransactionView::showDetails()
{
    if(!tokenView->selectionModel())
        return;
    QModelIndexList selection = tokenView->selectionModel()->selectedRows();
    if(!selection.isEmpty())
    {
        TokenDescDialog *dlg = new TokenDescDialog(selection.at(0));
        dlg->setAttribute(Qt::WA_DeleteOnClose);
        dlg->show();
    }
}

void TokenTransactionView::copyAddress()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::AddressRole);
}

void TokenTransactionView::copyAmount()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::AmountRole);
}

void TokenTransactionView::copyTxID()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::TxHashRole);
}

void TokenTransactionView::copyTxPlainText()
{
    GUIUtil::copyEntryData(tokenView, 0, TokenTransactionTableModel::TxPlainTextRole);
}

void TokenTransactionView::chooseDate(int idx)
{
    if(!tokenProxyModel)
        return;
    QDate current = QDate::currentDate();
    dateRangeWidget->setVisible(false);
    switch(dateWidget->itemData(idx).toInt())
    {
    case All:
        tokenProxyModel->setDateRange(
                    TokenFilterProxy::MIN_DATE,
                    TokenFilterProxy::MAX_DATE);
        break;
    case Today:
        tokenProxyModel->setDateRange(
                    QDateTime(current),
                    TokenFilterProxy::MAX_DATE);
        break;
    case ThisWeek: {
        // Find last Monday
        QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
        tokenProxyModel->setDateRange(
                    QDateTime(startOfWeek),
                    TokenFilterProxy::MAX_DATE);

    } break;
    case ThisMonth:
        tokenProxyModel->setDateRange(
                    QDateTime(QDate(current.year(), current.month(), 1)),
                    TokenFilterProxy::MAX_DATE);
        break;
    case LastMonth:
        tokenProxyModel->setDateRange(
                    QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)),
                    QDateTime(QDate(current.year(), current.month(), 1)));
        break;
    case ThisYear:
        tokenProxyModel->setDateRange(
                    QDateTime(QDate(current.year(), 1, 1)),
                    TokenFilterProxy::MAX_DATE);
        break;
    case Range:
        dateRangeWidget->setVisible(true);
        dateRangeChanged();
        break;
    }
}

void TokenTransactionView::chooseType(int idx)
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setTypeFilter(
                typeWidget->itemData(idx).toInt());
}

void TokenTransactionView::chooseName(int idx)
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setName(
                nameWidget->itemData(idx).toString());
}

void TokenTransactionView::changedPrefix(const QString &prefix)
{
    if(!tokenProxyModel)
        return;
    tokenProxyModel->setAddressPrefix(prefix);
}

void TokenTransactionView::changedAmount(const QString &amount)
{
    if(!tokenProxyModel)
        return;
    int256_t amount_parsed = 0;
    if(BitcoinUnits::parseToken(18, amount, &amount_parsed))
    {
        tokenProxyModel->setMinAmount(amount_parsed);
    }
    else
    {
        tokenProxyModel->setMinAmount(0);
    }
}
<|endoftext|>


<commit_before>#define _USE_MATH_DEFINES
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#include <math.h>

#include "../mumble_plugin.h"

HANDLE h = NULL;

static DWORD getProcess(const wchar_t *exename) {
	PROCESSENTRY32 pe;
	DWORD pid = 0;

	pe.dwSize = sizeof(pe);
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnap != INVALID_HANDLE_VALUE) {
		BOOL ok = Process32First(hSnap, &pe);

		while (ok) {
			if (wcscmp(pe.szExeFile, exename)==0) {
				pid = pe.th32ProcessID;
				break;
			}
			ok = Process32Next(hSnap, &pe);
		}
		CloseHandle(hSnap);
	}
	return pid;
}

static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
	MODULEENTRY32 me;
	BYTE *addr = NULL;
	me.dwSize = sizeof(me);
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
	if (hSnap != INVALID_HANDLE_VALUE) {
		BOOL ok = Module32First(hSnap, &me);

		while (ok) {
			if (wcscmp(me.szModule, modname)==0) {
				addr = me.modBaseAddr;
				break;
			}
			ok = Module32Next(hSnap, &me);
		}
		CloseHandle(hSnap);
	}
	return addr;
}

static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
	SIZE_T r;
	BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
	return (ok && (r == len));
}

static void about(HWND h) {
	::MessageBox(h, L"Reads audio position information from Call of Duty: Modern Warfare 2 Special Ops(v1.0)", L"Mumble CoDMW2SO Plugin", MB_OK);
}

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
	float viewHor, viewVer;
	char state;
	char specops;

	for (int i=0;i<3;i++)
		avatar_pos[i]=avatar_front[i]=avatar_top[i]=0.0f;

	bool ok;
	bool so;

	/*
		This plugin uses the following Variables:

			Address			Type	Description
			===================================
			0x00786A64		float	Z-Coordinate
			0x00786A68		float	X-Coordinate
			0x00786A6C		float	Y-Coordinate
			0x00786A34		float	Horizontal view (degrees)
			0x00786A30		float	Vertical view (degrees)

			0x007588C4		byte	Magical state value
	*/

	so = peekProc((BYTE *) 0x00935207, &specops, 1); // Magical state value
		if (! so)
		return false;

	//	if (specops != 0)
	//	return false; // 0 value indicates you are playing Special Ops

	ok = peekProc((BYTE *) 0x01597682, &state, 1); // Magical state value
		if (! ok)
		return false;

	// /*
	//	state value is:
	//	0		while not in game
	//	4		while playing

	//	This value is used for disabling pa for spectators
	//	or people not on a server.
	// */

		if (state != 4)
		return true; // This results in all vectors beeing zero which tells mumble to ignore them.

	ok = peekProc((BYTE *) 0x00786A64, avatar_pos+2, 4) &&	//Z
	     peekProc((BYTE *) 0x00786A68, avatar_pos, 4) &&	//X
	     peekProc((BYTE *) 0x00786A6C, avatar_pos+1, 4) && //Y
	     peekProc((BYTE *) 0x00786A34, &viewHor, 4) && //Hor
	     peekProc((BYTE *) 0x00786A30, &viewVer, 4); //Ver

	if (! ok)
		return false;

	// Scale Coordinates
	/*
	   Z-Value is increasing when heading north
				  decreasing when heading south
	   X-Value is increasing when heading west
				  decreasing when heading east
	   Y-Value is increasing when going up
				  decreasing when going down
	   40 units = 1 meter (not confirmed)
	*/
	for (int i=0;i<3;i++)
		avatar_pos[i]/=40.0f; // Scale to meters
	avatar_pos[0]*=(-1.0f); // Convert right to left handed

	avatar_top[2] = -1; // Head movement is in front vector

	// Calculate view unit vector
	/*
	   Vertical view 0 when centered
					85	when looking down
				   275 when looking up
	   Decreasing when looking up.

	   Horizontal is 0 when facing North
					90 when facing West
				   180 when facing South
				   270 when facing East
	   Increasing when turning left.
	*/
	viewVer *= static_cast<float>(M_PI / 180.0f);
	viewHor *= static_cast<float>(M_PI / 180.0f);

	avatar_front[0] = -sin(viewHor) * cos(viewVer);
	avatar_front[1] = -sin(viewVer);
	avatar_front[2] = cos(viewHor) * cos(viewVer);

	for (int i=0;i<3;i++) {
		camera_pos[i] = avatar_pos[i];
		camera_front[i] = avatar_front[i];
		camera_top[i] = avatar_top[i];
	}

	return ok;
}

static int trylock() {
	h = NULL;
	DWORD pid=getProcess(L"iw4sp.exe");
	if (!pid)
		return false;

	BYTE *mod=getModuleAddr(pid, L"iw4sp.exe");
	if (!mod)
		return false;

	// char sMagic[11];
	// if (!peekProc(mod + 0x01591E52, sMagic, 11) || strncmp("SPECIALOPS", sMagic, 11)!=0)
	//	return false;

	h=OpenProcess(PROCESS_VM_READ, false, pid);
	if (!h)
		return false;

	float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
	std::string context;
	std::wstring identity;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity))
		return true;

	CloseHandle(h);
	h = NULL;
	return false;
}

static void unlock() {
	if (h) {
		CloseHandle(h);
		h = NULL;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports Call of Duty: Modern Warfare 2 Special Ops v1.0 only. No context or identity support yet.");
}

static std::wstring description(L"Call of Duty: Modern Warfare 2 Special Ops v1.0");
static std::wstring shortname(L"Call of Duty: Modern Warfare 2 Special Ops");

static MumblePlugin codmw2soplug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	about,
	NULL,
	trylock,
	unlock,
	longdesc,
	fetch
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &codmw2soplug;
}
<commit_msg>Fix CoDMW2SO state value<commit_after>#define _USE_MATH_DEFINES
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#include <math.h>

#include "../mumble_plugin.h"

HANDLE h = NULL;

static DWORD getProcess(const wchar_t *exename) {
	PROCESSENTRY32 pe;
	DWORD pid = 0;

	pe.dwSize = sizeof(pe);
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnap != INVALID_HANDLE_VALUE) {
		BOOL ok = Process32First(hSnap, &pe);

		while (ok) {
			if (wcscmp(pe.szExeFile, exename)==0) {
				pid = pe.th32ProcessID;
				break;
			}
			ok = Process32Next(hSnap, &pe);
		}
		CloseHandle(hSnap);
	}
	return pid;
}

static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
	MODULEENTRY32 me;
	BYTE *addr = NULL;
	me.dwSize = sizeof(me);
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
	if (hSnap != INVALID_HANDLE_VALUE) {
		BOOL ok = Module32First(hSnap, &me);

		while (ok) {
			if (wcscmp(me.szModule, modname)==0) {
				addr = me.modBaseAddr;
				break;
			}
			ok = Module32Next(hSnap, &me);
		}
		CloseHandle(hSnap);
	}
	return addr;
}

static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
	SIZE_T r;
	BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
	return (ok && (r == len));
}

static void about(HWND h) {
	::MessageBox(h, L"Reads audio position information from Call of Duty: Modern Warfare 2 Special Ops(v1.0)", L"Mumble CoDMW2SO Plugin", MB_OK);
}

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
	float viewHor, viewVer;
	char state;
	char specops;

	for (int i=0;i<3;i++)
		avatar_pos[i]=avatar_front[i]=avatar_top[i]=0.0f;

	bool ok;
	bool so;

	/*
		This plugin uses the following Variables:

			Address			Type	Description
			===================================
			0x00786A64		float	Z-Coordinate
			0x00786A68		float	X-Coordinate
			0x00786A6C		float	Y-Coordinate
			0x00786A34		float	Horizontal view (degrees)
			0x00786A30		float	Vertical view (degrees)

			0x01597682		byte	Magical state value
	*/

	so = peekProc((BYTE *) 0x01974920, &specops, 1); // Magical state value
		if (! so)
		return false;

		if (specops != 2)
		return false; // 2 value indicates you are playing Special Ops

	ok = peekProc((BYTE *) 0x01597682, &state, 1); // Magical state value
		if (! ok)
		return false;

	// /*
	//	state value is:
	//	0		while not in game
	//	4		while playing

	//	This value is used for disabling pa for spectators
	//	or people not on a server.
	// */

		if (state != 4)
		return true; // This results in all vectors beeing zero which tells mumble to ignore them.

	ok = peekProc((BYTE *) 0x00786A64, avatar_pos+2, 4) &&	//Z
	     peekProc((BYTE *) 0x00786A68, avatar_pos, 4) &&	//X
	     peekProc((BYTE *) 0x00786A6C, avatar_pos+1, 4) && //Y
	     peekProc((BYTE *) 0x00786A34, &viewHor, 4) && //Hor
	     peekProc((BYTE *) 0x00786A30, &viewVer, 4); //Ver

	if (! ok)
		return false;

	// Scale Coordinates
	/*
	   Z-Value is increasing when heading north
				  decreasing when heading south
	   X-Value is increasing when heading west
				  decreasing when heading east
	   Y-Value is increasing when going up
				  decreasing when going down
	   40 units = 1 meter (not confirmed)
	*/
	for (int i=0;i<3;i++)
		avatar_pos[i]/=40.0f; // Scale to meters
	avatar_pos[0]*=(-1.0f); // Convert right to left handed

	avatar_top[2] = -1; // Head movement is in front vector

	// Calculate view unit vector
	/*
	   Vertical view 0 when centered
					85	when looking down
				   275 when looking up
	   Decreasing when looking up.

	   Horizontal is 0 when facing North
					90 when facing West
				   180 when facing South
				   270 when facing East
	   Increasing when turning left.
	*/
	viewVer *= static_cast<float>(M_PI / 180.0f);
	viewHor *= static_cast<float>(M_PI / 180.0f);

	avatar_front[0] = -sin(viewHor) * cos(viewVer);
	avatar_front[1] = -sin(viewVer);
	avatar_front[2] = cos(viewHor) * cos(viewVer);

	for (int i=0;i<3;i++) {
		camera_pos[i] = avatar_pos[i];
		camera_front[i] = avatar_front[i];
		camera_top[i] = avatar_top[i];
	}

	return ok;
}

static int trylock() {
	h = NULL;
	DWORD pid=getProcess(L"iw4sp.exe");
	if (!pid)
		return false;

	h=OpenProcess(PROCESS_VM_READ, false, pid);
	if (!h)
		return false;

	float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
	std::string context;
	std::wstring identity;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity))
		return true;

	CloseHandle(h);
	h = NULL;
	return false;
}

static void unlock() {
	if (h) {
		CloseHandle(h);
		h = NULL;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports Call of Duty: Modern Warfare 2 Special Ops v1.0 only. No context or identity support yet.");
}

static std::wstring description(L"Call of Duty: Modern Warfare 2 Special Ops v1.0");
static std::wstring shortname(L"Call of Duty: Modern Warfare 2 Special Ops");

static MumblePlugin codmw2soplug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	about,
	NULL,
	trylock,
	unlock,
	longdesc,
	fetch
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &codmw2soplug;
}
<|endoftext|>