2021-09-20 18:20:01 +02:00

166 lines
5.4 KiB
C#

/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using dnlib.DotNet;
using dnSpy.Contracts.MVVM;
namespace dnSpy.AsmEditor.DnlibDialogs {
enum CharSet {
NotSpec = (int)PInvokeAttributes.CharSetNotSpec >> 1,
Ansi = (int)PInvokeAttributes.CharSetAnsi >> 1,
Unicode = (int)PInvokeAttributes.CharSetUnicode >> 1,
Auto = (int)PInvokeAttributes.CharSetAuto >> 1,
}
enum BestFit {
UseAssem = (int)PInvokeAttributes.BestFitUseAssem >> 4,
Enabled = (int)PInvokeAttributes.BestFitEnabled >> 4,
Disabled = (int)PInvokeAttributes.BestFitDisabled >> 4,
}
enum ThrowOnUnmappableChar {
UseAssem = (int)PInvokeAttributes.ThrowOnUnmappableCharUseAssem >> 12,
Enabled = (int)PInvokeAttributes.ThrowOnUnmappableCharEnabled >> 12,
Disabled = (int)PInvokeAttributes.ThrowOnUnmappableCharDisabled >> 12,
}
enum CallConv {
Winapi = (int)PInvokeAttributes.CallConvWinapi >> 8,
Cdecl = (int)PInvokeAttributes.CallConvCdecl >> 8,
Stdcall = (int)PInvokeAttributes.CallConvStdcall >> 8,
Thiscall = (int)PInvokeAttributes.CallConvThiscall >> 8,
Fastcall = (int)PInvokeAttributes.CallConvFastcall >> 8,
}
sealed class ImplMapVM : ViewModelBase {
static readonly EnumVM[] charSetList = EnumVM.Create(typeof(DnlibDialogs.CharSet));
public EnumListVM CharSet { get; } = new EnumListVM(charSetList);
static readonly EnumVM[] bestFitList = EnumVM.Create(typeof(DnlibDialogs.BestFit));
public EnumListVM BestFit { get; } = new EnumListVM(bestFitList);
static readonly EnumVM[] throwOnUnmappableCharList = EnumVM.Create(typeof(DnlibDialogs.ThrowOnUnmappableChar));
public EnumListVM ThrowOnUnmappableChar { get; } = new EnumListVM(throwOnUnmappableCharList);
static readonly EnumVM[] callConvList = EnumVM.Create(typeof(DnlibDialogs.CallConv));
public EnumListVM CallConv { get; } = new EnumListVM(callConvList);
public bool IsEnabled {
get => isEnabled;
set {
if (isEnabled != value) {
isEnabled = value;
OnPropertyChanged(nameof(IsEnabled));
}
}
}
bool isEnabled = true;
public string Name {
get => name;
set {
if (name != value) {
name = value;
OnPropertyChanged(nameof(Name));
}
}
}
string name = string.Empty;
public string? ModuleName {
get => moduleName;
set {
if (moduleName != value) {
moduleName = value;
OnPropertyChanged(nameof(ModuleName));
}
}
}
string? moduleName = string.Empty;
public PInvokeAttributes Attributes {
get {
var mask = PInvokeAttributes.CharSetMask |
PInvokeAttributes.BestFitMask |
PInvokeAttributes.ThrowOnUnmappableCharMask |
PInvokeAttributes.CallConvMask;
return (attributes & ~mask) |
(PInvokeAttributes)((int)(DnlibDialogs.CharSet)CharSet.SelectedItem! << 1) |
(PInvokeAttributes)((int)(DnlibDialogs.BestFit)BestFit.SelectedItem! << 4) |
(PInvokeAttributes)((int)(DnlibDialogs.ThrowOnUnmappableChar)ThrowOnUnmappableChar.SelectedItem! << 12) |
(PInvokeAttributes)((int)(DnlibDialogs.CallConv)CallConv.SelectedItem! << 8);
}
set {
if (attributes != value) {
attributes = value;
OnPropertyChanged(nameof(Attributes));
OnPropertyChanged(nameof(NoMangle));
OnPropertyChanged(nameof(SupportsLastError));
}
}
}
PInvokeAttributes attributes;
public bool NoMangle {
get => GetFlagValue(PInvokeAttributes.NoMangle);
set => SetFlagValue(PInvokeAttributes.NoMangle, value);
}
public bool SupportsLastError {
get => GetFlagValue(PInvokeAttributes.SupportsLastError);
set => SetFlagValue(PInvokeAttributes.SupportsLastError, value);
}
bool GetFlagValue(PInvokeAttributes flag) => (Attributes & flag) != 0;
void SetFlagValue(PInvokeAttributes flag, bool value) {
if (value)
Attributes |= flag;
else
Attributes &= ~flag;
}
public ImplMap? ImplMap {
get {
if (!IsEnabled)
return null;
var modRef = ModuleName is null ? null : ownerModule.UpdateRowId(new ModuleRefUser(ownerModule, ModuleName));
return ownerModule.UpdateRowId(new ImplMapUser(modRef, Name, Attributes));
}
set {
IsEnabled = value is not null;
if (value is null)
return;
Name = value.Name;
Attributes = value.Attributes;
ModuleName = value.Module?.Name;
CharSet.SelectedItem = (DnlibDialogs.CharSet)((int)(value.Attributes & PInvokeAttributes.CharSetMask) >> 1);
BestFit.SelectedItem = (DnlibDialogs.BestFit)((int)(value.Attributes & PInvokeAttributes.BestFitMask) >> 4);
ThrowOnUnmappableChar.SelectedItem = (DnlibDialogs.ThrowOnUnmappableChar)((int)(value.Attributes & PInvokeAttributes.ThrowOnUnmappableCharMask) >> 12);
CallConv.SelectedItem = (DnlibDialogs.CallConv)((int)(value.Attributes & PInvokeAttributes.CallConvMask) >> 8);
}
}
readonly ModuleDef ownerModule;
public ImplMapVM(ModuleDef ownerModule) => this.ownerModule = ownerModule;
}
}